關(guān)于6.0以上權(quán)限:新的權(quán)限機(jī)制更好的保護(hù)了用戶的隱私揉稚,Google將權(quán)限分為兩類灰瞻,一類是Normal Permissions牺荠,這類權(quán)限一般不涉及用戶隱私卫玖,是不需要用戶進(jìn)行授權(quán)的期虾,比如手機(jī)震動(dòng)原朝、訪問(wèn)網(wǎng)絡(luò)等;另一類是Dangerous
Permission镶苞,一般是涉及到用戶隱私的喳坠,需要用戶進(jìn)行授權(quán),比如讀取sdcard茂蚓、訪問(wèn)通訊錄等壕鹉。
不需要運(yùn)行時(shí)申請(qǐng)的權(quán)限
此類權(quán)限都是正常保護(hù)的權(quán)限,只需要在AndroidManifest.xml中簡(jiǎn)單聲明這些權(quán)限即可聋涨,安裝即授權(quán)晾浴,不需要每次使用時(shí)都檢查權(quán)限,而且用戶不能取消以上授權(quán)牍白,除非用戶卸載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
需要運(yùn)行時(shí)申請(qǐng)的權(quán)限
所有危險(xiǎn)的Android系統(tǒng)權(quán)限屬于權(quán)限組,如果APP運(yùn)行在Android 6.0 (API level 23)或者更高級(jí)別的設(shè)備中茂腥,而且targetSdkVersion>=23時(shí)笙各,系統(tǒng)將會(huì)自動(dòng)采用動(dòng)態(tài)權(quán)限管理策略,如果你在涉及到特殊權(quán)限操作時(shí)沒(méi)有申請(qǐng)權(quán)限權(quán)限而直接調(diào)用了相關(guān)代碼础芍,你的App可能就崩潰了杈抢,綜上所述你需要注意:
此類權(quán)限也必須在Manifest中申明,否則申請(qǐng)時(shí)不提示用戶仑性,直接回調(diào)開發(fā)者權(quán)限被拒絕惶楼。
同一個(gè)權(quán)限組的任何一個(gè)權(quán)限被授權(quán)了,這個(gè)權(quán)限組的其他權(quán)限也自動(dòng)被授權(quán)诊杆。例如一旦WRITE_CONTACTS被授權(quán)了歼捐,App也有READ_CONTACTS和GET_ACCOUNTS了。
申請(qǐng)某一個(gè)權(quán)限的時(shí)候系統(tǒng)彈出的Dialog是對(duì)整個(gè)權(quán)限組的說(shuō)明晨汹,而不是單個(gè)權(quán)限豹储。例如我申請(qǐng)READ_EXTERNAL_STORAGE,系統(tǒng)會(huì)提示"允許xxx訪問(wèn)設(shè)備上的照片淘这、媒體內(nèi)容和文件嗎剥扣?"巩剖。
如果App運(yùn)行在Android 5.1 (API level 22)或者更低級(jí)別的設(shè)備中,或者targetSdkVersion<=22時(shí)(此時(shí)設(shè)備可以是Android 6.0 (API level 23)或者更高)钠怯,在所有系統(tǒng)中仍將采用舊的權(quán)限管理策略佳魔,系統(tǒng)會(huì)要求用戶在安裝的時(shí)候授予權(quán)限。其次晦炊,系統(tǒng)就告訴用戶App需要什么權(quán)限組赂蠢,而不是個(gè)別的某個(gè)權(quán)限结榄。
CALENDAR(日歷)
READ_CALENDAR
WRITE_CALENDAR
CAMERA(相機(jī))
CAMERA
CONTACTS(聯(lián)系人)
READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION(位置)
ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONE(麥克風(fēng))
RECORD_AUDIO
PHONE(手機(jī))
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(存儲(chǔ)卡)
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
關(guān)于運(yùn)行時(shí)權(quán)限的一些建議
只請(qǐng)求你需要的權(quán)限,減少請(qǐng)求的次數(shù)耳璧,或用隱式Intent來(lái)讓其他的應(yīng)用來(lái)處理郊酒。
如果你使用Intent合敦,你不需要設(shè)計(jì)界面瘟忱,由第三方的應(yīng)用來(lái)完成所有操作瞧柔。比如打電話、選擇圖片等宋彼。
如果你請(qǐng)求權(quán)限弄砍,你可以完全控制用戶體驗(yàn)仙畦,自己定義UI输涕。但是用戶也可以拒絕權(quán)限,就意味著你的應(yīng)用不能執(zhí)行這個(gè)特殊操作慨畸。
防止一次請(qǐng)求太多的權(quán)限或請(qǐng)求次數(shù)太多莱坎,用戶可能對(duì)你的應(yīng)用感到厭煩,在應(yīng)用啟動(dòng)的時(shí)候寸士,最好先請(qǐng)求應(yīng)用必須的一些權(quán)限檐什,非必須權(quán)限在使用的時(shí)候才請(qǐng)求,建議整理并按照上述分類管理自己的權(quán)限:
普通權(quán)限(Normal PNermissions):只需要在Androidmanifest.xml中聲明相應(yīng)的權(quán)限弱卡,安裝即許可乃正。
需要運(yùn)行時(shí)申請(qǐng)的權(quán)限(Dangerous Permissions):
必要權(quán)限:最好在應(yīng)用啟動(dòng)的時(shí)候,進(jìn)行請(qǐng)求許可的一些權(quán)限(主要是應(yīng)用中主要功能需要的權(quán)限)婶博。
附帶權(quán)限:不是應(yīng)用主要功能需要的權(quán)限(如:選擇圖片時(shí)瓮具,需要讀取SD卡權(quán)限)。
解釋你的應(yīng)用為什么需要這些權(quán)限:在你調(diào)用requestPermissions()之前凡人,你為什么需要這個(gè)權(quán)限名党。
例如,一個(gè)攝影的App可能需要使用定位服務(wù)挠轴,因?yàn)樗枰梦恢脴?biāo)記照片传睹。一般的用戶可能會(huì)不理解,他們會(huì)困惑為什么他們的App想要知道他的位置岸晦。所以在這種情況下欧啤,所以你需要在requestpermissions()之前告訴用戶你為什么需要這個(gè)權(quán)限睛藻。
使用兼容庫(kù)support-v4中的方法
ContextCompat.checkSelfPermission()
ActivityCompat.requestPermissions()
ActivityCompat.shouldShowRequestPermissionRationale()
幾個(gè)重要的方法與常量解釋
PackageManager中的兩個(gè)常量:
PackageManager.PERMISSION_DENIED:該權(quán)限是被拒絕的。
PackageManager.PERMISSION_GRANTED:該權(quán)限是被授權(quán)的堂油。
Activity中或者Fragment都會(huì)有以下幾個(gè)方法:
intcheckSelfPermission(String)voidrequestPermissions(int, String...)booleanshouldShowRequestPermissionRationale(String)voidonRequestPermissionsResult()
上述四個(gè)方法中修档,前三個(gè)方法在support-v4的ActivityCompat中都有,建議使用兼容庫(kù)中的方法府框。最后一個(gè)方法是用戶授權(quán)或者拒絕某個(gè)權(quán)限組時(shí)系統(tǒng)會(huì)回調(diào)Activity或者Fragment中的方法吱窝。
checkSelfPermission() 檢查權(quán)限
檢查某一個(gè)權(quán)限的當(dāng)前狀態(tài),你應(yīng)該在請(qǐng)求某個(gè)權(quán)限時(shí)檢查這個(gè)權(quán)限是否已經(jīng)被用戶授權(quán)迫靖,已經(jīng)授權(quán)的權(quán)限重復(fù)申請(qǐng)可能會(huì)讓用戶產(chǎn)生厭煩院峡。
該方法有一個(gè)參數(shù)是權(quán)限名稱,有一個(gè)int的返回值系宜,用這個(gè)值與上面提到的兩個(gè)常量做比較可判斷檢查的權(quán)限當(dāng)前的狀態(tài)照激。
if(ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS)? ? ? ? != PackageManager.PERMISSION_GRANTED) {// 沒(méi)有權(quán)限,申請(qǐng)權(quán)限盹牧。}else{// 有權(quán)限了俩垃,去放肆吧。}
requestPermissions() 申請(qǐng)權(quán)限
請(qǐng)求用戶授權(quán)幾個(gè)權(quán)限汰寓,調(diào)用后系統(tǒng)會(huì)顯示一個(gè)請(qǐng)求用戶授權(quán)的提示對(duì)話框口柳,App不能配置和修改這個(gè)對(duì)話框,如果需要提示用戶這個(gè)權(quán)限相關(guān)的信息或說(shuō)明有滑,需要在調(diào)用 requestPermissions() 之前處理跃闹,該方法有兩個(gè)參數(shù):
int requestCode,會(huì)在回調(diào)onRequestPermissionsResult()時(shí)返回毛好,用來(lái)判斷是哪個(gè)授權(quán)申請(qǐng)的回調(diào)望艺。
String[] permissions,權(quán)限數(shù)組肌访,你需要申請(qǐng)的的權(quán)限的數(shù)組找默。
由于該方法是異步的,所以無(wú)返回值吼驶,當(dāng)用戶處理完授權(quán)操作時(shí)惩激,會(huì)回調(diào)Activity或者Fragment的onRequestPermissionsResult()方法。
對(duì)于Activity我們直接調(diào)用requestPermissions(int, String[])即可旨剥,不過(guò)這個(gè)方法是在api leve 23以上咧欣,所以我們?yōu)榱诉m配可以是使用兼容包提供的方法:
ActivityCompat.requestPermissions(activity,newString[]{Manifest.permission.READ_CONTACTS}, MMM);
1
對(duì)于support包的Fragment就可以直接調(diào)用requestPermissions(int, String[]),對(duì)于app包的Fragment就需要做版本判斷了轨帜,這樣就顯得比較麻煩魄咕。
onRequestPermissionsResult() 處理權(quán)限結(jié)果回調(diào)
該方法在Activity/Fragment中應(yīng)該被重寫,當(dāng)用戶處理完授權(quán)操作時(shí)蚌父,系統(tǒng)會(huì)自動(dòng)回調(diào)該方法哮兰,該方法有三個(gè)參數(shù):
int requestCode毛萌,在調(diào)用requestPermissions()時(shí)的第一個(gè)參數(shù)。
String[] permissions喝滞,權(quán)限數(shù)組阁将,在調(diào)用requestPermissions()時(shí)的第二個(gè)參數(shù)。
int[] grantResults右遭,授權(quán)結(jié)果數(shù)組做盅,對(duì)應(yīng)permissions,具體值和上方提到的PackageManager中的兩個(gè)常量做比較窘哈。
@OverridepublicvoidonRequestPermissionsResult(intrequestCode, String permissions[],int[] grantResults) {switch(requestCode) {caseMMM: {if(grantResults.length >0&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 權(quán)限被用戶同意吹榴,可以去放肆了。}else{// 權(quán)限被用戶拒絕了滚婉,洗洗睡吧图筹。}return;? ? ? ? }? ? }}
shouldShowRequestPermissionRationale()
望文生義,是否應(yīng)該顯示請(qǐng)求權(quán)限的說(shuō)明让腹。
第一次請(qǐng)求權(quán)限時(shí)远剩,用戶拒絕了,調(diào)用shouldShowRequestPermissionRationale()后返回true骇窍,應(yīng)該顯示一些為什么需要這個(gè)權(quán)限的說(shuō)明瓜晤。
用戶在第一次拒絕某個(gè)權(quán)限后,下次再次申請(qǐng)時(shí)像鸡,授權(quán)的dialog中將會(huì)出現(xiàn)“不再提醒”選項(xiàng)活鹰,一旦選中勾選了哈恰,那么下次申請(qǐng)將不會(huì)提示用戶只估。
第二次請(qǐng)求權(quán)限時(shí),用戶拒絕了着绷,并選擇了“不再提醒”的選項(xiàng)蛔钙,調(diào)用shouldShowRequestPermissionRationale()后返回false。
設(shè)備的策略禁止當(dāng)前應(yīng)用獲取這個(gè)權(quán)限的授權(quán):shouldShowRequestPermissionRationale()返回false 荠医。
加這個(gè)提醒的好處在于吁脱,用戶拒絕過(guò)一次權(quán)限后我們?cè)俅紊暾?qǐng)時(shí)可以提醒該權(quán)限的重要性,免得再次申請(qǐng)時(shí)用戶勾選“不再提醒”并決絕彬向,導(dǎo)致下次申請(qǐng)權(quán)限直接失敗兼贡。