android6.0動態權限申請的正確流程

前言

從 Android 6.0(API 級別 23)開始,用戶開始在應用運行時向其授予權限,而不是在應用安裝時授予。所以如果你的應用使用到了一些危險權限,就必須在AndroidManifest.xml 中靜態地聲明需要用到的權限,並在使用到該功能時要動態的申請,否則在調用到相應權限功能時候,會拋出 SecurityException異常。所以本文探討一下動態權限的申請的正確流程,並把它封裝成一個庫,簡化了申請過程。

權限的分類

在講解之前,先看一下android權限的分類,android權限分爲四類,如下:

1、普通權限

普通權限也叫正常權限,它不需要動態申請,你只需要在用到它的時候在AndroidManifest.xml 中靜態地聲明,然後系統在app運行時就會自動的授予該app相應的權限。這類權限主要在你的app想要接觸app沙盒外的數據或資源的時用到,它不會涉及到系統的操作,也不會泄漏或篡改用戶的隱私數據。如下:

ACCESS_LOCATION_EXTRA_COMMANDS 
ACCESS_NETWORK_STATE 
ACCESS_NOTIFICATION_POLICY 
ACCESS_WIFI_STATE 
BLUETOOTH 
BLUETOOTH_ADMIN 
BROADCAST_STICKY 
CHANGE_NETWORK_STATE 
CHANGE_WIFI_MULTICAST_STATE 
CHANGE_WIFI_STATE 
DISABLE_KEYGUARD 
EXPAND_STATUS_BAR 
FOREGROUND_SERVICE 
GET_PACKAGE_SIZE 
INSTALL_SHORTCUT 
INTERNET 
KILL_BACKGROUND_PROCESSES 
MANAGE_OWN_CALLS 
MODIFY_AUDIO_SETTINGS 
NFC 
READ_SYNC_SETTINGS 
READ_SYNC_STATS 
RECEIVE_BOOT_COMPLETED 
REORDER_TASKS 
REQUEST_COMPANION_RUN_IN_BACKGROUND 
REQUEST_COMPANION_USE_DATA_IN_BACKGROUND 
REQUEST_DELETE_PACKAGES 
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS 
SET_ALARM 
SET_WALLPAPER 
SET_WALLPAPER_HINTS 
TRANSMIT_IR 
USE_FINGERPRINT 
VIBRATE 
WAKE_LOCK 
WRITE_SYNC_SETTINGS 

2、簽名權限

該類權限只對擁有相同簽名的應用開放。例如某個應用自定義了一個permission 且在權限標籤中加入 android:protectionLevel=”signature”,其他應用想要訪問該應用中的某些數據時,必須要在AndroidManifest.xml中聲明該權限,而且還要與該應用具有相同的簽名,系統會在app運行時自動授予該權限。這類我們用的比較少。

3、危險權限

也叫敏感權限,運行時權限,跟普通權限相反,一旦某個應該獲取了該類權限,用戶的隱私數據就面臨被泄露篡改的風險。所以你想使用該權限就必須在AndroidManifest.xml 中靜態地聲明需要用到的權限,並在使用到該功能時要動態的申請,除非用戶同意該權限,否則你不能使用該權限對應的功能。如下:

危險權限

可以看到android把危險權限分爲10組,所以申請危險權限的時候都是按組申請,我們只要申請組內的任意一個危險權限就行,當用戶一旦同意授權該危險權限,那麼該權限所對應的權限組中的所有其他權限也會同時被授權。

4、特殊權限

特殊權限我瞭解的有三個,如下:

  • SYSTEM_ALERT_WINDOW:設置懸浮窗
  • WRITE_SETTINGS:修改系統設置
  • REQUEST_INSTALL_PACKAGES: 允許應用安裝未知來源應用

它也是要要申請的,但是它不同於危險權限的申請,危險權限的申請會彈出一個對話框詢問你是否同意,而特殊權限的申請需要跳轉到指定的界面,讓你手動確認同意。

動態權限申請流程

所以動態權限的申請就是申請危險權限或特殊權限,權限的申請在不同的Android版本有不同的行爲,如下:

  • 如果設備運行的是 Android 5.1 或更低版本,或者應用的 targetSdkVersion 爲 22 或更低:如果您在 Manifest 中列出了危險權限,則用戶必須在安裝應用時系統會要求用戶授予此權限,如果他們不授予此權限,系統根本不會安裝應用,用戶一旦全部同意授予,他們撤銷權限的唯一方式是卸載應用。
  • 如果設備運行的是 Android 6.0 或更高版本,並且應用的 targetSdkVersion爲23 或更高:應用必須在 Manifest 中列出權限,並且它必須在運行時請求其需要的每項危險權限。用戶可以授予或拒絕每項權限,且即使用戶拒絕權限請求,應用仍可以繼續運行有限的功能。用戶可以隨時進入應用的“Settings”中調整應用的動態權限授權。所以你每次使用到該權限的功能時,都要動態申請,因爲用戶有可能在“Settings”界面中把它再次關閉掉。

我這裏討論的是6.0後的動態申請,所以從 Android 6.0開始,無論您的應用面向哪個 API 級別,您都應對應用進行測試,以驗證它在缺少需要的權限時行爲是否正常。

如果還不瞭解動態權限申請的詳細步驟,可以看一下這篇文章:Android 6.0運行權限解析(高級篇)。

這裏我假設大家已經知道那些方法了,我把權限申請的流程分爲單個和多個權限申請,分別畫了個圖。

1、單個權限申請流程

2、多個權限申請流程

3、自定義提示權限組的提示框

上面兩個圖有有提到跳出自定義提示權限組,那麼它主要包含以下內容:

  • 1、包含需要授權的權限列表或單個權限提示
  • 2、包含跳轉到應用設置授權界面中的跳轉按鈕
  • 3、包含放棄授權的取消按鈕,即取消這個提示框

注意:如果用戶不授權,則不能使用該功能或應用無法運行,可以考慮取消第3步的取消按鈕,即無法取消這個提示框,一定要用戶去“Settings”授權。

其他注意點

除了特殊權限外,還有一個location權限也比較特殊,需要通過 **LocationManager的isProviderEnabled(LocationManager.GPS_PROVIDER)**判斷是否打開定位開關後再進行權限申請,如下:

	lm = (LocationManager) this.getSystemService(this.LOCATION_SERVICE);
    if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {//開了定位服務
        //請求定位功能
       PermissionHelper.getInstance().with(this).requestPermission(
                Manifest.permission.ACCESS_FINE_LOCATION,
                new IPermissionCallback() {
                    @Override
                    public void onAccepted(Permission permission) {
                        //...
                    }

                    @Override
                    public void onDenied(Permission permission) {
						//...
                    }
                }
        );
    } else {
        //跳轉到開啓定位的地方
        Toast.makeText(this, "系統檢測到未開啓GPS定位服務,請開啓", Toast.LENGTH_SHORT).show();
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        startActivityForResult(intent, PRIVATE_CODE);
    }
}

結語

本文主要讓讓大家對權限的申請流程有進一步的認識,然後可以通過對動態權限的封裝,將檢測動態權限,請求動態權限,權限設置跳轉,監聽權限設置結果等處理和業務功能隔離開來,業務以後可以非常快速的接入動態權限支持,提高開發效率,更多細節查看PermissionHelper

參考資料:

Permissions

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章