關(guān)于6.0以上權(quán)限:新的權(quán)限機(jī)制更好的保護(hù)了用戶的隱私,Google將權(quán)限分為兩類,一類是Normal Permissions,這類權(quán)限一般不涉及用戶隱私,是不需要用戶進(jìn)行授權(quán)的,比如手機(jī)震動、訪問網(wǎng)絡(luò)等;另一類是Dangerous
Permission,一般是涉及到用戶隱私的,需要用戶進(jìn)行授權(quán),比如讀取sdcard、訪問通訊錄等。
不需要運(yùn)行時(shí)申請的權(quán)限
此類權(quán)限都是正常保護(hù)的權(quán)限,只需要在AndroidManifest.xml中簡單聲明這些權(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í)申請的權(quán)限
所有危險(xiǎn)的Android系統(tǒng)權(quán)限屬于權(quán)限組,如果APP運(yùn)行在Android 6.0 (API level 23)或者更高級別的設(shè)備中,而且targetSdkVersion>=23時(shí),系統(tǒng)將會自動采用動態(tài)權(quán)限管理策略,如果你在涉及到特殊權(quán)限操作時(shí)沒有申請權(quán)限權(quán)限而直接調(diào)用了相關(guān)代碼,你的App可能就崩潰了,綜上所述你需要注意:
此類權(quán)限也必須在Manifest中申明,否則申請時(shí)不提示用戶,直接回調(diào)開發(fā)者權(quán)限被拒絕。
同一個(gè)權(quán)限組的任何一個(gè)權(quán)限被授權(quán)了,這個(gè)權(quán)限組的其他權(quán)限也自動被授權(quán)。例如一旦WRITE_CONTACTS被授權(quán)了,App也有READ_CONTACTS和GET_ACCOUNTS了。
申請某一個(gè)權(quán)限的時(shí)候系統(tǒng)彈出的Dialog是對整個(gè)權(quán)限組的說明,而不是單個(gè)權(quán)限。例如我申請READ_EXTERNAL_STORAGE,系統(tǒng)會提示"允許xxx訪問設(shè)備上的照片、媒體內(nèi)容和文件嗎?"。
如果App運(yùn)行在Android 5.1 (API level 22)或者更低級別的設(shè)備中,或者targetSdkVersion<=22時(shí)(此時(shí)設(shè)備可以是Android 6.0 (API level 23)或者更高),在所有系統(tǒng)中仍將采用舊的權(quán)限管理策略,系統(tǒng)會要求用戶在安裝的時(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(存儲卡)
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
關(guān)于運(yùn)行時(shí)權(quán)限的一些建議
只請求你需要的權(quán)限,減少請求的次數(shù),或用隱式Intent來讓其他的應(yīng)用來處理。
如果你使用Intent,你不需要設(shè)計(jì)界面,由第三方的應(yīng)用來完成所有操作。比如打電話、選擇圖片等。
如果你請求權(quán)限,你可以完全控制用戶體驗(yàn),自己定義UI。但是用戶也可以拒絕權(quán)限,就意味著你的應(yīng)用不能執(zhí)行這個(gè)特殊操作。
防止一次請求太多的權(quán)限或請求次數(shù)太多,用戶可能對你的應(yīng)用感到厭煩,在應(yīng)用啟動的時(shí)候,最好先請求應(yīng)用必須的一些權(quán)限,非必須權(quán)限在使用的時(shí)候才請求,建議整理并按照上述分類管理自己的權(quán)限:
普通權(quán)限(Normal PNermissions):只需要在Androidmanifest.xml中聲明相應(yīng)的權(quán)限,安裝即許可。
需要運(yùn)行時(shí)申請的權(quán)限(Dangerous Permissions):
必要權(quán)限:最好在應(yīng)用啟動的時(shí)候,進(jìn)行請求許可的一些權(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)記照片。一般的用戶可能會不理解,他們會困惑為什么他們的App想要知道他的位置。所以在這種情況下,所以你需要在requestpermissions()之前告訴用戶你為什么需要這個(gè)權(quán)限。
使用兼容庫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都會有以下幾個(gè)方法:
intcheckSelfPermission(String)voidrequestPermissions(int, String...)booleanshouldShowRequestPermissionRationale(String)voidonRequestPermissionsResult()
上述四個(gè)方法中,前三個(gè)方法在support-v4的ActivityCompat中都有,建議使用兼容庫中的方法。最后一個(gè)方法是用戶授權(quán)或者拒絕某個(gè)權(quán)限組時(shí)系統(tǒng)會回調(diào)Activity或者Fragment中的方法。
checkSelfPermission() 檢查權(quán)限
檢查某一個(gè)權(quán)限的當(dāng)前狀態(tài),你應(yīng)該在請求某個(gè)權(quán)限時(shí)檢查這個(gè)權(quán)限是否已經(jīng)被用戶授權(quán),已經(jīng)授權(quán)的權(quán)限重復(fù)申請可能會讓用戶產(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) {// 沒有權(quán)限,申請權(quán)限。}else{// 有權(quán)限了,去放肆吧。}
requestPermissions() 申請權(quán)限
請求用戶授權(quán)幾個(gè)權(quán)限,調(diào)用后系統(tǒng)會顯示一個(gè)請求用戶授權(quán)的提示對話框,App不能配置和修改這個(gè)對話框,如果需要提示用戶這個(gè)權(quán)限相關(guān)的信息或說明,需要在調(diào)用 requestPermissions() 之前處理,該方法有兩個(gè)參數(shù):
int requestCode,會在回調(diào)onRequestPermissionsResult()時(shí)返回,用來判斷是哪個(gè)授權(quán)申請的回調(diào)。
String[] permissions,權(quán)限數(shù)組,你需要申請的的權(quán)限的數(shù)組。
由于該方法是異步的,所以無返回值,當(dāng)用戶處理完授權(quán)操作時(shí),會回調(diào)Activity或者Fragment的onRequestPermissionsResult()方法。
對于Activity我們直接調(diào)用requestPermissions(int, String[])即可,不過這個(gè)方法是在api leve 23以上,所以我們?yōu)榱诉m配可以是使用兼容包提供的方法:
ActivityCompat.requestPermissions(activity,newString[]{Manifest.permission.READ_CONTACTS}, MMM);
1
對于support包的Fragment就可以直接調(diào)用requestPermissions(int, String[]),對于app包的Fragment就需要做版本判斷了,這樣就顯得比較麻煩。
onRequestPermissionsResult() 處理權(quán)限結(jié)果回調(diào)
該方法在Activity/Fragment中應(yīng)該被重寫,當(dāng)用戶處理完授權(quán)操作時(shí),系統(tǒ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ù)組,對應(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)該顯示請求權(quán)限的說明。
第一次請求權(quán)限時(shí),用戶拒絕了,調(diào)用shouldShowRequestPermissionRationale()后返回true,應(yīng)該顯示一些為什么需要這個(gè)權(quán)限的說明。
用戶在第一次拒絕某個(gè)權(quán)限后,下次再次申請時(shí),授權(quán)的dialog中將會出現(xiàn)“不再提醒”選項(xiàng),一旦選中勾選了,那么下次申請將不會提示用戶。
第二次請求權(quán)限時(shí),用戶拒絕了,并選擇了“不再提醒”的選項(xiàng),調(diào)用shouldShowRequestPermissionRationale()后返回false。
設(shè)備的策略禁止當(dāng)前應(yīng)用獲取這個(gè)權(quán)限的授權(quán):shouldShowRequestPermissionRationale()返回false 。
加這個(gè)提醒的好處在于,用戶拒絕過一次權(quán)限后我們再次申請時(shí)可以提醒該權(quán)限的重要性,免得再次申請時(shí)用戶勾選“不再提醒”并決絕,導(dǎo)致下次申請權(quán)限直接失敗。