物联网 - Android系统的USB权限处理

news/2024/10/18 16:54:09/

最近一直在给自己做减法,所以将之前保存的书签和未记录的成长一起整理 - 归纳 - 输出,此处主要记录了在开发售货机app时,因usb权限未开启,从而导致硬件设备的打印功能(USB OTG 通信)无法调用的场景处理。

        • 所遇场景
        • 清单授权
        • 动态授权
        • 兴趣扩展

如果你能看到这篇blog,你可能大概率遇到了USB相关的功能,虽然不一定能解决你的问题,但 可以把它当作一切的开始...

usb权限配置主要有以下俩种方式

  • AndroidMainfest 清单文件 - 静态授权
  • 代码中动态授权 - 6.0之后记得动态权限适配

所遇场景

如果不是因为在售货机中遇到了到了下面usb相关代码的话,我平时开发应该很少能接触到usb ~

    /*** 我看了一下这个方法,整体是判断某个设备的usb是否赋予权限,未授权的话就进行权限申请* */public void usbPermiss(Context context) {UsbManager manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);// 获取设备HashMap<String, UsbDevice> deviceList = manager.getDeviceList();if (deviceList.size() > 0) {Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();// 这里是if不是while,说明我只想支持一种devicewhile (deviceIterator.hasNext()) {final UsbDevice device = deviceIterator.next();//Toast.makeText( this, device.toString(), Toast.LENGTH_SHORT).show();// 官方文档上边是这样写的,直接获取第一个,但往往不一定只连接一个设备,就要求我们找到自己想要的那个,一般的做法是int count = device.getInterfaceCount();for (int i = 0; i < count; i++) {UsbInterface intf = device.getInterface(i);// 之后我们会根据 intf的 getInterfaceClass 判断是哪种类型的Usb设备,// 并且结合 device.getVectorID() 或者厂家ID进行过滤,比如 UsbConstants.USB_CLASS_PRINTERif ((device.getVendorId() == 0x4b43 && device.getProductId() == 0x3538)|| (device.getVendorId() == 0x0FE6 && device.getProductId() == 0x811E)) {// 这个device就是你要找的UsbDevice,此时还需要进行权限判断// 没有权限if (!manager.hasPermission(device)) {String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";PendingIntent mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);manager.requestPermission(device, mPermissionIntent);return;}}}}}}

关于Android USB 授权方式的实现,网上都在熬老汤了,千篇一律,长得都一样,此处直接借鉴、修改,方便理解、使用 ~

清单授权

AndroidMainfest - 在对应的Activity中加入以下配置

    <!-- USB --><intent-filter><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" /><!-- USB END -->

示例

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.rxjava"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.RxJava"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /><action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /><meta-dataandroid:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"android:resource="@xml/device_filter" /></intent-filter></activity></application></manifest>

在读 device_filter 中,要了解usb设备是通过以下俩个属性来一起定义的

  • vendor-id 厂商id
  • product-id 产品id

注意:其中 device_filter 中列出了可用 usb 设备,当usb 设备连接手机之后,app 会自动询问是否允许获取该 usb 的权限。这里有一个 linux 的 usb设备厂商id 和 产品id 的汇总,可以作为 Android usb 设备的参考

<?xml version="1.0" encoding="utf-8"?>
<resources><!-- 0x0403 / 0x6001: FTDI FT232R UART --><usb-device vendor-id="1027" product-id="24577" /><!-- 0x0403 / 0x6015: FTDI FT231X --><usb-device vendor-id="1027" product-id="24597" /><!-- 0x2341 / Arduino --><usb-device vendor-id="9025" /><!-- 0x16C0 / 0x0483: Teensyduino  --><usb-device vendor-id="5824" product-id="1155" /><!-- 0x10C4 / 0xEA60: CP210x UART Bridge --><usb-device vendor-id="4292" product-id="60000" /><!-- 0x067B / 0x2303: Prolific PL2303 --><usb-device vendor-id="1659" product-id="8963" /><!-- 0x1a86 / 0x7523: Qinheng CH340 --><usb-device vendor-id="6790" product-id="29987" />
</resources>

动态授权

USB权限申请(前提是已经定位到要申请USB权限的usbdevice)

    //获取USB设备ACTIONprivate static final String ACTION_USB_PERMISSION = "com.android.usb.USB_PERMISSION";//获取USB设备列表及定位到要申请权限的USB设备
//    UsbManager mUsbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
//    HashMap<String, UsbDevice> devices = mUsbManager.getDeviceList();
//    List<UsbDevice> deviceList = new ArrayList<UsbDevice>();
//    for(UsbDevice device:devices.values()){
//        //获取打印机设备 vid和pid
//        if (3540 == device.getVendorId() && 567 == device.getProductId()) {
//            currentDevice = device;
//        }
//    }//开始申请USB权限private void getUsbPermission(UsbDevice mUSBDevice) {UltraLog.d("开始申请USB权限");PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0);IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);mContext.registerReceiver(mUsbReceiver, filter);// 该代码执行后,系统弹出一个对话框/等待权限mUsbManager.requestPermission(mUSBDevice, pendingIntent); //以下代码是因为在系统层将弹出框直接修改掉了,可以不用
//    long start = System.currentTimeMillis();
//    while (!mUsbManager.hasPermission(mUSBDevice)) {
//        long current = System.currentTimeMillis();
//        if ((current - start) > 3500) {
//            break;
//        }
//        try {
//            Thread.sleep(50);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//    }}

