1. 程式人生 > >Android6.0動態許可權適配&XMPermissions

Android6.0動態許可權適配&XMPermissions

Permissions

Android6.0動態許可權

簡介

從 Android 6.0(API 級別 23)開始,使用者開始在應用執行時向其授予許可權,而不是在應用安裝時授予。此方法可以簡化應用安裝過程,因為使用者在安裝或更新應用時不需要授予許可權。它還讓使用者可以對應用的功能進行更多控制;例如,使用者可以選擇為相機應用提供相機訪問許可權,而不提供裝置位置的訪問許可權。使用者可以隨時進入應用的“Settings”螢幕呼叫許可權。摘自Android官網:在執行時請求許可權

targetSdkVerion

我們在開發的時候需要指定minSdkVersiontargetSdkVerion

  • minSdkVersion
    為app最低適配的版本,低於該版本的手機無法安裝;
  • targetSdkVerion簡單來說就代表著你的App能夠適配的系統版本,意味著你的App在這個版本的手機上做了充分的 前向 相容性處理和實際測試。其實我們寫程式碼時都是經常幹這麼一件事,就是 if(Build.VERSION.SDK_INT >= 23) { … } ,這就是相容性處理最典型的一個例子。如果你的target設定得越高,其實呼叫系統提供的API時,所得到的處理也是不一樣的,甚至有些新的API是隻有新的系統才有的;

看許可權名就知道特殊許可權比危險許可權更危險,特殊許可權需要在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"); } } }

普通許可權不會對使用者的隱私和安全產生太大的風險,所以只需要在AndroidManifest.xml中宣告即可.

  • 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 最多的開源庫。

個人對註解使用不太感冒,而且專案有用到Rxjava的地方。 綜上所述,我在RxPermissionsXXPermissions 基礎上開發了 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

當然這麼做非常麻煩像儲存、定位、電話這三個許可權我們幾乎每次介面訪問都需要獲取,所以我們可以將一些許可權申請在應用啟動前置。

  • 轉轉:儲存、定位、電話前置
  • 59同城: 儲存、電話前置
  • 京東: 定位、電話前置
  • 手機淘寶: 電話前置
  • 手機百度: 儲存前置

在進行簡訊傳送和打電話時,不需要許可權也可以哦~!我自己測試了4個主流廠商的8款手機。

隨著Android系統的不斷更新,後續後問題會繼續同步噠~!

文章到這裡就全部講述完啦,若有其他需要交流的可以留言哦

想閱讀作者的更多文章,可以檢視我 個人部落格 和公共號:振興書城