問題背景
隨著今年Android6.0系統(tǒng)的國產(chǎn)ROM終于來了去扣,適配6.0已經(jīng)勢在必行了涩蜘。最近也有很多開發(fā)者在微信私聊和咨詢我遇到的問題绿语,其中有一些都是關(guān)于Android6.0權(quán)限的弥姻,我感覺有必要寫一篇文章來解惑了蓖宦。Runtime Permissions在6.0系統(tǒng)的幾個變化中,還是比較大的茄厘。
如果你在Android6.0系統(tǒng)的手機(jī)上如果遇到了這樣的錯誤矮冬,必定跟其運行時權(quán)限有關(guān)谈宛。
open failed: EACCES (Permission denied)
權(quán)限變化
在Adroid系統(tǒng)6.0以前次哈,權(quán)限的處理是在App安裝時授權(quán),授權(quán)完了才能完成相關(guān)的安裝吆录。而在6.0的系統(tǒng)上窑滞,是先安裝App,在安裝完之后,在使用相關(guān)權(quán)限的操作時哀卫,才會彈出權(quán)限的提示框巨坊,用戶同意授權(quán)之后才能正常使用。谷歌這樣做此改,可以讓用戶更加清醒的認(rèn)識相關(guān)權(quán)限的使用趾撵,在一定程度上更加人性化和保護(hù)了用戶的隱私。
谷歌官方將權(quán)限分為了兩類共啃,一個是正常權(quán)限(Normal Permissions)占调,這類權(quán)限不涉及用戶隱私,是不需要用戶進(jìn)行授權(quán)的移剪,比如訪問網(wǎng)絡(luò)究珊,手機(jī)震動等。還有一類是危險權(quán)限(Dangerous Permissions)纵苛,一般是涉及到用戶隱私的剿涮,需要用戶進(jìn)行授權(quán),比如操作SD卡的寫入攻人,相機(jī)取试,錄音等。
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:
解決方法
看完官方文檔贝椿,還好解決方案還不是太難想括,也不是非常麻煩,當(dāng)然和以前相比還是有一點繁瑣的烙博。廢話不多說了瑟蜈,解決方案如下。
檢查系統(tǒng)版本
private boolean canMakeSmores(){
return(Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP_MR1);
}
檢查系統(tǒng)版本的原因渣窜,顯而易見铺根,如果是系統(tǒng)6.0及以上的,需要采用新的權(quán)限授權(quán)方法乔宿。
授權(quán)回調(diào)處理
@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
switch(permsRequestCode){
case 200:
boolean cameraAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
if(cameraAccepted){
//授權(quán)成功之后位迂,調(diào)用系統(tǒng)相機(jī)進(jìn)行拍照操作等
}else{
//用戶授權(quán)拒絕之后,友情提示一下就可以了
}
break;
}
}
進(jìn)一步處理和完善
通過上面可以看出详瑞,只檢查系統(tǒng)版本了掂林,如果授權(quán)過的權(quán)限,還需要再次去授權(quán)么坝橡?我們的判斷其實可以更完善一下泻帮,比如:
private boolean hasPermission(String permission){
if(canMakeSmores()){
return(checkSelfPermission(permission)==PackageManager.PERMISSION_GRANTED);
}
return true;
}
上面這段代碼,是先判斷系統(tǒng)版本计寇,再判斷這個權(quán)限是否已經(jīng)授權(quán)過锣杂,這樣就不會重復(fù)了脂倦。
還有就是比如如果用戶第一次已經(jīng)拒絕過這個權(quán)限,下次再操作時怎么辦呢元莫?還有一個更人性化的方法就是:
shouldShowRequestPermissionRationale(@NonNull String permission)
這個方法的作用:
第一次請求權(quán)限時赖阻,用戶拒絕了,下一次:shouldShowRequestPermissionRationale() 返回 true踱蠢,應(yīng)該顯示一些為什么需要這個權(quán)限的說明
第二次請求權(quán)限時火欧,用戶拒絕了,并選擇了“不在提醒”的選項時:shouldShowRequestPermissionRationale() 返回 false
設(shè)備的策略禁止當(dāng)前應(yīng)用獲取這個權(quán)限的授權(quán):shouldShowRequestPermissionRationale() 返回 false
完結(jié)
到這里就基本介紹完結(jié)了茎截,希望能夠?qū)Υ蠹矣兴鶐椭几簦軌蜻M(jìn)一步理解Android6.0運行時權(quán)限的使用。繼續(xù)加油吧稼虎,學(xué)習(xí)永無止境衅檀。