关于Android获取Usb设备权限

本文详细介绍了Android应用如何处理USB设备权限弹窗,包括在Manifest中配置权限、使用device_filter.xml筛选设备、注册BroadcastReceiver监听USB事件,并探讨了HID和camera权限请求的逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、出现权限弹窗:拔插USB设备,弹出权限申请框,通过用户确认或拒绝权限。

二、USB授权方式:(参考google官方文档

1.minfest中进行权限配置

<manifest ...>
        <uses-feature android:name="android.hardware.usb.host" />
        <uses-sdk android:minSdkVersion="12" />
        ...
        <application>
            <activity ...>
                ...
                <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" />
            </activity>
        </application>
    </manifest>

2.res/xml/device_filter.xml 配置文件为需要过滤设备的pid以及vid

<?xml version="1.0" encoding="utf-8"?>
 <resources>
   <usb-device vendor-id="1234" product-id="5678" class="255" subclass="66" protocol="1" />
  </resources>

3.

注册广播以及建立广播接收,当监听到USB的插入动作时,通过UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE)从 Intent 获取代表所连接设备:

匹配是否为目的usb,使用usbManager.requestPermission(device, permissionIntent)获取权限弹窗,进行授权。

.Java代码示例:

    private final String ACTION_USB_PERMISSION = "com.exmple.USB_PERMISSION";
    private static final int VID =1234 ;    
    private static final int PID = 5678;
    private BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
        @RequiresApi(api = Build.VERSION_CODES.KITKAT)
        @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 (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))//是否授权成功
                    {
                        if(device != null){
                            openDevice();
                        }
 
                    }
                    else
                    {
                        Log.e("Rechar","device not permission, device info:" + device.toString());
                    }
                }
            }
            else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action))
            {
                
                UsbDevice device = (UsbDevice) 
                intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                assert device != null;
                if (VID == device.getVendorId() && PID == device.getProductId())
                    {
                        closeDevice();
                        openDeviceAndRequestDevice();
                    }
 
            }
            else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action))
            {
               
                UsbDevice device = (UsbDevice)             
                intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                assert device != null;
                if (VID == device.getVendorId() && PID == device.getProductId())
                    {
                        closeDevice();
                    }
            }
        }
    };
 
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_USB_PERMISSION);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        registerReceiver(mUsbReceiver, filter);//注册广播
    }
 
 
    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        unregisterReceiver(mUsbReceiver);
 
    }
    private void openDeviceAndRequestDevice()
    {
        UsbManager usbManager = (UsbManager)this.getSystemService(Context.USB_SERVICE);
        for (UsbDevice device : usbManager.getDeviceList().values())
        {
            if (device.getVendorId() == VID && device.getProductId() == PID)
            {
                Intent intent = new Intent(ACTION_USB_PERMISSION);//发送自定义广播
                PendingIntent pendingIntent =     
                PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0);
                usbManager.requestPermission(device, pendingIntent);//弹出权限框,进行权限申请
            }
        }
    }
    private void openDevice()
    {
        Log.e("Rechar", "openDevice: " );
        Toast.makeText(this,"openDevice",Toast.LENGTH_LONG).show();
    }
    private void closeDevice()
    {
        Log.e("Rechar", "closeDevice: " );
        Toast.makeText(this,"closeDevice",Toast.LENGTH_LONG).show();
    }
 
 
}

