關于運行時權限
?在舊的權限管理系統中,權限僅僅在APP安裝時詢問一次,用戶同意了這些權限App才能安裝,APP一旦安裝后就可以偷偷做很多不為人知的事情。
我們知道從Android6.0開始,App可以直接安裝,在運行時需要用到權限的地方,會一個一個詢問用戶授予權限,比如照相,寫SD卡,讀聯系人等,系統會彈出一個對話框讓用戶選擇是否授予權限(這個dialog是各個手機廠商定制的,不能由開發者定制),用戶可以拒絕,可以在每個APP的權限進行管理
特別注意:這個對話框不是開發者調用某個權限的功能是由系統自動彈出的,而不是由開發者手動調用的。
哪些權限需要動態申請
新的權限策略分為兩類:第一類是不涉及用戶隱私的,只需要在manifest中聲明即可,比如網絡,藍牙,NFC等,第二類是涉及用戶隱私信息的,需要用戶授權后才可使用的,比如SD卡讀寫,聯系人,短信讀寫等等
不需要運行時申請的權限:
此類權限都是正常保護的權限,只需要在AndroidManifest.xml中簡單聲明這些權限即可,安裝即授權,不需要每次使用時都檢查權限,而且用戶不能取消以上授權,除非用戶卸載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
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
REQUEST_INSTALL_PACKAGES
SET_ALARM
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
UNINSTALL_SHORTCUT
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
需要運行時申請的權限
所有危險的Android系統權限屬于權限組,如果APP運行在Android 6.0 (API level 23)或者更高級別的設備中,而且targetSdkVersion>=23時,系統將會自動采用動態權限管理策略,如果你在涉及到特殊權限操作時沒有申請權限權限而直接調用了相關代碼,你的App可能就崩潰了,綜上所述你需要注意:
- 此類權限也必須在Manifest中申明,否則申請時不提示用戶,直接回調開發者權限被拒絕。
- 同一個權限組的任何一個權限被授權了,這個權限組的其他權限也自動被授權。例如一旦WRITE_CONTACTS被授權了,App也有READ_CONTACTS和GET_ACCOUNTS了。
- 申請某一個權限的時候系統彈出的Dialog是對整個權限組的說明,而不是單個權限。例如我申請READ_EXTERNAL_STORAGE,系統會提示"允許xxx訪問設備上的照片、媒體內容和文件嗎?
如果App運行在Android 5.1 (API level 22)或者更低級別的設備中,或者targetSdkVersion<=22時(此時設備可以是Android 6.0 (API level 23)或者更高),在所有系統中仍將采用舊的權限管理策略,系統會要求用戶在安裝的時候授予權限。其次,系統就告訴用戶App需要什么權限組,而不是個別的某個權限。
CALENDAR(日歷)
READ_CALENDAR
WRITE_CALENDAR
CAMERA(相機)
CAMERA
CONTACTS(聯系人)
READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION(位置)
ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONE(麥克風)
RECORD_AUDIO
PHONE(手機)
READ_PHONE_STATE
CALL_PHONE
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
SENSORS(傳感器)
BODY_SENSORS
SMS(短信)
SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGE(存儲卡)
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
關于運行時權限的一些建議
防止一次請求太多的權限或請求次數太多,用戶可能對你的應用感到厭煩,在應用啟動的時候,最好先請求應用必須的一些權限,非必須權限在使用的時候才請求,建議整理并按照上述分類管理自己的權限: 普通權限(Normal PNermissions):只需要在Androidmanifest.xml中聲明相應的權限,安裝即許可需要運行時申請的權限(Dangerous Permissions): 必要權限:最好在應用啟動的時候,進行請求許可的一些權限(主要是應用中主要功能需要的權限)。附帶權限:不是應用主要功能需要的權限(如:選擇圖片時,需要讀取SD卡權限)。 解釋你的應用為什么需要這些權限:在你調用requestPermissions()之前,你為什么需要這個權限 例如,一個攝影的App可能需要使用定位服務,因為它需要用位置標記照片。一般的用戶可能會不理解,他們會困惑為什么他們的App想要知道他的位置。所以在這種情況下,所以你需要在requestpermissions()之前告訴用戶你為什么需要這個權限。 使用兼容庫support-v4中的方法
ContextCompat.checkSelfPermission()
ActivityCompat.requestPermissions()
ActivityCompat.shouldShowRequestPermissionRationale()
幾個重要的方法與常量解釋
- PackageManager中的兩個常量:
- PackageManager.PERMISSION_DENIED:該權限是被拒絕的。
- PackageManager.PERMISSION_GRANTED:該權限是被授權的。
- Activity中或者Fragment都會有以下幾個方法:
int checkSelfPermission(String)
void requestPermissions(int, String...)
boolean shouldShowRequestPermissionRationale(String)
void onRequestPermissionsResult()
checkSelfPermission() 檢查權限
檢查某一個權限的當前狀態,你應該在請求某個權限時檢查這個權限是否已經被用戶授權,已經授權的權限重復申請可能會讓用戶產生厭煩。該方法有一個參數是權限名稱,有一個int的返回值,用這個值與上面提到的兩個常量做比較可判斷檢查的權限當前的狀態。
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED) {// 沒有權限,申請權限。
}else{// 有權限了,去放肆吧。
}r
equestPermissions() 申請權限 請求用戶授權幾個權限,調用后系統會顯示一個請求用戶授權的提示對話框,App不能配置和修改這個對話框,如果需要提示用戶這個權限相關的信息或說明,需要在調用 requestPermissions() 之前處理,該方法有兩個參數:? int requestCode,會在回調onRequestPermissionsResult()時返回,用來判斷是哪個授權申請的回調。String[] permissions,權限數組,你需要申請的的權限的數組。 由于該方法是異步的,所以無返回值,當用戶處理完授權操作時,會回調Activity或者Fragment的onRequestPermissionsResult()方法。
對于Activity我們直接調用requestPermissions(int, String[])即可,不過這個方法是在api leve 23以上,所以我們為了適配可以是使用兼容包提供的方法:
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.READ_CONTACTS}, MMM);
onRequestPermissionsResult() 處理權限結果回調 該方法在Activity/Fragment中應該被重寫,當用戶處理完授權操作時,系統會自動回調該方法,該方法有三個參數:? int requestCode,在調用requestPermissions()時的第一個參數。String[] permissions,權限數組,在調用requestPermissions()時的第二個參數。
int[] grantResults,授權結果數組,對應permissions,具體值和上方提到的PackageManager中的兩個常量做比較。
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {switch (requestCode) {case MMM: {if (grantResults.length > 0&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 權限被用戶同意,可以去放肆了。} else {// 權限被用戶拒絕了,洗洗睡吧。}return;}}
}
shouldShowRequestPermissionRationale() 望文生義,是否應該顯示請求權限的說明。第一次請求權限時,用戶拒絕了,調用shouldShowRequestPermissionRationale()后返回true,應該顯示一些為什么需要這個權限的說明。用戶在第一次拒絕某個權限后,下次再次申請時,授權的dialog中將會出現“不再提醒”選項,一旦選中勾選了,那么下次申請將不會提示用戶。第二次請求權限時,用戶拒絕了,并選擇了“不再提醒”的選項,調用shouldShowRequestPermissionRationale()后返回false。設備的策略禁止當前應用獲取這個權限的授權:shouldShowRequestPermissionRationale()返回false 。加這個提醒的好處在于,用戶拒絕過一次權限后我們再次申請時可以提醒該權限的重要性,免得再次申請時用戶勾選“不再提醒”并決絕,導致下次申請權限直接失敗。 f (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {// 沒有權限。if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS)) {// 用戶拒絕過這個權限了,應該提示用戶,為什么需要這個權限。} else {// 申請授權。ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, MMM);}
}...@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {switch (requestCode) {case MMM: {if (grantResults.length > 0&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 權限被用戶同意,可以去放肆了。} else {// 權限被用戶拒絕了,洗洗睡吧。}return;}}
}
從上面來看,判斷很多,邏輯也很多,這樣就加重了我們開發的負擔,加上很多人反饋說國產手機有各種各樣的bug,這樣兼容起來就更加麻煩了,那么下面我就為大家介紹一個開源內褲來解決這一系列問題。
說說Android6.0以上不申請權限直接調用相機的情況: 1,對于國外的手機比如三星,不詢問權限直接調用,會直接崩潰,這符合android原生系統的權限管理策略 2,對于國內手機,比如vivo,不詢問相機權限,照樣會給出彈窗,而且即使勾選“不在提醒”且拒絕權限,下次調用還是照樣彈窗直到用戶授權才能用。這應該是vivo系統定制的,系統幫助應用詢問的權限 3,對于國內手機,魅族系列,不詢問相機權限,依然可以使用相機,猜測是系統給默認授權了。
AndPermission 這個開源庫名叫AndPermission:https://github.com/yanzhenjie/AndPermission,經過我的實踐是完全解決了上述問題,推薦大家使用。
Gradle
compile 'com.yanzhenjie:permission:1.0.6'使用介紹
我建議看官去Github下載Demo并閱讀本文會幫助你理解 https://github.com/yanzhenjie/AndPermission
總結
以上是生活随笔為你收集整理的Android踩坑日记:Android动态权限分析和解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。