Android6.0運行時權限處理

概述

從Android6.0(API23)開始,用戶可以在應用運行時向其授予權限,而不是在應用安裝時授予。 在Android6.0以前,應用安裝會給出應用聲明的權限列表,用戶如果要繼續安裝,就得接受全部的權限,讓用戶很無奈; 從Android6.0開始的運行時權限,讓用戶可以對應用的功能進行更多的控制,例如,用戶可以選擇爲相機應用提供相機的訪問權限,而不提供設備位置的訪問權限。用戶可以隨時進入應用的“Settings”開關權限。

兼容性

  • 如果設備的系統版本是Android5.1或者更低的版本,或者應用的 targetSdkVersion爲22或更低:如果您在清單中列出了危險權限,則用戶必須在安裝應用時授予此權限;如果用戶不授予此權限,系統根本不會安裝應用。
  • 如果設備的系統版本是Android6.0或者更高的版本,或者應用的 targetSdkVersion爲23或更高:應用必須在清單中列出權限,並且它必須在運行時請求其需要的每項危險權限。用戶可以授權或拒絕每項權限,且即使用戶拒絕權限請求,應用仍可以繼續運行有限的功能。

權限分類

系統權限分爲兩類:正常權限和危險權限

Normal Permissions

正常權限,不會直接給用戶隱私權帶來風險。如果您的應用在其清單列出了正常權限,系統將自動授予該權限。

  • ACCESSLOCATIONEXTRA_COMMANDS
  • ACCESSNETWORKSTATE
  • ACCESSNOTIFICATIONPOLICY
  • ACCESSWIFISTATE
  • BLUETOOTH
  • BLUETOOTH_ADMIN
  • BROADCAST_STICKY
  • CHANGENETWORKSTATE
  • CHANGEWIFIMULTICAST_STATE
  • CHANGEWIFISTATE
  • DISABLE_KEYGUARD
  • EXPANDSTATUSBAR
  • FOREGROUND_SERVICE
  • GETPACKAGESIZE
  • INSTALL_SHORTCUT
  • INTERNET
  • KILLBACKGROUNDPROCESSES
  • MANAGEOWNCALLS
  • MODIFYAUDIOSETTINGS
  • NFC
  • READSYNCSETTINGS
  • READSYNCSTATS
  • RECEIVEBOOTCOMPLETED
  • REORDER_TASKS
  • REQUESTCOMPANIONRUNINBACKGROUND
  • REQUESTCOMPANIONUSEDATAIN_BACKGROUND
  • REQUESTDELETEPACKAGES
  • REQUESTIGNOREBATTERY_OPTIMIZATIONS
  • SET_ALARM
  • SET_WALLPAPER
  • SETWALLPAPERHINTS
  • TRANSMIT_IR
  • USE_FINGERPRINT
  • VIBRATE
  • WAKE_LOCK
  • WRITESYNCSETTINGS

Dangerous Permissions

危險權限,會授予應用訪問用戶機密數據的權限。如果您的應用在清單中列出了危險權限,則用戶必須明確批准您的應用使用這些權限。 危險權限是按權限組來劃分,如果你申請某個危險的權限,假設你的app早已被用戶授權了 同一組的某個危險權限,那麼系統會立即授權,而不需要用戶去點擊授權。 例如,你的app對 READ_CONTACTS已經授權了,當你的app申請 WRITE_CONTACTS時,系統會直接授權通過。 NOTE:對應申請時彈出的Dialog上面的文本說明也是對整個權限組的說明,而不是單個權限。

權限組

權限

CALENDAR

READCALENDARWRITECALENDAR

CALL_LOG

READCALLLOGWRITECALLLOGPROCESSOUTGOINGCALLS

CAMERA

CAMERA

CONTACTS

READCONTACTSWRITECONTACTSGET_ACCOUNTS

LOCATION

ACCESSFINELOCATIONACESSCOARSELOCATION

MICROPHONE

RECORD_AUDIO

PHONE

READPHONESTATEREADPHONENUMBERSCALLPHONEADDVOICEMAILUSE_SIP

SENSORS

BODY_SENSORS

SMS

SENDSMSRECEIVESMSREADSMSRECEIVEWAPPUSHRECEIVEMMS

STORAGE

