Android許可權最佳實踐
提示:這篇文章寫的比較早了,一直沒時間“翻新”,現在看來存在一些問題,等後面會重新寫一篇。讀者簡單參考即可。
前言
大家好我是光源。
從 Android6.0 開始Android的許可權模式有了一番更改,從安裝時一股腦列給使用者,到執行時動態申請許可權。對於 Android開發者而言,這是一個重要的變更。
討論這個問題之前,我們得先檢查一下專案的 target version。如果是 23及以上,則必須得適配新許可權模式;如果是 23之下,則還是統一在安裝時全部申請許可權——即便如此,使用Android 6.0及以上系統的使用者還是可以在設定中去關閉你的某些許可權。當許可權被關閉時,不會導致你的應用直接崩潰,但是會導致你獲取到的返回值為null 或者 0,這個是需要注意的地方。
以下是 Android 官網給出的最佳實踐,草草翻譯,有不妥之處還請斧正。
正文
app很容易用海量的許可權請求淹沒使用者。如果使用者發現 app 影響使用或者擔憂 app 濫用使用者個人資訊,他們可能不再使用或者完全刪除這個app。以下最佳實踐能幫助你避免這種糟糕的使用者體驗。
優先使用 Intent
在很多情況下,你都可以選擇兩種方式來為你的app完成任務。你可以讓你的app去請求許可權來自己完成操作,或者你也可以讓 app 利用 intent 讓其他 app 進行這項工作。
舉個例子假如你的 app 需要用裝置中的相機來拍照,你的 app 可以請求 CAMERA
許可權 以直接使用相機元件,然後你的 app 將使用相機元件介面去控制相機並拍照。這個方法使你的 app 有完整的攝影程式控制權,讓你將相機UI納入app中【譯者注:即可以完全自定義相機UI】。
然而,如果你不需要這麼完整的控制,你可以使用 ACTION_IMAGE_CAPTURE
intent 去請求圖片。當你傳送這個intent,系統讓使用者選擇一個相機 app(如果還沒有預設的相機 app)。 使用者用選中的相機 app 拍照後,它將照片反回給你的 app 的 onActivityResult()
方法。
同樣得,如果你需要打電話、讀寫使用者的通訊錄等等,你可以通過建立合適的 intent 來實現或者請求許可權後直接訪問合適的元件。二者各有利弊。
如果你使用許可權:
- 你的 app 在執行該操作時對使用者體驗有完整的掌控。但是這麼寬泛的控制增加了任務的複雜度,因為你需要自行設計合適的UI。
- 不管在執行時還是剛安裝時,使用者傾向於只進行一次許可權操作,此後,你的 app 就可以進行操作無需使用者額外授權。但是,如果使用者沒有允許許可權或者後來取消了,你的 app 將一直無法進行該操作。
如果你使用 intent:
- 你不需要為該操作設計UI。處理 intent 的 app 提供了UI。然而,這意味著你無法掌控這部分使用者體驗。使用者可能跟你一無所知的 app 打交道。
- 如果使用者沒有處理該操作的預設應用,系統會讓使用者選擇一個。如果使用者沒有指定一個預設處理,每次進行該操作都會彈出額外的選擇對話方塊。
只�申請必須的許可權
你每次申請許可權都在迫使使用者做決定,所以你應該減少發出這些請求的次數。如果使用者使用的是 Android 6.0 及之後的系統,每次使用者使用某些 app 中需要許可權的特性,app 就必須因申請許可權而打斷使用者。如果使用者使用 6.0之前的系統,在安裝 app 時使用者必須得允許每一個許可權。如果許可權清單太長或者看起來不合適,使用者可能會決定停止安裝你的 app。因為以上種種,你最好減少申請的許可權數量。
不要壓垮使用者
如果使用者使用 Android6.0及之後的系統,在執行 app時需要授權。如果你把一大堆許可權申請一次性拋給使用者,你會把他們壓垮進而刪除你的應用。因而你應該只在必要時才去請求許可權。
在某些情況下,對你的 app 而言一個或多個許可權是完全必要的,在 app 啟動時就去請求這些許可權是有意義的。比如你做了一個攝影 app,它需要使用相機。當使用者第一次啟動該 app 時,他們自然不會驚訝請求相機的許可權。但是如果這個app還有通過使用者的通訊錄分享圖片的功能的話,你就不應該在第一次啟動時獲取 READ_CONTACTS
許可權。而應該等到使用者使用”分享“功能時再請求許可權。
解釋你為何需要許可權
當你呼叫[requestPermissions()](https://developer.android.com/reference/android/support/v4/app/ActivityCompat.html#requestPermissions(android.app.Activity, java.lang.String[], int)) 表明你的 app 需要什麼許可權時系統會顯示許可權對話方塊,但是沒有說為什麼。在某些情況下,使用者會感到困惑。在呼叫[requestPermissions()](https://developer.android.com/reference/android/support/v4/app/ActivityCompat.html#requestPermissions(android.app.Activity, java.lang.String[], int)) 前向使用者解釋你的 app 為何需要這些許可權是個好主意。
比如,一個拍照 app 可能會需要定位服務以便給圖片打上地理位置標籤。一個普通使用者可能無法理解一張圖片可以包含位置資訊,然後會困惑為什麼拍照 app 會需要知道他的位置。所以在這種情況下,app 在呼叫[requestPermissions()](https://developer.android.com/reference/android/support/v4/app/ActivityCompat.html#requestPermissions(android.app.Activity, java.lang.String[], int)) 前告訴使用者這個特性是個好主意。
告知使用者的一個不錯的方法是把這些許可權請求合併進 app 引導中。app 引導可以依次介紹 app 的特性,在做這些的同時,可以解釋需要哪些許可權。例如,拍照 app的引導可以示範”通過通訊錄分享照片“的功能,告知使用者他們需要授權 app 檢視使用者的通訊錄。然後該 app 可以呼叫[requestPermissions()](https://developer.android.com/reference/android/support/v4/app/ActivityCompat.html#requestPermissions(android.app.Activity, java.lang.String[], int)) 請求讀取通訊錄。當然,不是所有使用者都會跟從引導,所以你依然需要檢查確認並且在 app 的日常使用中請求許可權。
測試兩種許可權模式
從 Android 6.0 開始,使用者在應用執行時允許或者拒絕許可權而不是在應用安裝時,這導致你需要測試各種條件下app 的表現。
在 Android 6.0之前,你可以合理假定你的 app 一直可執行,它擁有所有在 app manifest中宣告的許可權。在新的許可權模式下,你不能這麼認為了。
以下提示將幫助你驗證 Android 6.0及以上系統的許可權相關程式碼問題。
驗證 app 當前許可權以及相關程式碼路徑。
測試使用者通過許可權保護服務和資料。
測試多種許可權分別被允許、拒絕的組合情況。比如,相機 app 可能在 manifest 檔案中宣告瞭
CAMERA
、READ_CONTACTS
和ACCESS_FINE_LOCATION
許可權。你應該測試每個許可權開啟和關閉的情況來確保 app 可以優雅地處理所有許可權配置情況。記住,從 Android 6.0開始使用者可以開啟或關閉任意一個app的許可權,即便是 targets API 在 22及以下的。-
使用 adb 工具通過命令列管理許可權:
-
以組的形式列出許可權和狀態:
$ adb shell pm list permissions -d -g
-
允許或拒絕一個或多個許可權:
$ adb shell pm [grant|revoke] <permission-name>
-
為使用許可權的服務分析 app
後記
以上是 Android 官網給出的最佳實踐。個人覺得這篇文章主要從使用者體驗角度來闡述許可權的最佳實踐,還缺乏程式碼層面的實踐,因此擴充套件一下。
許可權相關程式碼最佳實踐
第零步,在manifest 檔案中宣告所需的許可權。
第一步,檢測是否擁有許可權。
API 23 or above | all version |
---|---|
checkSelfPermission | ContextCompat.checkSelfPermission() |
被授權函式返回PERMISSION_GRANTED
,否則返回PERMISSION_DENIED
。
第二步,檢測是否需要顯示申請許可權對話方塊。如果第一步返回沒有許可權的話,則我們需要去申請許可權,但是申請許可權之前,需要顯示檢視使用者是否已經禁止了申請許可權對話方塊,如果禁止的話,我們用第三步的程式碼將沒有任何效果。
API 23 or above | all version |
---|---|
shouldShowRequestPermissionRationale | ActivityCompat.shouldShowRequestPermissionRationale / FragmentCompat.shouldShowRequestPermissionRationale |
返回為 true
或 false
,在 6.0以下恆定為 false
,這個不用多解釋了吧,在 6.0以下還沒有系統預設對話方塊存在,肯定不彈了。
第三步,顯示提示框去申請許可權。
API 23 or above | all version |
---|---|
requestPermissions | ActivityCompat.requestPermissions/ FragmentCompat.requestPermissions() |
發出請求後,會在 onRequestPermissionsResult 方法中獲得回撥結果。
以目前 Android系統的佔有率分佈,最低建議支援4.0,所以我們可以直接使用相容庫中的三個方法以相容所有版本。下面是一個簡單的需求,向SD卡中寫入資料:
/**
* 向SD卡插入資料
*/
private void insertDataToSDCard() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
//擁有許可權
//TODO 向SD卡寫資料
} else {
//沒有許可權,判斷是否會彈許可權申請對話方塊
boolean shouldShow = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (shouldShow) {
//申請許可權
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_REQUEST_PERMISSION);
} else {
//被禁止顯示彈窗
//TODO 顯示對話方塊告知使用者必須開啟許可權
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQUEST_CODE_REQUEST_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//permission granted
//TODO 向SD卡寫資料
} else {
//permission denied
//TODO 顯示對話方塊告知使用者必須開啟許可權
}
}
}
可見,通過相容庫去做許可權模式相容還是挺簡單明瞭的。考慮到擴充套件性,完全可以�把許可權判斷邏輯寫成一個通用的工具類。
最後,推薦一個第三方庫hotchemi’s PermissionsDispatcher,這個也是參考資料中看到的一個不錯的第三方庫,有興趣可以看看。
參考資料
相關文章
- Android 6.0 執行時許可權管理最佳實踐Android
- CATIA許可管理最佳實踐
- Capital許可證管理最佳實踐API
- CATIA軟體許可管理最佳實踐
- Atlas 2.1.0 實踐(4)—— 許可權控制
- Android系統許可權和root許可權Android
- 【專案實踐】一文帶你搞定頁面許可權、按鈕許可權以及資料許可權
- 基於casbin的RBAC許可權實踐
- android許可權大全Android
- Android permission許可權Android
- 如何用 Vue 實現前端許可權控制(路由許可權 + 檢視許可權 + 請求許可權)Vue前端路由
- android動態許可權到自定義許可權框架Android框架
- Nestjs RBAC 許可權控制管理實踐(一)JS
- Nestjs RBAC 許可權控制管理實踐 (二)JS
- Android許可權管理之Permission許可權機制及使用Android
- android 許可權庫EasyPermissionsAndroid
- Android許可權適配Android
- Android安全—許可權模型Android模型
- Android系統許可權Android
- android 許可權問題Android
- Android SELinux許可權AndroidLinux
- Android6.0------許可權申請管理(單個許可權和多個許可權申請)Android
- 分散式系統中,許可權設計實踐分散式
- Oracle的物件許可權、角色許可權、系統許可權Oracle物件
- 許可權之選單許可權
- android 許可權元件設計Android元件
- Xamarin Android許可權請求Android
- Android之SharedPreferences許可權Android
- Android 許可權清單大全Android
- Android許可權管理之Android 6.0執行時許可權及解決辦法Android
- 許可權控制在數棧產品的實踐
- vuejs單頁應用的許可權管理實踐VueJS
- linux 檔案許可權 s 許可權和 t 許可權解析Linux
- 國產 Android 許可權申請最佳適配方案 —— permissions4mAndroid
- 許可權系統:一文搞懂功能許可權、資料許可權
- MySQL許可權管理實戰MySql
- Laravel實現許可權控制Laravel
- Android動態許可權總結Android