Android M 開始,App不會在安裝的時候授予權限,而是在運行時一個一個的詢問用戶授予權限。html
1. 運行時權限僅當咱們設置targetSdkVersion >= 23才起做用,固然還要是M系統的手機。app在6.0以前的設備依然使用舊的權限系統。java
2. 若是app的targetSdkVersion < 23,或者手機版本 < 6.0 ,那將被認爲app沒有用23新權限測試過,那將被繼續使用舊有規則:用戶在安裝的時候不得不接受全部權限,安裝後app就有了那些權限咯!android
注意,此時用戶依然能夠取消已經贊成的受權!用戶取消受權時,android 6.0系統會警告,但這不妨礙用戶取消受權。app
當咱們在targetSdkVersion 低於23的App調用一個須要權限的函數時,這個權限若是被用戶取消受權了的話,不拋出異常。可是他將啥都不幹,結果致使函數返回值是null或者0。ide
2、官網流程翻譯函數
官網:https://developer.android.com/training/permissions/index.html測試
在AndroidManifest.xml中聲明this
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.snazzyapp"> <uses-permission android:name="android.permission.SEND_SMS"/> <application ...> ... </application> </manifest>
權限分正常和危險兩種,正常的權限和之前同樣,只須要在Manifest.xml中聲明便可,在App安裝時,自動分配權限,且用戶也不能夠在設置中取消權限;危險權限須要運行時申請。spa
權限組,將危險權限分組,同一個組裏的任何一個權限被受權了,其餘權限也自動被受權。翻譯
下面是權限表格
Permission Group | Permissions |
---|---|
CALENDAR |
|
CAMERA |
|
CONTACTS |
|
LOCATION |
|
MICROPHONE |
|
PHONE |
|
SENSORS |
|
SMS |
|
STORAGE |
(1) 檢測是否已經受權
/** * Determine whether <em>you</em> have been granted a particular permission. * * @param permission The name of the permission being checked. * * @return {@link PackageManager#PERMISSION_GRANTED} if you have the * permission, or {@link PackageManager#PERMISSION_DENIED} if not. * * @see PackageManager#checkPermission(String, String) * @see #checkCallingPermission(String) */ checkSelfPermission(String)
(2) 請求權限
shouldShowRequestPermissionRationale()
判斷是否須要爲權限申請向用戶友好提示
返回true,上次申請權限,用戶選擇拒絕。
返回false
第一次申請,或上次申請權限,用戶選擇拒絕,並選擇了「不在提醒」的選項;
設備的策略禁止當前應用獲取這個權限的受權。
注意:第二次請求權限時,纔會有「不在提醒」的選項,若是用戶一直拒絕,並無選擇「不在提醒」的選項,下次請求權限時,會繼續有「不在提醒」的選項。
顯示權限說明:是根據你的應用中使用的權限分類來的:
1.用戶容易知道應用須要獲取的權限:如一個拍照應用,須要攝像頭的權限,是很正常,不用提示。
2.一些用戶感受困惑的一些權限:如:分享圖片,還須要獲取位置的權限,這個須要提示用戶:爲何須要這個權限。
若是用戶拒絕某受權。下一次彈框,用戶會有一個「再也不提醒」的選項的來防止app之後繼續請求受權。
若是這個選項在拒絕受權前被用戶勾選了。下次爲這個權限請求requestPermissions時,對話框就不彈出來了,結果就是,app啥都不幹。
這將是不好的用戶體驗,用戶作了操做卻得不到響應。這種狀況須要好好處理一下。
final private int REQUEST_CODE_ASK_PERMISSIONS = 123; private void insertDummyContactWrapper() { int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.WRITE_CONTACTS); if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) { if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)) { showMessageOKCancel("You need to allow access to Contacts", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { requestPermissions(new String[] {Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_ASK_PERMISSIONS); } }); return; } requestPermissions(new String[] {Manifest.permission.WRITE_CONTACTS}, REQUEST_CODE_ASK_PERMISSIONS); return; } insertDummyContact(); }
(3) 處理請求返回結果
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_READ_CONTACTS: { // if request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted, yay! // Do the contacts-related task you need to do. } else { // permission denied, boo! // Disable the functionality that depends on this permission. } return; } // other 'case' lines to check for other // permissions this app might request } }
3. Permissions Best Practices 權限申請最佳實踐
1. 若是不須要對數據有特別的控制權的話,能夠採起用Intent呼起系統應用的方式來避免申請權限,好比Camera、contacts、phone call,都是能夠直接調用系統app的。
注意打電話操做雖然是用的Intent方式,若是是這樣的寫法context.startActivity(new Intent("android.intent.action.CALL", Uri.parse(formatter.format(tel)))); 也要申請權限;若是是用的 android.intent.action.DIAL來調起的話,就不須要。
2. 只申請須要的權限,且只在須要的時候申請。