Android USB 开发详解

2023-05-16

Android USB 开发详解

先附上 Android USB 官方文档

Android通过两种模式支持各种 USB 外设和 Android USB 附件(实现Android附件协议的硬件):USB附件和USB主机。USB开发需 Android 3.1(API级别12)以上。由于本人工作中只用到了主机模式,所以本文的侧重点在主机模式开发。

  • Android USB 开发详解
    • 调试
    • 一、AndroidManifest 文件设置
    • 二、USB 设备的连接和使用
      • 1.Android 中的 USB
      • 2.USB 设备的插入
      • 3.获取 UsbManager
      • 4.获取 USB 设备列表
      • 5.获取特定的设备
      • 6.申请 USB 设备使用权限
      • 7.通信
    • 其他

调试

在使用 USB 连接设备调试的时候,USB 外设将不能连接至设备,可以使用 WIFI 的方式连接调试,settings -> plugin -> WiFi ADB 插件好几个,选个适合自己的就 OK。

或者…我这里正好有一篇Android 模拟器连接 USB 设备喜欢点个赞哈!

一、AndroidManifest 文件设置

  • uses-feature 申明这个软件需要使用 USB 功能,申明这个 Google Play 会把不满足的设备过滤掉,一般用 USB 的都是定制开发,忽略就行
<uses-feature android:name="android.hardware.usb.host"/>
  • 1
  • 将应用程序的最低SDK设置为API级别12或更高,早期 API 没有。
  • 如果你希望你的应用程序连接指定的 USB 设备时被通知,需指定 和 元素对用于 android.hardware.usb.action.USB_DEVICE_ATTACHED。该 元素指向声明识别有关您要检测的设备信息的外部XML资源文件。
<activity
            android:name=".MainActivity"
            android:screenOrientation="landscape">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <!-- 如果这里是启动 Activity 的话,点击 USB 接入的弹窗会启动该页面 -->
                <category android:name="android.intent.category.LAUNCHER" />
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>
            <meta-data
                android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/device_filter" />
        </activity>
  • 在XML资源文件中,声明要过滤的USB设备的元素。以下列表描述了属性 。通常,如果要过滤特定设备并使用类,子类和协议(如果要过滤一组USB设备(如大容量存储设备或数码相机)),请使用供应商(vendor-id)和产品(product-id)ID,在开发中这些过滤ID一般可以在文档中找到,或者自己连上看也行。你可以指定部分或全部这些属性。 
    将资源文件保存在res/xml/目录中。资源文件名(不带.xml扩展名)必须与您在元素中指定的文件名相同 。对于XML资源文件格式的 例子如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <usb-device
        class="255"
        product-id="5678"
        protocol="1 "
        subclass="66"
        vendor-id="1234" />
</resources>

 

配置好清单文件后当用户连接与您的设备过滤器匹配的设备时,系统会向他们显示一个对话框,询问他们是否要启动您的应用程序。如果用户接受,则应用程序将自动具有访问设备的权限,直到设备断开连接。如果给了默认,那么这个 USB 设备插入后会自动启动这个 Activity

image

二、USB 设备的连接和使用

在清单文件中配置好以后我们直接进入 Java 代码环节

1.Android 中的 USB

Android 3.1(API级别12)以上原生提供了 USB 开发的 API,在android.hardware.usb包下提供了开发的相关类。

Class说明
UsbManager获得 USB 管理器,与连接的 USB 设备通信。
UsbDeviceUSB 设备的抽象,每个UsbDevice 都代表一个 USB 设备。
UsbInterface定义了设备的功能集,一个 UsbDevice 可能包含一个或多个UsbInterface,每个 Interface 都是独立的。
UsbEndpointUsbEndpoint 是 interface 的通信通道。
UsbDeviceConnectionhost 与 device 建立的连接,并在 endpoint 传输数据。
UsbRequestUSB 请求包。
UsbConstantsUSB 常量的定义

2.USB 设备的插入

Android 系统中,USB 设备的插入和拔出是以系统广播的形式发送的,我们只要注册监听这个广播就好

public class USBReceiver extends BroadcastReceiver {
    public static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (ACTION_USB_PERMISSION.equals(action)) {
            // 获取权限结果的广播
            synchronized (this) {
                UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (device != null) {
                    //call method to set up device communication
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        Log.e("USBReceiver", "获取权限成功:" + device.getDeviceName());
                    } else {
                        Log.e("USBReceiver", "获取权限失败:" + device.getDeviceName());
                    }
                }
            }
        }else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
            // 有新的设备插入了,在这里一般会判断这个设备是不是我们想要的,是的话就去请求权限
        } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
            // 有设备拔出了
        }
    }
}

 

3.获取 UsbManager

usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);

