USB android授權方式
權限的控制分三塊:
1:USB host端有個線程循環檢測系統是否USB設備插拔,如果有就找到申請權限的APP并調用起來
2:APP運行后主動申請權限,也就是requestPermission()接口
3:APP運行后直接打開USB設備,這時候USB host端會去檢測APP是否已經有控制權限了,也就是調用的hasPermission()接口
第一種方式主要是再設計app 時候,能通過系統intent filter , 進行啟動某個activity
第二種方式主要是設計app已經啟動,再使用usb 的使用進行動態注冊,申請權限
第三中跟第二種類似,是再open device 時候進行申請權限, 可以hasPermission 授權
第一種:
systemReady -> UsbHostManager.java
monitorUsbHostBus ->
android_server_UsbHostManager_monitorUsbHostBus -> android_server_UsbHostManager.cpp
usb_host_run -> Usbhost.c
usb_host_read_event ->
context->cb_added -> //有usb設備添加
usb_device_added ->
env->CallVoidMethod -> //對方方法method_endUsbDeviceAdded --> endUsbDeviceAdded
endUsbDeviceAdded -> UsbHostManager.java
getCurrentSettings().deviceAttached ->
deviceAttached -> UsbSettingsManager.java
resolveActivity ->
resolveActivity ->
mUserContext.startActivityAsUser //包名是com.android.systemui.usb.UsbConfirmActivity
onCreate -> UsbConfirmActivity.java
setupAlert //彈出權限確認對話框
第二種:
requestPermission -> UsbManager.java
mService.requestDevicePermission ->
requestDevicePermission -> UsbService.java
getSettingsForUser(userId).requestPermission ->
requestPermission -> UsbSettingsManager.java
requestPermissionDialog ->
mUserContext.startActivityAsUser //包名com.android.systemui.usb.UsbPermissionActivity
onCreate -> UsbPermissionActivity.java
setupAlert //彈出權限確認對話框
第三種:
openDevice -> UsbService.java
mHostManager.openDevice ->
openDevice -> UsbHostManager.java
getCurrentSettings().checkPermission ->
hasPermission UsbSettingsManager.java
第一種方式問題及處理方法
APP : 設計插入啟動activity, 下面是靜態注冊:
圖片.png
動態注冊:
@Override
public void registerReceiver() {
IntentFilter mUsbDeviceFilter = new IntentFilter();
mUsbDeviceFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
mUsbDeviceFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
mUsbDeviceFilter.addAction(ACTION_USB_PERMISSION);
mContext.registerReceiver(this,mUsbDeviceFilter);
}
1-聲明 為android.hardware.usb.host
2-如果你的APP想要在有USB device插入時能夠被調用起來,那么必須要在xml的Activity中申請權限android.hardware.usb.action.USB_DEVICE_ATTACHED
3-如果只關心某些設備,可以通過里配置一個xml文件來做過濾
如果不想彈出權限:
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
index 3eccccd..18130ab 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
@@ -99,6 +99,11 @@ public class UsbConfirmActivity extends AlertActivity
setupAlert();
+ if (mResolveInfo.activityInfo.packageName.equals("ai.xxxx.xxx")) {
+ Log.d(TAG, "UsbConfirmActivity enable Usb permission for ai.xxxx.xxx");
+ onClick(this, AlertDialog.BUTTON_POSITIVE);
+ }
}
第二、三種流程及問題處理方法
詳細流程:
圖片.png
新建activity,獲取UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE)
獲取所以的USB設備HashMap map = usbManager.getDeviceList()
過濾別的USB設備,拿到自己USB的USBDevice類,然后請求USB權限,usbManager.requestPermission(usbDevice, pendingIntent);并注冊一個回調意圖,用來判斷用戶是否授予權限
UsbManager類的requestPermission方法會調用mService. requestDevicePermission
在requestDevicePermission方法里面調用的getSettingsForUser(userId).requestPermission
getSettingsForUser(userId)其實是去獲取UsbUserSettingsManager實例,所以是調用的UsbUserSettingsManager的requestPermission方法
在requestPermission方法里面首先會進行判斷是否擁有USB權限,如果有就回調廣播直接return返回的。如果沒有那就判斷是否有相機權限,如果沒有權限回調廣播直接return的。注意從始至終是沒有發送用戶拒絕的廣播的
接著會調用自身的requestPermissionDialog方法,在requestPermissionDialog方法里面又會去調用mUsbPermissionManager.requestPermissionDialog方法
10.最終在UsbPermissionManager類的requestPermissionDialog方法中調用startActivityAsUser 啟動UsbPermissionActivity權限申請對話框
11.監聽彈出權限對話框的onclick方法,如果點擊的授權,那就在UsbPermissionActivity的onDestory里面回調最開始的廣播,通知我們的應用,用戶授予的權限。
實例:
如果對usb 授權,需要知道vid pid
android/frameworks/base/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
public boolean hasPermission(UsbDevice device) {
synchronized (mLock) {
int uid = Binder.getCallingUid();
if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
return true;
}
+ if( vid&& pid == true) {
+ String deviceName = device.getDeviceName();
+ Slog.d(TAG, "customer uid:"+uid+"deviceName:"+deviceName);
+ SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
+ if (uidList == null) {
+ uidList = new SparseBooleanArray(1);
+ mDevicePermissionMap.put(deviceName, uidList);
+ }
+ uidList.put(uid, true);
+ }
SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName());
if (uidList == null) {
return false;
}
return uidList.get(uid);
}
}