前言
從 Android 6.0(API 級別 23)開始档泽,用戶開始在應(yīng)用運行時向其授予權(quán)限,而不是在應(yīng)用安裝時授予揖赴。所以如果你的應(yīng)用使用到了一些危險權(quán)限馆匿,就必須在AndroidManifest.xml 中靜態(tài)地聲明需要用到的權(quán)限,并在使用到該功能時要動態(tài)的申請燥滑,否則在調(diào)用到相應(yīng)權(quán)限功能時候渐北,會拋出 SecurityException異常。所以本文探討一下動態(tài)權(quán)限的申請的正確流程铭拧,并把它封裝成一個庫赃蛛,簡化了申請過程恃锉。
權(quán)限的分類
在講解之前,先看一下android權(quán)限的分類呕臂,android權(quán)限分為四類破托,如下:
1、普通權(quán)限
普通權(quán)限也叫正常權(quán)限歧蒋,它不需要動態(tài)申請土砂,你只需要在用到它的時候在AndroidManifest.xml 中靜態(tài)地聲明,然后系統(tǒng)在app運行時就會自動的授予該app相應(yīng)的權(quán)限谜洽。這類權(quán)限主要在你的app想要接觸app沙盒外的數(shù)據(jù)或資源的時用到萝映,它不會涉及到系統(tǒng)的操作,也不會泄漏或篡改用戶的隱私數(shù)據(jù)阐虚。如下:
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序臂、簽名權(quán)限
該類權(quán)限只對擁有相同簽名的應(yīng)用開放。例如某個應(yīng)用自定義了一個permission 且在權(quán)限標(biāo)簽中加入 android:protectionLevel=”signature”实束,其他應(yīng)用想要訪問該應(yīng)用中的某些數(shù)據(jù)時奥秆,必須要在AndroidManifest.xml中聲明該權(quán)限,而且還要與該應(yīng)用具有相同的簽名咸灿,系統(tǒng)會在app運行時自動授予該權(quán)限吭练。這類我們用的比較少。
3析显、危險權(quán)限
也叫敏感權(quán)限鲫咽,運行時權(quán)限,跟普通權(quán)限相反谷异,一旦某個應(yīng)該獲取了該類權(quán)限分尸,用戶的隱私數(shù)據(jù)就面臨被泄露篡改的風(fēng)險。所以你想使用該權(quán)限就必須在AndroidManifest.xml 中靜態(tài)地聲明需要用到的權(quán)限歹嘹,并在使用到該功能時要動態(tài)的申請箩绍,除非用戶同意該權(quán)限,否則你不能使用該權(quán)限對應(yīng)的功能尺上。如下:
可以看到android把危險權(quán)限分為10組材蛛,所以申請危險權(quán)限的時候都是按組申請,我們只要申請組內(nèi)的任意一個危險權(quán)限就行怎抛,當(dāng)用戶一旦同意授權(quán)該危險權(quán)限卑吭,那么該權(quán)限所對應(yīng)的權(quán)限組中的所有其他權(quán)限也會同時被授權(quán)。
4马绝、特殊權(quán)限
特殊權(quán)限我了解的有三個豆赏,如下:
SYSTEM_ALERT_WINDOW:設(shè)置懸浮窗
WRITE_SETTINGS:修改系統(tǒng)設(shè)置
REQUEST_INSTALL_PACKAGES: 允許應(yīng)用安裝未知來源應(yīng)用
它也是要要申請的,但是它不同于危險權(quán)限的申請,危險權(quán)限的申請會彈出一個對話框詢問你是否同意掷邦,而特殊權(quán)限的申請需要跳轉(zhuǎn)到指定的界面白胀,讓你手動確認同意。
動態(tài)權(quán)限申請流程
所以動態(tài)權(quán)限的申請就是申請危險權(quán)限或特殊權(quán)限抚岗,權(quán)限的申請在不同的Android版本有不同的行為或杠,如下:
如果設(shè)備運行的是 Android 5.1 或更低版本,或者應(yīng)用的 targetSdkVersion 為 22 或更低:如果您在 Manifest 中列出了危險權(quán)限,則用戶必須在安裝應(yīng)用時系統(tǒng)會要求用戶授予此權(quán)限,如果他們不授予此權(quán)限,系統(tǒng)根本不會安裝應(yīng)用,用戶一旦全部同意授予砾肺,他們撤銷權(quán)限的唯一方式是卸載應(yīng)用。
如果設(shè)備運行的是 Android 6.0 或更高版本匈挖,并且應(yīng)用的 targetSdkVersion為23 或更高:應(yīng)用必須在 Manifest 中列出權(quán)限稠氮,并且它必須在運行時請求其需要的每項危險權(quán)限。用戶可以授予或拒絕每項權(quán)限茉盏,且即使用戶拒絕權(quán)限請求鉴未,應(yīng)用仍可以繼續(xù)運行有限的功能。用戶可以隨時進入應(yīng)用的“Settings”中調(diào)整應(yīng)用的動態(tài)權(quán)限授權(quán)鸠姨。所以你每次使用到該權(quán)限的功能時铜秆,都要動態(tài)申請,因為用戶有可能在“Settings”界面中把它再次關(guān)閉掉讶迁。
我這里討論的是6.0后的動態(tài)申請连茧,所以從 Android 6.0開始,無論您的應(yīng)用面向哪個 API 級別巍糯,您都應(yīng)對應(yīng)用進行測試啸驯,以驗證它在缺少需要的權(quán)限時行為是否正常。
如果還不了解動態(tài)權(quán)限申請的詳細步驟祟峦,可以看一下這篇文章:Android 6.0運行權(quán)限解析(高級篇)罚斗。
這里我假設(shè)大家已經(jīng)知道那些方法了,我把權(quán)限申請的流程分為單個和多個權(quán)限申請宅楞,分別畫了個圖针姿。
1、單個權(quán)限申請流程
2厌衙、多個權(quán)限申請流程
3距淫、自定義提示權(quán)限組的提示框
上面兩個圖有有提到自定義提示權(quán)限組,那么它主要包含以下內(nèi)容:
1婶希、包含需要授權(quán)的權(quán)限列表或單個權(quán)限提示
2溉愁、包含跳轉(zhuǎn)到應(yīng)用設(shè)置授權(quán)界面中的跳轉(zhuǎn)按鈕
3、包含放棄授權(quán)的取消按鈕,即取消這個提示框
注意:如果用戶不授權(quán)拐揭,則不能使用該功能或應(yīng)用無法運行撤蟆,可以考慮取消第3步的取消按鈕,即無法取消這個提示框堂污,一定要用戶去“Settings”授權(quán)家肯。
其他注意點
除了特殊權(quán)限外,還有一個location權(quán)限也比較特殊盟猖,需要通過 LocationManager的isProviderEnabled(LocationManager.GPS_PROVIDER)判斷是否打開定位開關(guān)后再進行權(quán)限申請讨衣,如下:
lm = (LocationManager) this.getSystemService(this.LOCATION_SERVICE);
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {//開了定位服務(wù)
//請求定位功能
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 {
//跳轉(zhuǎn)到開啟定位的地方
Toast.makeText(this, "系統(tǒng)檢測到未開啟GPS定位服務(wù),請開啟", Toast.LENGTH_SHORT).show();
Intent intent = new Intent();
intent.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(intent, PRIVATE_CODE);
}
}
結(jié)語
本文主要讓讓大家對權(quán)限的申請流程有進一步的認識,然后可以通過對動態(tài)權(quán)限的封裝式镐,將檢測動態(tài)權(quán)限反镇,請求動態(tài)權(quán)限,權(quán)限設(shè)置跳轉(zhuǎn)娘汞,監(jiān)聽權(quán)限設(shè)置結(jié)果等處理和業(yè)務(wù)功能隔離開來歹茶,業(yè)務(wù)以后可以非常快速的接入動態(tài)權(quán)限支持你弦,提高開發(fā)效率惊豺,更多細節(jié)查看PermissionHelper。
參考資料: