你或許理解錯了Android系統權限管理的這兩個概念

作者簡介 原創微信公眾號郭霖 WeChat ID: guolin_blog

本篇是釗林的第二篇投稿,示例對比了清單權限與運行時權限,并給出了運行時權限的適配方案。希望能夠幫助到大家。

釗林的博客地址:

http://teachcourse.cn

正文

摘要

為什么系統禁用錄音權限后,在?Android?6.0以上 版本手機運行崩潰?為什么清單文件聲明了錄音權限,Android 6.0以下 版本僅第一次提示權限授予窗口?為什么使用運行時權限請求,返回權限以授予?怎么讓Android應用程序在每次操作時識別系統是否禁用對應權限?如果你和我一樣存在很多很多的疑問,說明你還沒明白傳統的manifest清單文件聲明權限和運行時權限請求之間的區別。

對比傳統權限聲明和運行時權限請求的區別

傳統權限聲明針對 Android 6.0 及其以下版本使用,Android 6.0對應的API版本23,聲明的方式直接將所有應用程序用到的權限統一在?manifest?清單文件中定義,使用標簽,應用程序點擊安裝的過程,羅列清單文件聲明的所有權限,安裝完成后用戶可以選擇是否授予應用程序某個隱私的權限,Android系統提供:允許、提示和禁止三種選擇,下面看一組演示:

build.gradle?選擇編譯版本、目標版本都是?API 19,運行在Android 4.4.2系統(華為)效果:


圖 1

build.gradle?選擇編譯版本、目標版本都是?API 19,運行在Android 6.0.1系統(小米)效果


圖 2

build.gradle選擇編譯版本、目標版本都是API 23,運行在Android 4.4.2系統(華為)效果:


圖 3

build.gradle選擇編譯版本、目標版本都是API 23,運行在Android 6.0.1系統(小米)效果:


圖 4

圖1演示傳統權限授予過程,在完成安裝的過程中可以選擇某個權限是否允許提示禁止狀態;

圖2演示低版本應用程序在Android 6.0以上系統安裝過程,默認授予應用程序清單文件聲明的所有權限,小米手機測試無法修改權限狀態;

圖3圖4演示API版本23開發的應用程序分別安裝在低版本和高版本系統權限授予過程,安裝在低版本時授予權限過程和傳統的方式一樣,用戶可以修改權限的狀態;安裝到高版本時授予權限過程發生了很大變化,用戶安裝過程無法修改權限狀態,最后運行應用程序的錄音功能,出現閃退、崩潰現象。到這里,你是不是和我一樣,有一點點明白傳統權限聲明和運行時權限請求之間的區別嗎?

深入理解運行時權限請求過程

是不是我們可以大致認為:使用 API 23 及其以上版本開發的應用程序安裝在Android 6.0系統以下的手機,默認授予應用程序清單文件所有的權限,安裝在Android 6.0系統以上的手機默認禁止清單文件聲明的所有權限?應用程序獲取權限的過程中,調用Android開發庫提供的一些方法,某個方法返回null或屬性為null,就可能導致使用部分功能時應用程序崩潰,而部分被禁止權限的功能雖然不會導致程序崩潰,但也無法獲取正確的數值。

運行時權限的出現,一改傳統清單文件一鍵授權的不足,防止用戶安裝過程的慣性操作,獲取了用戶某些隱私權限,這些權限包括:收集位置信息讀取短信內容記錄用戶數據等,然后進行一些非法操作:發送短信訂閱資費套餐,扣取手機話費等,為了用戶隱私信息的安全,API 23開發的應用程序統一在運行時提醒用戶授予權限,僅授予針對當前功能使用到的權限,未使用到的權限默認禁止。

那么如何兼容低版本的應用程序呢?以及如何讓高版本的應用程序也能在Android 6.0以下系統正常運行?那可能就像文章開頭演示的四種效果圖。

運行時權限涉及的幾個過程:第一檢查權限是否被授予,使用方法?checkPermission();第二請求獲取權限,使用方法?requestPermissions();第三用戶是否授予應用程序權限,監聽回調方法?onRequestPermissionsResult(),為了防止應用API 23開發的應用程序在Android 6.0以上系統正常安裝,在代碼中添加權限檢查,如下:

針對圖4,運行時請求獲取錄音權限,然后點擊禁止后回調方法?onRequestPermissionsResult(),如下圖:


應用程序請求授予權限后,如果用戶點擊禁止,以后每次權限檢查不再出現選擇提示窗口,onRequestPermissionsResult()?方法返回權限的狀態是?PackageManager.PERMISSION_DENIED,防止反復彈出要求用戶授予權限彈窗,如果開發者仍然期待在用戶沒有禁止權限狀態后,再次提醒用戶授予權限,需要調用方法?shouldShowRequestPermissionRationale(),該方法的目的顯示系統UI說明提示用戶重新授予應用程序權限,Nexus 5?測試運行效果,如下:

動圖