USB广播接受者 - 动态注册

    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {@SuppressLint("NewApi")public void onReceive(Context context, Intent intent) {String action = intent.getAction();if (ACTION_USB_PERMISSION.equals(action)) {synchronized (this) {mContext.unregisterReceiver(mUsbReceiver);UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)&& currentDevice.equals(device)) {//TODO 授权成功,操作USB设备} else {//用户点击拒绝了}}}}};

兴趣扩展

在查usb授权的时候,网上的主流版本就是上方的静态授权和动态授权了,下方也是动态授权的方式,不过走的是英语注释,我脑补了一下中文注释,在此留档,愿对你有所帮助~

    /*** 获得 usb 权限*/private void openUsbDevice() {//before open usb device//should try to get usb permissiontryGetUsbPermission();}UsbManager mUsbManager;private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";//获取USB权限状态private void tryGetUsbPermission() {mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);registerReceiver(mUsbPermissionActionReceiver, filter);PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);//here do emulation to ask all connected usb device for permissionfor (final UsbDevice usbDevice : mUsbManager.getDeviceList().values()) {//add some conditional check if necessary//if(isWeCaredUsbDevice(usbDevice)){if (mUsbManager.hasPermission(usbDevice)) {//if has already got permission, just goto connect it//that means: user has choose yes for your previously popup window asking for grant perssion for this usb device//and also choose option: not ask again//有权限后的处理方式afterGetUsbPermission(usbDevice);} else {//this line will let android popup window, ask user whether to allow this app to have permission to operate this usb device//无权限则申请权限mUsbManager.requestPermission(usbDevice, mPermissionIntent);}//}}}//有usb权限后的执行逻辑private void afterGetUsbPermission(UsbDevice usbDevice) {//call method to set up device communication//Toast.makeText(this, String.valueOf("Got permission for usb device: " + usbDevice), Toast.LENGTH_LONG).show();//Toast.makeText(this, String.valueOf("Found USB device: VID=" + usbDevice.getVendorId() + " PID=" + usbDevice.getProductId()), Toast.LENGTH_LONG).show();doYourOpenUsbDevice(usbDevice);}//开始对应的usb设备private void doYourOpenUsbDevice(UsbDevice usbDevice) {//now follow line will NOT show: User has not given permission to device UsbDeviceUsbDeviceConnection connection = mUsbManager.openDevice(usbDevice);//add your operation code here}//usb权限监听者private final BroadcastReceiver mUsbPermissionActionReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {String action = intent.getAction();if (ACTION_USB_PERMISSION.equals(action)) {synchronized (this) {UsbDevice usbDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {//user choose YES for your previously popup window asking for grant perssion for this usb device//如果有我们usb设备的话,正常执行上方的逻辑就好if (null != usbDevice) {afterGetUsbPermission(usbDevice);}} else {//user choose NO for your previously popup window asking for grant perssion for this usb deviceToast.makeText(context, String.valueOf("Permission denied for device" + usbDevice), Toast.LENGTH_LONG).show();}}}}};

http://www.ppmy.cn/news/182550.html

相关文章

串口通讯的配置

串口以及中断的配置&#xff1a; #if EN_USART1_RX //如果使能了接收 //串口1中断服务程序 //注意,读取USARTx->SR能避免莫名其妙的错误 u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15&#xff0c; 接收完成标志 //b…

unicode和中文互相转换

提示&#xff1a; encode 编码 decode 解码 正文&#xff1a; text 爱你呦‘ # 将中文转换为Unicode编码 text_unicode text.encode(unicode-escape).decode() print(text_unicode) #\u7231\u4f60\u5466 # 将Unicode编码转换为中文 # text_Chinese text_…

【单片机】继电器控制

【单片机】继电器控制 一、操作目的二、操作内容三、预备知识四、操作接线图五、程序清单六、代码详解 一、操作目的 掌握用继电器的基本方法和编程。 二、操作内容 利用P1口输出高低电平,控制继电器的开合,以实现对外部装置的控制。 三、预备知识 现代自动控制设备中都存在一个…

全国地区代码表

天津市 地区代码地区名称1100天津市 辽宁省 地区代码地区名称2210沈阳市2210法库县2210康平县2210辽中县2210新民市2220大连市2222普兰店市2223庄河市2224瓦房店市2225长海县2230鞍山市2231台安县2232海城市2240抚顺市2241抚顺县2242新宾县2243喀左县2250本溪市2251本溪县2252桓…

全国地区代码科普

2019独角兽企业重金招聘Python工程师标准>>> 全国地区代码表 天津市 地区代码 地区名称 1100 天津市 辽宁省 地区代码 地区名称 2210 沈阳市 2210 法库县 2210 康平县 2210 辽中县 2210 新民市 2220 大连市 2222 普兰店市 2223 庄河市 2224 …

I.MX6ull 中断 二 (按键驱动蜂鸣器)

按键中断 KEY0 &#xff08;UART1_CTS 引脚&#xff09;触发蜂鸣器 1 修改start.S 添加中断相关定义 中断向量表 .global _start /* 全局标号 *//** 描述&#xff1a; _start函数&#xff0c;首先是中断向量表的创建* 参考文档:ARM Cortex-A(armV7)编程手册V4.0.pdf P…

ARM NEON优化2.NEON基本数据类型与基本指令集

目录 一. 基本数据类型 1.1 64bit数据类型 1.2 128bit数据类型 1.3 结构化数据类型 二. 基本指令集 2.1 初始化寄存器 vcreate vdup vmov 2.2 加载数据进寄存器 vld vld_lane 2.3 存储寄存器到内存 vst vst_lane 2.4 读取/修改寄存器数据 vget_lane vget_low…

浏览器开发者工具使用实例

开发者工具使用实例 1、查找事件执行函数 举例 F12打开控制台 在 chrome 的控制台的Element选项卡面板里右侧面板有个 Event Listeners&#xff0c;这里会显示你所选择元素的原生事件。原生事件就是元素上直接οnclick"xx"等&#xff0c;如下图。 显示是按事件类型显…