4.以上已完成USB的授权。但在开发过程中发现usb-HID并不能弹出权限框,且自动拒绝了权限。分析了系统源码:先判断USB的权限,若没有会return ,再判断camera的权限若没有回return。因此在代码中加入camera的权限后获取到了权限弹框。系统源码如下:

 public void requestPermission(UsbDevice device, String packageName, PendingIntent pi, int uid) {
      Intent intent = new Intent();
 
        // respond immediately if permission has already been granted
      if (hasPermission(device, packageName, uid)) {
            intent.putExtra(UsbManager.EXTRA_DEVICE, device);
            intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
            try {
                pi.send(mUserContext, 0, intent);
            } catch (PendingIntent.CanceledException e) {
                if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
            }
            return;
        }
        if (isCameraDevicePresent(device)) {
            if (!isCameraPermissionGranted(packageName, uid)) {
                intent.putExtra(UsbManager.EXTRA_DEVICE, device);
                intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
                try {
                    pi.send(mUserContext, 0, intent);
                } catch (PendingIntent.CanceledException e) {
                    if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled");
                }
                return;
            }
        }
 
        // start UsbPermissionActivity so user can choose an activity
        intent.putExtra(UsbManager.EXTRA_DEVICE, device);
        requestPermissionDialog(intent, packageName, pi);
    }

但是我暂时没有想明白,HID和camera的关系所在,系统代码为何这么写,希望知道的大佬指教一下。谢谢!附上当时参考usb流程解析的网站(usb流程解析),为了防止该网站内容被删除,将该内容附在下面以供参考:

USB请求权限流程

1. 新建activity,获取UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE)

2. 获取所以的USB设备HashMap<String, UsbDevice> map = usbManager.getDeviceList()

3. 过滤别的USB设备,拿到自己USB的USBDevice类,然后请求USB权限,usbManager.requestPermission(usbDevice, pendingIntent);并注册一个回调意图,用来判断用户是否授予权限

4. UsbManager类的requestPermission方法会调用mService. requestDevicePermission

5.mService是IUsbManager的对象,而IUsbManager是一个AIDL接口https://www.androidos.net.cn/android/8.0.0_r4/xref/frameworks/base/core/java/android/hardware/usb/IUsbManager.aidl

UsbService是它的实现类,所以最终是调用的UsbService的requestDevicePermission方法

6. 在requestDevicePermission方法里面调用的getSettingsForUser(userId).requestPermission

7. getSettingsForUser(userId)其实是去获取UsbUserSettingsManager实例,所以是调用的UsbUserSettingsManager的requestPermission方法

8. 在requestPermission方法里面首先会进行判断是否拥有USB权限,如果有就回调广播直接return返回的。如果没有那就判断是否有相机权限,如果没有权限回调广播直接return的。注意从始至终是没有发送用户拒绝的广播的

9. 接着会调用自身的requestPermissionDialog方法,在requestPermissionDialog方法里面又会去调用mUsbPermissionManager.requestPermissionDialog方法

10.最终在UsbPermissionManager类的requestPermissionDialog方法中调用startActivityAsUser 启动UsbPermissionActivity权限申请对话框

11.监听弹出权限对话框的onclick方法,如果点击的授权,那就在UsbPermissionActivity的onDestory里面回调最开始的广播,通知我们的应用,用户授予的权限。

 

Android 应用中获取 USB 权限,需要在应用的 AndroidManifest.xml 文件中声明一个 `<uses-feature>` 标签,指定应用需要使用 USB 设备。同时还需要申请 USB 权限,可以在应用中调用 `UsbManager.requestPermission()` 方法来实现。 以下是一个示例代码,演示如何获取 USB 设备权限: ```java // 在AndroidManifest.xml文件中添加以下权限声明 <uses-feature android:name="android.hardware.usb.host" /> // 在应用中获取USB设备权限 public void getUsbPermission(UsbDevice device) { if (device != null) { UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); PendingIntent permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); usbManager.requestPermission(device, permissionIntent); } } // USB设备权限申请结果的广播接收器 private final BroadcastReceiver usbPermissionReceiver = new BroadcastReceiver() { @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 (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { if (device != null) { // 成功获取USB设备权限,可以进行后续操作 } } else { // 未能获取USB设备权限 } } } } }; ``` 注意,获取 USB 设备权限需要用户授权,因此在申请权限之前需要先向用户说明该应用需要使用 USB 设备,以获得用户的同意。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值