READEXTERNALSTORAGEWRITEEXTERNALSTORAGE

運行時權限處理

檢查權限

如果你的應用需要危險權限,則每次執行需要這一權限的操作時都必須檢查自己是否具有該權限。因爲用戶可以自由的開關此權限,所以,即使應用昨天使用了相機,它不能假設自己今天仍具有該權限。

ContextCompat.checkSelfPermission:用於檢測某個權限是否已經被授予

int permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR);

說明:如果應用具有此權限,方法將返回 PackageManager.PERMISSION_GRANTED,並且允許應用可以繼續操作。如果應用不具有此權限,方法將返回 PackageManager.PERMISSION_DENIED,且應用必須明確向用戶要求權限。

請求權限

如果應用尚無所需的權限,則應用必須調用 requestPermissions()方法,來請求適當的權限。

ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS);

說明:從第二個參數可以看出,支持一次性請求多個權限,系統會通過對話框逐一詢問用戶是否授權。

處理權限請求響應

當應用請求權限時,系統將向用戶顯示一個對話框。當用戶響應時,系統將調用應用的 onRequestPermissionsResult()方法。

@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
    }
}

解釋權限的用途

如果用戶繼續嘗試使用需要某項權限的功能,但拒絕權限請求,則可能表明用戶不理解應用爲什麼需要此權限才能提供相關的功能,這時就可以顯示解釋給用戶。 shouldShowRequestPermissionRationale(): 如果應用之前請求過此權限但用戶拒絕了請求,此方法返回 true; 如果用戶過去拒絕了權限請求,並在權限請求系統對話框選擇了 Don't ask again選項,此方法返回 false

if (ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.READ_CONTACTS)) {
        // Show an expanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.
    } else {
        // No explanation needed, we can request the permission.
        ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS);
        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}

AndPermission的使用

AndPermission是嚴格按照 Android系統的 運行時權限設計的,並最大限度上兼容了國產手機。 庫地址:https://github.com/yanzhenjie/AndPermission

導入

implementation 'com.yanzhenjie:permission:2.0.0-rc12'

使用

申請權限
AndPermission.with(this)
  .runtime()
  .permission(Permission.Group.STORAGE)
  .onGranted(permissions -> {
    // Storage permission are allowed.
  })
  .onDenied(permissions -> {
    // Storage permission are not allowed.
  })
  .start();
權限被拒絕,說明權限用途
private Rationale mRationale = new Rationale() {
    @Override
    public void showRationale(Context context, List<String> permissions, 
            RequestExecutor executor) {
        // 這裏使用一個Dialog詢問用戶是否繼續授權。
        // 如果用戶繼續:
        executor.execute();
        // 如果用戶中斷:
        executor.cancel();
    }
};
AndPermission.with(this)
    .runtime()
    .permission(Permission.WRITE_EXTERNAL_STORAGE)
    .rationale(mRationale)
    .onGranted(...)
    .onDenied(...)
    .start();
權限總是被拒絕,前往設置頁授權
AndPermission.with(this)
    .runtime()
    .permission(...)
    .rationale(...)
    .onGranted(...)
    .onDenied(new Action() {
        @Override
        public void onAction(List<String> permissions) {
            if (AndPermission.hasAlwaysDeniedPermission(context, permissions)) {
                // 這些權限被用戶總是拒絕。
                // 這裏使用一個Dialog展示沒有這些權限應用程序無法繼續運行,詢問用戶是否去設置中授權。
                AndPermission.with(this)
                    .runtime()
                    .setting()
                    .onComeback(new Setting.Action() {
                        @Override
                        public void onAction() {
                            // 用戶從設置回來了。
                        }
                    })
                    .start();
            }
        }
    })
    .start();

參考鏈接

  1. https://blog.csdn.net/lmj623565791/article/details/50709663
  2. https://blog.csdn.net/yanzhenjie1003/article/details/52503533
  3. https://edu.csdn.net/course/play/3539
  4. https://developer.android.com/training/permissions/requesting?hl=zh-cn
  5. https://developer.android.com/about/versions/marshmallow/android-6.0-changes?hl=zh-cn
  6. https://developer.android.com/training/permissions/best-practices?hl=zh-cn#testing
  7. http://www.yanzhenjie.com/AndPermission/cn/runtime/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章