Android 6.0開始動態請求權限

轉載請註明來源: http://blog.csdn.net/kjunchen/article/details/51366845

動態請求權限

從Android 6.0(API 23)開始,允許用戶在應用運行時決定是否允許權限,而不是在應用安裝的時候。這種方法簡化了應用的安裝過程,因爲用戶在安裝或更新應用的時候不需要允許權限。他也讓用戶對應用的功能有更多的控制;例如,用戶可以選擇給予相機應用相機的權限但是不允許使用設備位置的權限。用戶可進入應用設置隨時撤銷權限。

系統權限被分爲兩種類型,正常的(normal)和敏感的(dangerous):

  • 正常的權限不會直接讓用戶的隱私處於危險中。如果你的應用在清單文件中列入了正常的權限,系統會自動允許這些權限。

  • 敏感權限給予應用方位用戶的機密數據。如果你的應用在清單文件中列入危險類權限,會明確地讓用戶對你的應用允許權限。

更多信息請看 Normal and Dangerous Permissions.

在所有的Android版本中,你的應用需要在清單文件中去申明它需要的正常的和危險的權限。然而,聲明的影響是不同的,依賴於系統版本和你應用的目標SDK等級:

  • 如果設備運行在Android 5.1或更低,或者你的應用的 target SDK是22或者更低;如果你在清單文件中加入了敏感權限,當他們在安裝應用的時候必須同意權限;如果他們不同意權限,系統則不會安裝應用。

  • 如果設備運行在Android 6.0或更高的版本,或者你的應用的 target SDK是23或者更高。應用必須在manifest文件中加入權限,而且在應用運行過程中必須在它需要的時候請求每一個危險的權限。用戶可以允許或者拒絕每一個權限,即使用戶拒絕了一個權限的請求而應用可以在限制功能地繼續運行。

注意: 從Android6.0(API 23)開始,用戶可以在任何時候撤銷任何應用的權限,即使應用目標SDK低於23。你應該測試你的用用驗證它正常的表現當它缺少需要的權限,不管你的應用的target SDK等級是多少。

檢查權限

如果你的應用需要一個敏感權限,你必須檢查是否具有權限當你每次執行一個操作需要一個權限時。用戶總是可以自由地撤銷權限,所以,即使應用昨天使用了相機,但是今天可能沒有相機權限。

爲了檢查你是否有該權限,調用 ContextCompat.checkSelfPermission()方法。例如,下面片段展示瞭如何檢查一個Activity是否具有日曆權限:

// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
        Manifest.permission.WRITE_CALENDAR);

如果一個用擁有權限,這個方法會返回 PackageManager.PERMISSION_GRANTED ,應用可以繼續進行操作。如果應用沒有權限,方法會返回 PERMISSION_DENIED ,應用必須去想用戶請求該權限。

請求權限

如果你的應用需要一個敏感權限加入到manifest文件中,他必須徵求用戶允許權限。Android提供了一些方法讓你可以去請求一個權限。調用這些方法會彈出一個標準的Android彈出框,你不能自定義。

解釋你的應用爲什麼需要權限

在某些情況中,你可能想要幫助用戶理解你的應用個爲什麼需要一個權限。例如,如果一個用戶運行一個相機應用,應用請求使用相機權限,用戶對此並不會感到驚奇,但是,用戶並不理解爲什麼應用想要訪問用戶的位置或者聯繫人。在你請求一個權限之前,你應該考慮向用戶提供一個解釋。記住,如果你不想用解釋說服用戶;如果你提供太多的解釋,用戶可能發現應用令他沮喪並卸載它。

如果用戶已經關閉了權限請求,你可能需要提供一個解釋。如果用戶堅持嘗試使用一個功能但需要請求一個權限,但總是關閉權限請求,可能說明用戶沒有理解應用爲什麼需要該功能這個權限。在這種情況下,去展示一個解釋可能是一個好主意。

爲了幫助這種情況,用戶可能需要一個解釋,Android提供了一個實用的方法,shouldShowRequestPermissionRationale() 。如果應用以前請求過這個權限並且被用戶拒絕了那麼這個方法會返回 true

注意: 如果用戶在權限請求系統彈出框關閉權限請求而且選擇不在提示,這個方法返回 false 。如果一個設備已經禁止了應用的那個權限這個方法也會返回 false

請求你需要的權限

如果你的應用沒有你需要的權限,你必須調用 requestPermissions() 方法去請求合適的權限。你的應用通過權限請求,會有一個整型的請求碼唯一標識這個權限請求。這個方法是異步的,當用戶操作這個彈出框後他會立即返回,系統調用應用的回調方法跟結果。

下面代碼是檢查應用是否有權限去閱讀用的聯繫人,如果有需要就請求權限:

// Here, thisActivity is the current activity
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.
    }
}

注意: 當你的應用調用 requestPermissions()方法時,系統會向用戶展示標準的對話框。你不能配置或者修對話框。如果你需要想用提供任何信息或者解釋,你應該在調用 requestPermissions() 前去進行操作,正如 解釋你的應用爲什麼需要權限 中的描述。

處理權限請求響應

當你的應用請求權限時,系統會想用展示一個對話框。當用戶做出回覆後,系統會調用你應用的 onRequestPermissionsResult() 方法。你的應用必須重寫這個方法,去找出權限是否被允許。這個回調接口跟requestPermissions()方法有一個相同的請求碼。例如,如果一個應用請求 READ_CONTACTS 訪問,他的回調方法可能像下面這樣:

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

對話框會展示你的應用需要的權限所述的權限組,它不會列出具體的權限。例如,如果你請求 READ_CONTACTS 權限,系統對話框僅僅說你的應用需要訪問設備的聯繫人。對於每個權限組用戶只需要允許一次。如果你的應用請求任何其他的權限在那個組裏,系統會自動地允許他們。當你請求權限時,如果用戶在系統對話框中已經明確的允許你的請求,系統調用onRequestPermissionsResult() 方法,並且通過 PERMISSION_GRANTED

注意: 你的應用仍然需要明確地請求每一個它需要的權限,即使用戶已經允許了同組裏的另一個權限。另外,在未來的Android版本中羣組的權限分組可能會有改變。你的代碼不應該依賴特定的權限是不是在一個組裏。

例如,假設你應用的manifest文件中既有 READ_CONTACTS 權限又有 WRITE_CONTACTS 權限。如果你請求 READ_CONTACTS 並且用戶允許了改權限,然後你請求 WRITE_CONTACTS ,系統會立即允許權限而不和用戶交互。

如果用戶拒絕一個權限請求,你的應用應該採取適當的處理。例如,你的應用可能展示一個對話框,解釋它爲什麼需要權限去執行用戶請求的操作。

當系統詢問用戶允許權限時,用戶可以有選擇的告訴系統不用在此詢問權限。在這種情況下,任何時候,應用使用 requestPermissions() 方法去在次請求權限時,系統會立即拒絕請求。如果用戶已經明確的拒絕了你的請求,系統會調用 onRequestPermissionsResult() 方法並且通過PERMISSION_DENIED 。這意味着當你調用 requestPermissions() 方法時,你不能在用戶操作的地方產生預期的效果。

正常權限(Normal Permissions)

在API 23中,下面權限被定義爲正常權限

  • 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

敏感權限(Dangerous permissions)

Permission Group Permissions
CALENDAR READ_CALENDARWRITE_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, 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

原文鏈接

鄙人英語能力有限,翻譯難免有誤,請讀者多多包含! 也歡迎指正。

歡迎加QQ羣交流: 365532949
Homepage: http://junkchen.com

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章