查看?shouldShowRequestPermissionRationale()?源碼說明,詳細了解該方法的使用:獲取是否你應該通過顯示UI說明請求授權的原因,只有當你沒有獲得該權限,同時當前上下文環境需要的權限沒有明確和用戶溝通——對于獲取該權限有什么用處,這時候你應該調用該方法。比如說,如果你寫了一個拍照功能的APP,請求了用戶可能需要的拍照權限,而沒有解釋為什么請求的權限是必須的,可能用戶沒覺得不正常;然而如果當前APP在拍照時請求獲取位置的權限,這時對于一個不精通技術的用戶來說可能想知道定位和拍照是怎樣的一種聯系。在這個情景之下,你大概會選擇通過一個顯示UI說明請求授權的原因:

說明:Android 6.0.1系統小米手機測試,在用戶禁止后,調用?shouldShowRequestPermissionRationale?該方法沒有顯示說明;使用 Android Studio 內置的Nexus 5模擬器測試用戶第一次請求權限彈窗只有?DENY?和?ALLOW?選項,在用戶選擇?DENY?后再次調用?requestPermissions方法,彈窗除了?DENY?和?ALLOW?選項外,還多了一個?Never ask again?復選框。

關于ActivityCompat的說明

在上面檢查授予權限的代碼中,我使用了?getPackageManager().checkPermission()?這個方法檢查,考慮到兼容高低版本API的問題,還是推薦使用v4包下的?ActivityCompat.checkSelfPermission()?這個靜態方法或者父類?ContextCompat.checkSelfPermission();請求權限推薦使用?ActivityCompat.requestPermissions()?這個靜態方法,如果第一次禁止后,重新彈窗顯示UI說明,調用靜態方法?ActivityCompat.shouldShowRequestPermissionRationale()?后重新授權,具體可以查看?ActivityCompat?源碼理解它們之間的關系。

在API 23的版本中,查看?ActivityCompat?的源碼,上述的三個方法最終來自受保護的類?ActivityCompatApi23,在源碼中檢查了應用程序的API版本。

響應用戶授權狀態的回調方法?onRequestPermissionsResult()?屬于?ActivityCompat?內部的一個接口,如果沒有猜錯的話,僅在API 23以后的版本中,實現了?ActivityCompat.OnRequestPermissionsResultCallback接口 的Activity子類,才能回調?onRequestPermissionsResult()方法,同時也會看到 FragmentActivity、AppCompatActivity 源碼實現了上述接口。

運行時權限策略

提出了運行時權限,在運行應用程序的時候,每使用應用程序的一個功能開發者就需要請求授權一次,那必然會加大了開發者的工作量,請求權限的代碼會變得很多,同時本來運行時權限的申請方式本來就比傳統權限請求方式復雜,如果再讓開發者一次次請求授權那肯定非常反感。為了解決權限反復多次請求的問題,Google采用了權限分組的策略:同一組的多個權限,只要獲得了用戶授予的一個權限,同時可以使用同組的其他權限,權限的分組情況如下圖:

android.permission-group.CALENDAR

android.permission.READ_CALENDAR

android.permission.WRITE_CALENDAR

android.permission-group.CAMERA

android.permission.CAMERA

android.permission-group.CONTACTS

android.permission.READ_CONTACTS

android.permission.WRITE_CONTACTS

android.permission.GET_GET_ACCOUNTS

android.permission-group.LOCATION

android.permission.ACCESS_COARSE_LOCATION

android.permission.ACCESS_FINE_LOCATION

android.permission-group.MICROPHONE

android.permission.RECORD_AUDIO

android.permission-group.PHONE

android.permission.READ_PHONE_STATE

android.permission.CALL_PHONE

android.permission.READ_CALL_LOG

android.permission.WRITE_CALL_LOG

android.permission.ADD_VOICEMAIL

android.permission.USE_SIP

android.permission.PROCESS_OUTGOING_CALLS

android.permission-group.SENSORS

android.permission.BODY_SENSORS

android.permission-group.SMS

android.permission.SEND_SMS

android.permission.RECEIVE_SMS

android.permission.READ_SMS

android.permission.RECEIVE_WAP_PUSH

android.permission.RECEIVE_MMS

android.permission-group.STORAGE

android.permission.READ_EXTERNAL_STORAGE

android.permission.WRITE_EXTERNAL_STORAGE

參考資料:

https://developer.android.google.cn/guide/topics/security/permissions.html#perm-groups


完。。。。。。。。。。。。。。。。。。。。。

文章原創作者GuoLin 書籍推薦

郭林大神原創android 書籍:《第一行代碼 android》

淘寶鏈接: https://s.click.taobao.com/t?e=m%3D2%26s%3DgKUfuKdAZKocQipKwQzePOeEDrYVVa64K7Vc7tFgwiHjf2vlNIV67p2n%2BQBNMyE6Rku8%2Bpj6eJall3bs%2B3NRhNHnsKI%2BqxhyM0iVZhTFBom4YIorMPnmg8G0g2OJi%2FzmXHfenomYtn5EW9vzeG8LzfPUwktUBEmkxg5p7bh%2BFbQ%3D&pvid=10_106.6.161.154_3367_1490163222155

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容