Android 屏蔽USB权限弹框 | 您所在的位置:网站首页 › 安卓信息不弹出来 › Android 屏蔽USB权限弹框 |
最近在看Android USB主从设备通讯(下载Demo)相关的东西,调试时每次运行都弹下面的框,即使勾选“默认情况下用于该USB设备”,还是会弹出,在调试阶段频繁弹框影响开发效率。
下面分享下怎么屏蔽USB权限框: 1. 做过相关开发的都见过下面代码 // Check whether we have permission to access the device. if (!mUsbManager.hasPermission(device)) { Intent intent = new Intent(ACTION_USB_DEVICE_PERMISSION); intent.setPackage(getPackageName()); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); mUsbManager.requestPermission(device, pendingIntent); return; } 意思在没有权限的情况下,请求权限才弹的框。2. 分析弹框流程 mUsbManager.requestPermission(UsbDevice device...);//以UsbDevice为例,UsbAccessory同理
a. frameworks/base/core/java/android/hardware/usb/UsbManager.java=>requestPermission public void requestPermission(UsbDevice device, PendingIntent pi) { try { mService.requestDevicePermission(device, mContext.getPackageName(), pi); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }b. frameworks/base/core/java/android/hardware/usb/UsbDevice.java=>requestDevicePermission @Override public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) { final int userId = UserHandle.getCallingUserId(); getSettingsForUser(userId).requestPermission(device, packageName, pi); } getSettingsForUser是 UsbDevice成员函数 private UsbSettingsManager getSettingsForUser(int userId) { synchronized (mLock) { UsbSettingsManager settings = mSettingsByUser.get(userId); if (settings == null) { settings = new UsbSettingsManager(mContext, new UserHandle(userId)); mSettingsByUser.put(userId, settings); } return settings; } } c. frameworks/base/services/java/com/android/server/usb/UsbSettingsManager.java=> requestPermission public void requestPermission(UsbDevice device, String packageName, PendingIntent pi) { Intent intent = new Intent(); // respond immediately if permission has already been granted if (hasPermission(device)) { 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; } // start UsbPermissionActivity so user can choose an activity intent.putExtra(UsbManager.EXTRA_DEVICE, device); requestPermissionDialog(intent, packageName, pi); } 接着调成员函数requestPermissionDialog private void requestPermissionDialog(Intent intent, String packageName, PendingIntent pi) { final int uid = Binder.getCallingUid(); // compare uid with packageName to foil apps pretending to be someone else try { ApplicationInfo aInfo = mPackageManager.getApplicationInfo(packageName, 0); if (aInfo.uid != uid) { throw new IllegalArgumentException("package " + packageName + " does not match caller's uid " + uid); } } catch (PackageManager.NameNotFoundException e) { throw new IllegalArgumentException("package " + packageName + " not found"); } long identity = Binder.clearCallingIdentity(); intent.setClassName("com.android.systemui", "com.android.systemui.usb.UsbPermissionActivity"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(Intent.EXTRA_INTENT, pi); intent.putExtra("package", packageName); intent.putExtra(Intent.EXTRA_UID, uid); try { mUserContext.startActivityAsUser(intent, mUser); } catch (ActivityNotFoundException e) { Slog.e(TAG, "unable to start UsbPermissionActivity"); } finally { Binder.restoreCallingIdentity(identity); } } 由此看最终显示框的地方在SystemUI的UsbPermissionActivity。
3. 屏蔽弹框 a. 看到有博客说在UsbPermissionActivity的onCreate显示Dialog(setupAlert)时替换点击确定的代码 相当于自动点击确定 @Override public void onCreate(Bundle icicle) { ... //setupAlert(); mPermissionGranted = true; finish(); } 或 @Override public void onCreate(Bundle icicle) { ... mAlwaysUse.setOnCheckedChangeListener(this); mAlwaysUse.setChecked(true); ... setupAlert(); onClick(this, AlertDialog.BUTTON_POSITIVE); } 上述两种方法虽然能达到自动授权,个人觉得这种屏蔽方法不理想,下面介绍更好方法。
b. 直接让mUsbManager.hasPermission返回true(自动授权),不更彻底?! 下面列下函数调用关系 ①. frameworks/base/core/java/android/hardware/usb/UsbManager.java=>hasPermission public boolean hasPermission(UsbDevice device) { try { return mService.hasDevicePermission(device); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } ②. frameworks/base/core/java/android/hardware/usb/UsbDevice.java =>hasDevicePermission public boolean hasDevicePermission(UsbDevice device) { final int userId = UserHandle.getCallingUserId(); return getSettingsForUser(userId).hasPermission(device); } ③. frameworks/base/services/java/com/android/server/usb/UsbSettingsManager.java=>hasPermission // Android L(5.x)及之后的版本 public boolean hasPermission(UsbDevice device) { synchronized (mLock) { int uid = Binder.getCallingUid(); if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) { return true; } SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName()); if (uidList == null) { return false; } return uidList.get(uid); } }让条件(uid == Process.SYSTEM_UID || mDisablePermissionDialogs)为真即可 第一种方式:在AndroidManifest.xml里加上android:sharedUserId="android.uid.system",但是apk需打系统签名 第二种方式:让mDisablePermissionDialogs为真 mDisablePermissionDialogs = context.getResources().getBoolean( com.android.internal.R.bool.config_disableUsbPermissionDialogs); frameworks/base/core/res/res/values/config.xml true 哈哈,看看上面注释,这么改会引起CTS fail,这就看你的项目是否要过CTS了// Android KK(4.4)及之前的版本 public boolean hasPermission(UsbDevice device) { synchronized (mLock) { int uid = Binder.getCallingUid(); if (uid == Process.SYSTEM_UID) { return true; } SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName()); if (uidList == null) { return false; } return uidList.get(uid); } } 这里就用上述第一种方式即可。
感觉自己好啰嗦哦(贴了不少代码),对你有帮助就好。
|
CopyRight 2018-2019 实验室设备网 版权所有 |