Android6.0動態許可權適配&XMPermissions
從 Android 6.0(API 級別 23)開始,使用者開始在應用執行時向其授予許可權,而不是在應用安裝時授予。此方法可以簡化應用安裝過程,因為使用者在安裝或更新應用時不需要授予許可權。它還讓使用者可以對應用的功能進行更多控制;例如,使用者可以選擇為相機應用提供相機訪問許可權,而不提供裝置位置的訪問許可權。使用者可以隨時進入應用的“Settings”螢幕呼叫許可權。摘自 ofollow,noindex">Android官網:在執行時請求許可權 。
targetSdkVerion
我們在開發的時候需要指定 minSdkVersion
和 targetSdkVerion
。
-
minSdkVersion
為app最低適配的版本,低於該版本的手機無法安裝;
-
targetSdkVerion
簡單來說就代表著你的App能夠適配的系統版本,意味著你的App在這個版本的手機上做了充分的 前向 相容性處理和實際測試。其實我們寫程式碼時都是經常幹這麼一件事,就是 if(Build.VERSION.SDK_INT >= 23) { … } ,這就是相容性處理最典型的一個例子。如果你的target設定得越高,其實呼叫系統提供的API時,所得到的處理也是不一樣的,甚至有些新的API是隻有新的系統才有的;
Android6.0特殊許可權 Special Permissions
看許可權名就知道特殊許可權比危險許可權更危險,特殊許可權需要在manifest中申請並且通過傳送Intent讓使用者在設定介面進行勾。
//SYSTEM_ALERT_WINDOW private static final int REQUEST_CODE = 1; private void requestAlertWindowPermission(){ Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); intent.setData(Uri.parse("package:"+ getPackageName())); startActivityForResult(intent, REQUEST_CODE); } @Override protected void onActivityResult(intrequestCode, intresultCode, Intent data){ super.onActivityResult(requestCode, resultCode, data); if(requestCode == REQUEST_CODE) { if(Settings.canDrawOverlays(this)) { Log.i(LOGTAG, "onActivityResult granted"); } } } //WRITE_SETTINGS 修改系統設定 private static final int REQUEST_CODE_WRITE_SETTINGS = 2; private void requestWriteSettings(){ Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:"+ getPackageName())); startActivityForResult(intent, REQUEST_CODE_WRITE_SETTINGS ); } @Override protected void onActivityResult(intrequestCode, intresultCode, Intent data){ super.onActivityResult(requestCode, resultCode, data); if(requestCode == REQUEST_CODE_WRITE_SETTINGS) { if(Settings.System.canWrite(this)) { Log.i(LOGTAG, "onActivityResult write settings granted"); } } }
Android6.0普通許可權 normal permission
普通許可權不會對使用者的隱私和安全產生太大的風險,所以只需要在AndroidManifest.xml中宣告即可.
Android6.0危險許可權 dangerous permission
- Normal Permission:寫在xml檔案裡,那麼App安裝時就會預設獲得這些許可權,即使是在Android6.0系統的手機上,使用者也無法在安裝後動態取消這些normal許可權,這和以前的許可權系統是一樣的,不變。
- Dangerous Permission:還是得寫在xml檔案裡,但是App安裝時具體如果執行授權分以下幾種情況:
- 1、targetSDKVersion < 23 & API(手機系統) < 6.0 :安裝時預設獲得許可權,且使用者無法在安裝App之後取消許可權。
- 3、targetSDKVersion < 23 & API(手機系統) >= 6.0 :安裝時預設獲得許可權,但是使用者可以在安裝App完成後動態取消授權( 取消時手機會彈出提醒,告訴使用者這個是為舊版手機打造的應用,讓使用者謹慎操作 )。
- 2、targetSDKVersion >= 23 & API(手機系統) < 6.0 :安裝時預設獲得許可權,且使用者無法在安裝App之後取消許可權。
- 4、targetSDKVersion >= 23 & API(手機系統) >= 6.0 :安裝時不會獲得許可權,可以在執行時向用戶申請許可權。使用者授權以後仍然可以在設定介面中取消授權,使用者主動在設定介面取消後,在app執行過程中可能會出現crash。
Dangerous permissions and permission groups(危險許可權和許可權組)
同一組的任何一個許可權被授權了,其他許可權也自動被授權。例如,一旦WRITE_CONTENTS被授權了,APP也有READ_CONTACTS和GET_ACCOUNTS了。
permission-group | dangerous permissions |
---|---|
CALENDAR(日曆) | READ_CALENDAR , WRITE_CALENDAR |
CAMERA(照相機) | CAMERA |
CONTACTS(聯絡人) | READ_CONTACTS , WRITE_CONTACTS , GET_ACCOUNTS |
LOCATION(位置) | ACCESS_FINE_LOCATION (訪問精細的位置), ACCESS_COARSE_LOCATION(訪問粗略的位置) |
MICROPHONE(麥克風) | RECORD_AUDIO(錄音) |
PHONE(手機) | READ_PHONE_STATE , CALL_PHONE , READ_CALL_LOG , WRITE_CALL_LOG , ADD_VOICEMAIL(新增語音信箱) , USE_SIP(使用SIP協議 , PROCESS_OUTGOING_CALLS(程式撥出電話) |
SENSORS(感測器) | BODY_SENSORS |
SMS | SEND_SMS , RECEIVE_SMS , READ_SMS , RECEIVE_WAP_PUSH , RECEIVE_MMS |
TORAGE(儲存) | READ_EXTERNAL_STORAGE ,WRITE_EXTERNAL_STORAGE |
如何開始動態申請許可權
判斷許可權是否具有某項許可權
ContextCompat.checkSelfPermission(Context context,String permission); ActivityCompat.checkSelfPermission(Context context, String permission); activity.checkSelfPermission(String permission);
申請許可權
ActivityCompat.requestPermissions(Activity activity,String[] permissions,int requestCode); activity.requestPermissions(String[] permissions, int requestCode); //申請許可權回撥方法,在Activity或Fragment重寫 onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
是否要提示使用者申請該許可權的緣由,sdk小於23恆為false
ActivityCompat.shouldShowRequestPermissionRationale(Activity activity, String permission) 0、之前沒有拒絕過此許可權的申請(第一次安裝後請求許可權前呼叫):false 1、曾經被拒絕過許可權後再呼叫:true 2、曾經被拒絕過許可權且不再詢問後再呼叫:false 3、系統不允許任何程式獲取該許可權:false 4、檢視原始碼得知安卓6.0以下返回:false 5、總是允許許可權後再次呼叫:false
在APP使用過程中,從設定中更改許可權
如果應用程式的某個業務邏輯需要使用許可權,但使用者沒有選擇開啟。那麼最好引導使用者去設定介面修改應用程式的許可權。
XMPermissions
導讀
如果我們應用需要動態申請危險許可權,按照Google官方問檔我們需要在 activity
或者 fragment
中的 onRequestPermissionsResult
方法進行回撥處理。一個執行任務程式碼需要分開寫在兩處地方,這我們的程式碼會變得很不優雅。
有沒有鏈式、流式或者註解的方式去解決這個問題?有而且很多,以下是我在 github
上找的 start
最多的開源庫。
RxPermissions RxJava流式用法;
XXPermissions 鏈式用法;
permissions4m 註解用法;
個人對註解使用不太感冒,而且專案有用到Rxjava的地方。
綜上所述,我在 RxPermissions
和 XXPermissions
基礎上開發了 XMPermissions 。
依賴
implementation 'com.tzx.lib:xmpermission:1.0.0'
使用
public interface OnPermission { /** * 本次申請的許可權全部通過 */ void hasPermission(); /** * 本次申請的許可權沒有全部通過 * @param granteds */ void noPermission(List<PermissionState> granteds); }
RxJava
XMPermissions.with(this) .request(Permission.Group.STORAGE, Permission.Group.PHONE) .subscribe(new SimpleSubscriber<List<PermissionState>>() { @Override public void onNext(List<PermissionState> permissionStates) { for (PermissionState s: permissionStates) { Log.d("tanzhenxing:", s.toString()); } } });
鏈式呼叫
XMPermissions.with(this) //.constantRequest() //可設定被拒絕後繼續申請,直到使用者授權或者永久拒絕 .permission(Permission.Group.STORAGE, Permission.Group.CALENDAR) .request(new OnPermission() { @Override public void hasPermission() { Toast.makeText(MainActivity.this, "獲取許可權成功", Toast.LENGTH_SHORT).show(); } @Override public void noPermission(List<PermissionState> granteds) { for (PermissionState s: granteds) { Log.d("tzx:", s.toString()); } } });
跳轉到應用許可權設定頁面
XMPermissions.gotoPermissionSettings(content);
6.0動態許可權適配總結
有了 XMPermissions 適配6.0動態許可權就非常簡單了。將 targetVersion
升級到 23
,然後每個使用 儲存、定位、電話、相機、錄音
等危險許可權的地方做許可權的 check
。
當然這麼做非常麻煩像 儲存、定位、電話
這三個許可權我們幾乎每次介面訪問都需要獲取,所以我們可以將一些許可權申請在應用啟動前置。
儲存、定位、電話 儲存、電話 定位、電話 電話 儲存
在進行簡訊傳送和打電話時,不需要許可權也可以哦~!我自己測試了4個主流廠商的8款手機。
隨著 Android
系統的不斷更新,後續後問題會繼續同步噠~!
文章到這裡就全部講述完啦,若有其他需要交流的可以留言哦~!~!
想閱讀作者的更多文章,可以檢視我個人部落格 和公共號:
