我的APP簡記在豌豆莢上線之后,我叫同學幫我下載測試一下,結果卻驚奇的發現在我的小米2s測試機上跑得好好的,在他們同樣是小米,同樣是MIUI8的手機上卻不能調出拍照,會直接退出程序,也就是傳說中的閃退,于是我把手機連上Android Studio調試,結果出現了這樣的Log:open failed: EACCES (Permission denied);
后來我想到小米2s和小米5雖然都是MIUI8,但是好像Android 版本不同,2s好像是Android 5.0,5則是6.0以上,我記得6.0以上的系統好像要動態申請權限,而不是只是簡單的在AndroidManifest中申明就行了,于是我上網查了下。
?
權限分類
由于6.0以前的系統都是在安裝時詢問權限,而6.0以后運行時詢問,也就是動態權限管理,在6.0以上的系統分為Normal Permissions,和Dangerous Permissions。Normal Permissions就是不用動態申請的權限,而Dangerous Permissions就是需要動態申請的權限。
Normal Permissions:
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_INSTALL_PACKAGES
SET_ALARM
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
UNINSTALL_SHORTCUT
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
Dangerous Permissions:
動態申請
例如現在我要調用相機,那么我就要知道我現在的系統是否時大于6.0.就調用如下方法:
private boolean OverLollipop(){
return(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1);
}
如果返回True,就繼續動態申請權限操作,如果是Lollipop以下,不需要動態申請,就直接調用相機即可。
然后申請權限:
String[] perms = {"android.permission.CAMERA"};
int permsRequestCode = 200;
requestPermissions(perms, permsRequestCode);
這個requestPermissions和startActivityForResult很像,會返回到onRequestPermissionsResult方法
@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
switch(permsRequestCode){
case 200:
boolean cameraAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
if(cameraAccepted){
//授權成功之后,調用系統相機進行拍照操作等
}else{
//用戶授權拒絕之后,友情提示一下就可以了
}
break;
}
}
在這個方法里進行拍照操作即可。
優化邏輯
但是難道用戶每次都需要被這樣彈出的申請權限的對話框打擾嗎?很明顯我們需要判斷以前用戶有沒有允許過權限,如果之前就允許過了,就不用再申請了,那么我們把OverLollipop也集成到hasPermission中。
private boolean hasPermission(String permission){
if(OverLollipop()){
return(checkSelfPermission(permission)== PackageManager.PERMISSION_GRANTED);
}
return true;
}
那么這樣的話就不用重復申請權限了。
Thanks to Android6.0運行時權限的處理及解決辦法