这篇是以极大疑惑为驱动的文章,综合了大多数文章对USB权限申请的常规方法,及特殊操作。带着这样的疑惑来看这篇文章:为什么部分机型在硬件连接手机时没有任何的权限请求提示框呢?
修改AndroidManifest.xml
<uses-feature android:name="android.hardware.usb.host" /> <uses-feature android:name="android.hardware.usb.accessory" />在<actvity>主类添加
<activity android:name="MainActivity" android:exported="true" android:label="@string/title" android:screenOrientation="portrait" android:theme="@style/AppTheme.NoActionBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <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>其中的@xml/device_filter在res中添加xml目录,并新建device_filter,并在其中添加以下代码,其中的设备号等参数需要自己对照USB设备的参数。
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-device vendor-id="6790" product-id="29987" /> </resources>
以上第一步就是对主动申请的准备工作,接下来进入主动申请的步骤
1.首先需要检测usb设备,并过滤intent
UsbManager mUsbManager; private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; 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 permission for (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); } //} } }2.注册广播监听权限是否通过
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 if(null != usbDevice){ //do something after get usbDevice } } else { //user choose NO for your previously popup window asking for grant perssion for this usb device Toast.makeText(context, String.valueOf("Permission denied for device" + usbDevice), Toast.LENGTH_LONG).show(); } } } } };以上就是动态申请的全部内容。
但是步骤二对多数场景的使用特别不友好,特别是远程维护的安卓设备在每次断电之后都会重新加载usb设备,此时弹框将阻碍设备的正常运行。这时就需要绕开弹框,从framework层着手。
找到源码/android/frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
//setupAlert();//不使用窗口 mPermissionGranted = true; finish();注释掉设置弹框的代码,当然也可以按包名定制是否需要弹框确认。
如果,按照常规操作,并不能顺利地申请到usb权限,你会有怎样的思考呢?现象就是部分机型上有弹框出现,部分机型上没有弹框出现。这个问题的解答,直到阅读到这样一篇文章,如下
而给出的解决方法就是将android项目中的所有targetSdkVersion统一为27及以下,注意仅仅是targetSDKVersion,其他的设置可以不变,而究竟为什么要这样做,我个人认为可能是官方的刻意限制,不同版本的SDK在usb权限申请弹框上有差异。