現象說明:在獲取定位權限時,第一次拒絕授權,然后在應用詳情、權限管理中開啟定位權限,下次使用定位權限時還是提示未授權定位權限。
其實,小米對權限管理控制在谷歌之前就考慮好了,所以有自己的權限管理(安全中心),所以在授權是必須要安全中心、詳情中的權限管理2個入口的權限都是開啟狀態才能正常使用該權限。
在第一授權時,如果用戶允許權限,2處的權限開關都是開啟的,可以正常使用;如果拒絕該權限,那2處的權限開關都是關閉的,即使開啟詳情、權限管理中的權限,也還不能使用,必須手動開啟安全中心中對應的權限。
所以在使用過程中需要增加一個邏輯,通過正常的方式檢測獲取到權限后,需要判斷小米手機在安全中心權限是否已授權,代碼參考:
/** * 查看原生態的權限是否有授權 * * @param context * @param op 如定位權限AppOpsManager.OPSTR_FINE_LOCATION * @return */ public static boolean checkAppops(Context context, String op) { if (isMIUI()) { // 只有小米手機才檢測 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); int checkOp = appOpsManager.checkOp(op, Binder.getCallingUid(), context.getPackageName()); if (checkOp == AppOpsManager.MODE_IGNORED) { return false; } } } return true; } // 檢測MIUI private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code"; private static final String KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name"; private static final String KEY_MIUI_INTERNAL_STORAGE = "ro.miui.internal.storage"; // 注意這個狀態最好用SharePreference保存起來,需要每次讀取檢測 public static boolean isMIUI() { //獲取緩存狀態 String miui = SPUtil.getStringForDefault(SPConstant.IS_MIUI); if (miui != null) { if ("1".equals(miui)) return true; else if ("2".equals(miui)) return false; } Properties prop = new Properties(); boolean isMIUI; try { prop.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop"))); } catch (IOException e) { e.printStackTrace(); return false; } isMIUI = prop.getProperty(KEY_MIUI_VERSION_CODE, null) != null || prop.getProperty(KEY_MIUI_VERSION_NAME, null) != null || prop.getProperty(KEY_MIUI_INTERNAL_STORAGE, null) != null; SPUtil.putStringForDefault(SPConstant.IS_MIUI, isMIUI ? "1" : "2"); return isMIUI; }
如果存在個人理解有誤的地方,望指正!