4.获取 USB 设备列表

    public List<UsbDevice> getDeviceList() {
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
        List<UsbDevice> usbDevices = new ArrayList<>();
        while (deviceIterator.hasNext()) {
            UsbDevice device = deviceIterator.next();
            usbDevices.add(device);
            Log.e("USBUtil", "getDeviceList: " + device.getDeviceName());
        }
        return usbDevices;
    }

 

5.获取特定的设备

    /**
     * mVendorId=1137,mProductId=85  佳博 3150T 标签打印机
     *
     * @param vendorId  厂商ID
     * @param productId 产品ID
     * @return  device
     */
    public UsbDevice getUsbDevice(int vendorId, int productId) {
        HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
        while (deviceIterator.hasNext()) {
            UsbDevice device = deviceIterator.next();
            if (device.getVendorId() == vendorId && device.getProductId() == productId) {
                Log.e("USBUtil", "getDeviceList: " + device.getDeviceName());
                return device;
            }
        }
        Toast.makeText(context, "没有对应的设备", Toast.LENGTH_SHORT).show();
        return null;
    }

6.申请 USB 设备使用权限

安卓系统对 USB 设备的使用需要得到相应的权限,这个权限要用户手动授予,或插入设备时应用到你的应用中。在使用 USB 设备前首先我们要确认一下上一节中的device是否已经获得权限,如果没有就要主动申请权限:

    /**
     * 判断对应 USB 设备是否有权限
     */
    public boolean hasPermission(UsbDevice device) {
        return usbManager.hasPermission(device);
    }

    /**
     * 请求获取指定 USB 设备的权限
     */
    public void requestPermission(UsbDevice device) {
        if (device != null) {
            if (usbManager.hasPermission(device)) {
                Toast.makeText(context, "已经获取到权限", Toast.LENGTH_SHORT).show();
            } else {
                if (mPermissionIntent != null) {
                    usbManager.requestPermission(device, mPermissionIntent);
                    Toast.makeText(context, "请求USB权限", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(context, "请注册USB广播", Toast.LENGTH_LONG).show();
                }
            }
        }
    }

 

注册广播:

    public void registerReceiver(Activity context) {
        mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        context.registerReceiver(usbReceiver, filter);
    }

 

7.通信

与 USB 设备的通信可以是同步的也可以是异步的。无论哪种情况,你都应该创建一个新线程来执行所有数据传输,避免阻塞UI线程。

第一步,打开通信端口

    public boolean openPort(UsbDevice device) {
        //获取设备接口,一般只有一个,多个的自己研究去
        usbInterface = device.getInterface(0);

        // 判断是否有权限
        if (hasPermission(device)) {
            // 打开设备,获取 UsbDeviceConnection 对象,连接设备,用于后面的通讯
            usbConnection = usbManager.openDevice(device);

            if (usbConnection == null) {
                return false;
            }
            if (usbConnection.claimInterface(usbInterface, true)) {
                Toast.makeText(Utils.getContext(), "找到 USB 设备接口", Toast.LENGTH_SHORT).show();
            } else {
                usbConnection.close();
                Toast.makeText(Utils.getContext(), "没有找到 USB 设备接口", Toast.LENGTH_SHORT).show();
                return false;
            }
        } else {
            Toast.makeText(Utils.getContext(), "没有 USB 权限", Toast.LENGTH_SHORT).show();
            return false;
        }

        //获取接口上的两个端点,分别对应 OUT 和 IN
        for (int i = 0; i < usbInterface.getEndpointCount(); ++i) {
            UsbEndpoint end = usbInterface.getEndpoint(i);
            if (end.getDirection() == UsbConstants.USB_DIR_IN) {
                usbEndpointIn = end;
            } else {
                usbEndpointOut = end;
            }
        }
        return true;
    }

 

第二步,发送数据

usbConnection.bulkTransfer(usbEndpointOut, bytes, bytes.length, 500);

其他

剩余的 API 我会在项目不断完善的同时更新上来

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android USB 开发详解 的相关文章

随机推荐

  • Android中BroadCastReceiver使用(整理)

    BroadcastReceiver 在Android中 xff0c Broadcast是一种广泛运用的在应用程序之间传输信息的机制 而BroadcastReceiver是对发送出来的 Broadcast进行过滤接受并响应的一类组件 下面将详
  • Android的联通性---USB主机模式(三)

    获取跟设备通信的权限 在跟USB设备进行通信之前 xff0c 你的应用程序必须要获取用户的许可 注意 xff1a 如果你的应用程序使用Intent过滤器来发现接入的USB设备 xff0c 而且用户允许你的应用程序处理该Intent xff0
  • android USB

    google 在推出API 3 0后 就增加啦USB通讯这块 同时为API 2 3提供啦一个USB通讯吧 xff0c 这样也让2 3有啦USB通讯功能 不过只支持USBAccessory模式 USB通讯分为两种模式 xff1a xff08
  • 入门 Kotlin 和 Java 混合开发

    一 前沿 如果你学习过其他的编程语言 xff0c 你就会发现 Java 的语法很是哆嗦 xff0c 可是我们为什么没有放弃 Java 这门编程语言呢 xff1f 因为 JVM 是一个非常好的平台 xff0c 而且 Java 程序员目前在中国
  • kotlin 和java 混编

    如果你之前使用 Java 语言而没有 Kotlin 开发经验 xff0c 不用担心 xff0c Intellij IDEA 会帮你一键转换 xff0c 将 Java 代码转换成 Kotlin 代码 但是反过来就不行了 在 Mac 上 xff
  • Kotlin 基础语法

    Kotlin 文件以 kt 为后缀 包声明 代码文件的开头一般为包的声明 xff1a package com runoob main import java util fun test class Runoob kotlin源文件不需要相匹
  • ‘break‘ not in the ‘loop‘ or ‘switch‘ context

    使用phpexcel导出表格 xff0c 切换到php7 0报错 错误地址 xff1a FILE ThinkPHP Library Vendor phpexcel PHPExcel Calculation Functions php LIN
  • Android数据存储之SQLite

    概览 l 概述 l CRUD方法详解 l 注意事项 概述 对于大量数据的处理 xff0c 如果不想将数据存于服务器端 xff0c Android API提供了对关系数据库SQLite的支持 xff0c 在android SDK中tool目录
  • SQLlite在安卓中的基本详解和简单使用

    一 基础介绍 1 SQLite 是一个进程内的库 是一种轻量级的 自给自足的 无服务器的 无需配置的 事务性的SQL数据库引擎 和他其他的数据库一样 xff0c SQLite引擎不是一个独立的进程 xff0c 可以按应用程序需求进行静态或动
  • android开发中的数据库SQLite的使用

    其实学习android很久了 xff0c 关于数据存储 xff0c 之前学习的时候也一同学习过 xff0c 编程这些东西很久没用都忘得差不多了 xff0c 最近做个项目要用到 xff0c 所以又学习了一遍 android中关于数据的存储有好
  • Android图表控件MPAndroidChart——曲线图LineChart的使用(财富收益图)

    目录 前言 本文涉及文章 其他相关文章 1 数据准备 1 1 数据来源 2 曲线展示 2 1 MPAndroidChart获取 2 2 数据对象获取 2 3 数据展示 3 曲线完善 3 1 图表背景 边框 网格线修改 3 2 X Y轴值的自
  • Android图表控件MPAndroidChart——曲线图LineChart的使用(财富收益图)

    目录 前言 本文涉及文章 其他相关文章 1 数据准备 1 1 数据来源 2 曲线展示 2 1 MPAndroidChart获取 2 2 数据对象获取 2 3 数据展示 3 曲线完善 3 1 图表背景 边框 网格线修改 3 2 X Y轴值的自
  • SQLiteOpenHelper使用详解

    SQLiteOpenHelper 的子类 xff0c 至少需要实现三个方法 xff1a 1 构造函数 调用父类 SQLiteOpenHelper 的构造函数 这个方法需要四个参数 xff1a 上下文环境 xff08 例如 xff0c 一个
  • SQLiteOpenHelper的简单使用

    由于想学习GreenDao框架 xff0c 但是看了一下有的蒙圈 xff0c 所以先熟悉一下android原生的SQLiteOpenHelper的使用工具 xff1a SQLite Expert Personal SQLite Expert
  • android SQLiteOpenHelper 使用

    1 实体 package mydemo mycom demo2 entity public class UserInfo private int id private String username private String passw
  • SQLiteOpenHelper的简单使用

    由于想学习GreenDao框架 xff0c 但是看了一下有的蒙圈 xff0c 所以先熟悉一下android原生的SQLiteOpenHelper的使用 工具 xff1a SQLite Expert Personal SQLite Exper
  • 安卓案例:利用SQLiteOpenHelper操作数据库及表

    安卓案例 xff1a 利用SQLiteOpenHelper操作数据库及表 一 运行效果 二 涉及知识点 1 利用SQLiteOpenHelper类创建与升级数据库 这个类是一个抽象类 xff0c 我们必须继承该类创建一个子类 xff0c 实
  • delphi SimpleGraph控件的部分注释

    TSimpleGraph是一个delphi下的可视化图形开源控件 xff0c 有很强编辑态和运行态编辑功能 是学习开发DELPHI控件的一个很好的例子 控件本身有很强的扩展性 完全可以自定义绘制各种图形 控件的地址为http www del
  • java获取实体类的属性和值

    package com jackie day11 import java lang reflect Field import java lang reflect InvocationTargetException import java l
  • Android USB 开发详解

    Android USB 开发详解 先附上 Android USB 官方文档 Android通过两种模式支持各种 USB 外设和 Android USB 附件 xff08 实现Android附件协议的硬件 xff09 xff1a USB附件和