Android Android Studio Runtime Permissions

Android Runtime Permissions

柯杏洳 2016/12/08 10:08:15
2584







主題

Android Runtime Permissions

文章簡介

簡單的Android Runtime Permissions相關程式範例

作者

柯杏洳

版本/產出日期

V1.0/2016.12.07


1. 前言

本文章用來提供Android開發人員在開發應用程式時,初步了解Android Runtime Permissions的相關程式。



2. 開始前準備

請先自行準備一台Android 6.0以上的手機或模擬器,開好一個Android專案,本文章範例建立於以下版本的環境:

JDK 8

Android Studio 2.2.2



3. 關於Runtime Permissions

對於開發者來說,原本Android的 App如果需要權限,只需在App的Manifest檔案定義就好,而對於使用者來說,就是在Google Play按下安裝時,會看到應用程式要求存取的權限(然後為了安裝也只能同意),但是從6.0 (API level 23)開始,Android允許使用者可以在App安裝之後再去開啟或關閉app所獲取的一些權限(Dangerous Permissions,詳見第二個參考連結,這裡權限的開啟跟關閉是針對權限group),也可以說是從這個版本開始,這些權限需要使用者明確的同意才可以提供給App,於是開發時如果要支援6.0以上的手機,就需要加上一些程式碼做權限檢查跟request相關的處理(如果忘了寫程式處理,執行的時候就會有例外,開發者就會記得要加了XD)。



4. 手機上查看方式

這裡以我手邊手機Nexus 5(搭Android 6.0.1)為例,首先打開「設定」的App,點擊「應用程式」選單




a. 點擊右上角齒輪圖示(往下)
b. 點擊單一應用程式(往右)

可以檢視該應用程式現在取得了哪些權限,點擊權限區塊

點擊「應用程式權限」

可以變更這應用程式權限的授權狀況

在這裡可以查看各個權限已授權多少應用程式、共有多少應用程式request這些權限,再點擊權限項目進去

可以變更每個應用程式授權的狀況




5. 程式範例

如果正在開發的App使用到一些Dangerous權限(詳見第二個參考連結,常見的例子是要存取聯絡人資料、儲存空間、相機、電話等),除了一樣要在Manifest檔案定義之外,需要加入檢查、request跟request結果處理的部分。


在此以電話為例,我要使用Intent來做打電話的動作,利用Intent.ACTION_CALL這個Action,讓我的App能直接打電話,這需要使用到"android.permission.CALL_PHONE"的權限。(如果是用Intent.ACTION_DIAL叫別的App做打電話的動作,我們的App就不需要用到該權限)


(%1) Manifest加入權限宣告

<uses-permission android:name="android.permission.CALL_PHONE" />



(1) 檢查權限是否獲取

呼叫ContextCompat.checkSelfPermission(),傳入Context與權限字串常數(詳見第三個參考連結)檢查回傳值是否為PERMISSION_GRANTED。



(2) request權限

呼叫ActivityCompat.requestPermissions(),傳入Activity、權限字串陣列(可以一次要求多個權限)與RequestCode(跟startForActivityResult所用的RequestCode作用一樣,可以用來區分這是哪個request)


第一次執行request會出現下圖的對話框


如果按了拒絕,再執行request,會出現如下圖的對話框(多了不要再詢問的CheckBox),如果使用者勾選了不要再詢問,接下來再執行request將不會再顯示對話框(除非使用者有去應用程式設定變更授權狀態)。


如果一次request多個權限,則畫面會像下面兩張圖,左下角多了「目前是第幾個要詢問的權限 / 總共要詢問的權限數量」的字樣(左圖和右圖分別是第一次跟第二次以後出現的樣式,同樣只差在多了不要再詢問CheckBox)。



(3) 處理request權限的結果

為了要知道request的結果,我們得覆寫onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)。(不論使用者按下「允許」、「拒絕」或已不再顯示對話框,結果都將透過onRequestPermissionsResult回來



(4) 確認是否需要跟使用者解釋需要權限的原因Optional

呼叫ActivityCompat.shouldShowRequestPermissionRationale(),傳入Activity權限字串常數。

官方說法使用者可能就是不清楚為什麼要用到權限才按下拒絕,有時可能需要幫助使用者了解這個App為什麼需要用到這權限,因此這個方法主要是使用者第一次看到對話框,按下「拒絕」之後,且勾選不再詢問之前都會回傳true因為,如果使用者再次按下拒絕且勾選不要再詢問,就沒必要再作解釋

不過,在實際案例中,如果接下來的操作真的需要這個權限只要request回來的結果是沒有授權,App得讓使用者知道這樣功能無法運作,所以我自己覺得沒有一定要呼叫這個方法。



6. 補充

(1) Fragment權限request

如果是(已經被attach到某個Activity上的)Fragment想要自己request權限並處理request結果,差別在於request的時候,要直接呼叫Fragment本身的requestPermissions(),傳入權限字串陣列與RequestCode,並在Fragment的類別裡覆寫onRequestPermissionsResult()

特別需要注意的是,這裡Fragmentrequest結果其實會先經過Activity再到Fragment(詳情可以去Android AcitivityonRequestPermissionsResult程式),所以Activity如果有覆寫onRequestPermissionsResult(),必須執行父類別的方法就可以FragmentonRequestPermissionsResult()收到結果囉!



(2) 導去應用程式設定

萬一使用者真的勾選了不再詢問,且拒絕授權給App,此時呼叫request就不會再跟使用者有互動了,也許可以試著引導使用者去App設定打開權限,目前Android沒有開放直接開啟App權限設定頁的方式,找到的替代方案就是開啟該App的資訊頁(詳見最後一個參考連結)。



(3) Android StudioIntelliJ)小幫手

現在Android Studio會提示需要在Manifest加權限宣告

按下Quick fix快捷鍵(在MAC目前是alt+Enter)會顯示建議動作

選了動作會自動在Manifest補上宣告

<uses-permission android:name="android.permission.CALL_PHONE" />



也會提示需要呼叫checkSelfPermission檢查是否有權限

按下快捷鍵會顯示建議動作

選了動作會自動幫忙補上基本的判斷邏輯




以上是針對Runtime Permissions的簡單說明,如果有興趣可以看看官網詳細解釋與網路上各種大神的說明。


本文章的範例專案放在此連結:https://github.com/smallblack9/RuntimePermissionsSample




7. 參考來源

Working with System Permissions | Android Developers https://developer.android.com/training/permissions/index.html

Normal and Dangerous Permissions (主要有列出Dangerous的權限與其對應的group)
https://developer.android.com/guide/topics/security/permissions.html#normal-dangerous

Manifest.permission (內有權限常數的定義)
https://developer.android.com/reference/android/Manifest.permission.html

取通話紀錄的參考程式(stackoverflow)
http://stackoverflow.com/questions/19493360/get-last-call-duration-in-android

開啟App設定頁面參考作法
http://stackoverflow.com/questions/32822101/how-to-programmatically-open-the-permission-screen-for-a-specific-app-on-android





柯杏洳