1. 程式人生 > >Android6.0權限管理以及使用權限該註意的地方

Android6.0權限管理以及使用權限該註意的地方

結果 res hone grant 設備 -m hid 頁面 start

Android 6.0 Marshmallow首次增加了執行時權限管理,這對用戶來說,能夠更好的了解、控 制 app 涉及到的權限。然而對開發人員來說卻是一件比較蛋疼的事情。須要兼容適配,並保證程序功能的正常執行。
什麽叫執行時權限管理呢?在Android 6.0以下的系統中,當我們在安裝應用的時候,該應用就會提示我們這個應用所須要的權限,假設你要安裝。那就必須允許賦予全部權限,可是假設不允許,那就僅僅能取消安裝了,有點流氓。並且安裝完後,你不能夠收回這個權限。
而6.0就做到了執行時權限管理。即使安裝的時候給了權限,也能夠到系統設置裏。去關閉該權限。
以下分幾種情況來講,由於執行時權限僅僅有在Android6.0及以上的手機版本號才有,所以這裏僅僅考慮設備版本號大於6.0的手機。低版本號的手機在安裝時就已經賦予了全部的權限。也不可能收回,就不考慮了,以下的情況僅僅分targetSdkVersion:

  1. targetSDKVersion大於等於23的時候,那麽權限是能夠被回收(revoke)。這裏還要分權限。google將權限分為兩種,一種是normal permission,還有一種是dangerous permission。

    normal permission是指與用戶隱私無關的權限。能夠理解為無關緊要的權限,比方說訪問網絡的權限。對用戶來說沒什麽關系。dangerous permission就是會涉及到用戶隱私的權限。比如讀取用戶手機聯系人、短信等等。假設是normal permission的話,那麽在安裝的時候就會給,並且不會開放接口讓用戶回收該權限。app會一直擁有該權限,所以不用考慮這樣的類型的權限。假設是dangerous permission的話,在安裝的時候並未授予權限。系統開放接口允許用戶回收或者賦予權限。以下是某個應用的權限,第一張圖是dangerous permission。能夠回收和賦予的。


    技術分享
    點擊上面的全部權限,能夠查看到該應用全部的權限。
    技術分享
    那麽對於dangerous permission的話,在使用前須要去檢查該permission是否已經被授予

checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED

假設該權限已經被授予,那麽可繼續執行你的代碼,假設未授予,則須要向用戶詢問是否須要授予權限。彈出的框是系統界面,界面例如以下:
技術分享
調用代碼:

requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE}, 1
);

系統詢問是否授予權限的頁面結束後會有回調

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
   super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 1) {
        if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
            //your implementations
        }else{
            ToastUtil.show(this, "權限不足。支付失敗");
        }
    }
}
  1. 假設targetSdkVersion是小於23的。那麽將覺得app沒實用23新權限測試過,那麽繼續使用老規則:系統在安裝的時候會默認給app賦予全部的權限,app能夠照常執行。可是!可是!可是!

    用戶依舊能夠回收權限,只是此回收非彼回收。先看下關閉權限時彈的頁面:
    技術分享
    看到了麽。假設targetSDKVersion小於23的話,在關閉權限的時候。會彈一個警告框,告訴你這是舊版的android,關閉會有問題,假設你按拒絕。那麽該權限將會關閉。並且界面上。權限的開關會顯示關。可是這個權限卻沒有被回收(nexus 5x的手機親測。當然其它的機子我也不敢打包票)。checkSelfPermission返回granted。我看了下。假設targetSDKVersion等於23的話。系統日誌是:
    技術分享
    假設targetSDKVersion是小於23的話,則日誌是:
    Permission related app op changed.

只是我猜想假設你要支持runtime permission的話,還是要把targetSDKVersion設為23。假設你的targetSDKVersion是小於23的話,那麽還是要加上checkSelfPermission,以防萬一。誰知道google會出什麽坑。

還有就是權限的話,有分組的概念,看例如以下圖:
技術分享
假設一組中有一個被授予了,那麽組內的也會默認被授予。

並且也支持同一時候申請多個權限,詳細情況android developer官網。

以下是stackoverflow問題的網址:
http://stackoverflow.com/questions/36328151/ive-revoke-the-android-permission-but-checkselfpermission-still-return-granted

如有問題和錯誤的地方請指出。

以下就是要講一些權限管理註意的地方。
對於權限的話,Activity和Fragment都有自己的requestPermissions和onRequestPermissionsResult回調,可是Activity是有checkSelfPermission。可是fragment是沒有的,所以fragment假設想要檢查權限,還得調用宿主activity的checkSelfPermission。
對了,平時直接調用checkSelfPermission和requestPermissions會報什麽api錯誤,盡管編譯不會通過,可是看著就是煩啊。能夠調用ActivityCompat.checkSelfPermission(在supportv4包中)。
先看下Activity的requestSelfPermission這種方法:

public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
    Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
    startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
}

看下這裏是直接打開還有一個Activity進行操作,還用了startActivityForResult,回調會通過onRequestPermissionResult,我想這個回調應該是在onActivityResult裏面處理。然後調這個onRequestPermissionResult函數的。
那麽問題來了,假設我在onResume函數中申請某一個權限,調用requestPermissions,那麽現象是什麽樣的呢?
第一次進入頁面,彈出申請權限的對話框,假設點擊允許。則正常,對話框不會再顯示。可是假設第一次點擊拒絕,則點擊拒絕後重新彈出對話框來申請權限,假設你一直點拒絕。則對話框一直彈出,這是為什麽呢?由於第一次進入頁面並執行onResume函數時申請權限,進入還有一個頁面。彈出對話框,假設你點擊拒絕。先是回調onRequestPermissionResult,然後再執行onResume函數,這時又會再一次去檢查權限,由於發現無權限,則再一次請求,如是,進入一個循環之中,除非你點允許,否則是個無限循環。

所以申請權限不妨不要寫在onResume中,或者加一個標誌位推斷。


接下來再講講Fragment請求權限。

public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
    if (mHost == null) {
        throw new IllegalStateException("Fragment " + this + " not attached to Activity");
    }
    mHost.onRequestPermissionsFromFragment(this, permissions,requestCode);
}

這裏看到事實上是調用mHost請求權限的方法。mHost就是這個fragment的宿主Activity,所以Fragment請求權限實際上也是通過宿主Activity,當權限結果回調時,activity推斷是從Fragment中來的還是從自己Activity中來的,再進行分發結果。

Github上也有一些比較好用的權限庫:https://github.com/hotchemi/PermissionsDispatcher

Android6.0權限管理以及使用權限該註意的地方