Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android資訊 >> 談談Android 6.0運行時權限理解

談談Android 6.0運行時權限理解

編輯:Android資訊

前言

谷歌在2015年8月份時候,發布了Android 6.0版本,代號叫做“棉花糖”(Marshmallow ),其中的很大的一部分變化,是在用戶權限授權上,或許是感覺之前默認授權的不合理,現在6.0出來,使得用戶權限授權變得合理。這可能也是參考IOS系統的,只有在用戶需要使用權限的時候,才去授權請求,這樣做的目的是提高用戶體驗,當然,用戶感覺好了,受苦的是我們開發人員,原來的規則不適用了,現在我們去適應新的規則,畢竟是靠谷歌這顆大樹吃飯的嘛。

原來權限模型

在Android 6.0版本之前,權限都是一條龍服務的,只要用戶安裝完 , AndroidManifest清單上申請的權限都會被系統默認授權,並且授權後也撤銷不了。這樣的弊端在哪裡呢?有些權限可能用戶覺得不需要,比如他不想有通知的權限,不想受到通知的干擾,那麼他就不能屏蔽通知,就是不需要的權限,他去不掉,自主權不在他那邊。還有一些情況是,一些惡意程序,會利用這個權限默認授權,進行惡意獲取用戶數據和攻擊。所以Android 6.0版本,一方面讓用戶更加容易的控制自己的隱私,一方面需要重新適配應用權限。

Android 6.0權限模型

采用新的權限模型,只有在需要權限的時候,才告知用戶是否授權,是在runtime時候授權,而不是在原來安裝的時候 ,同時默認情況下每次在運行時打開頁面時候,需要先檢查是否有所需要的權限申請。這樣的用戶的自主性提高很多,比如用戶可以給APP賦予攝像的權限,但是可以拒絕記錄設備位置的權限,就是怕位置信息上傳等等。

權限流程

在API 23中,權限滿足的標准流程:

談談Android 6.0運行時權限理解

但這裡有個問題,那就是在系統授權彈窗環節,提醒框會有個不再提示的復選框,如果用戶點擊不太提示,並拒絕授權,那麼再下次授權的時候,系統授權彈窗的提示框就不會在提示,所以我們很有必要需要自定義權限彈窗提示框,那麼流程圖就變成如下了。

談談Android 6.0運行時權限理解

權限類型

談談Android 6.0運行時權限理解

在圖中,我們可以看到整個權限裡,可以分為系統權限和特殊權限授權。系統權限中,又分為normal和dangerous類型。

normal:這個權限類型並不直接威脅到用戶的隱私,可以直接在manifest清單裡注冊,系統會幫我們默認授權的。

dangerous:這個可以直接給app訪問用戶一些敏感的數據,不僅需要在manifest清單裡注冊,同時在使用的時候,需要向系統請求授權。

值得注意一點,這裡有特殊權限授權的區別,分別是SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS,雖然這兩個權限也是屬於dangerous權限類型,但是這兩個授權請求方式和其他dangerous權限是不一樣的,需要特殊處理 。

normal列表:

  • 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
  • INTERNET
  • KILL_BACKGROUND_PROCESSES
  • MODIFY_AUDIO_SETTINGS
  • NFC
  • READ_SYNC_SETTINGS
  • READ_SYNC_STATS
  • RECEIVE_BOOT_COMPLETED
  • REORDER_TASKS
  • REQUEST_INSTALL_PACKAGES
  • SET_TIME_ZONE
  • SET_WALLPAPER
  • SET_WALLPAPER_HINTS
  • TRANSMIT_IR
  • USE_FINGERPRINT
  • VIBRATE
  • WAKE_LOCK
  • WRITE_SYNC_SETTINGS
  • SET_ALARM
  • INSTALL_SHORTCUT
  • UNINSTALL_SHORTCUT

dangerous列表:

Permission Group 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
  • 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

版本兼容

當然,谷歌也是考慮到如果是以API 23之前的版本編譯的APP,在6.0的系統上運行,還是能兼容的。如果是23之前的版本編譯的APP,則權限模型走的是老的模式,也就是在一條龍的模式,在manifest清單注冊,系統會幫我們默認授權,並且也能運行。

但如果是以API 23的版本編譯的APP,那走的的必須是新的權限模型,在遇到dangerous權限的時候,必須進行授權的,如果沒有進行授權話,系統則會提示崩潰信息。所以,基於6.0系統的開發的程序, 在打開頁面的時候,必須要考慮這個頁面是否用到需要授權的權限,頁面檢測是否已經授權過了沒。

實現方式

第一步:檢測權限

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

第二步:請求權限

// 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.
    }
}

第三步:處理權限請求結果

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

其中要特別注意的是,如果是針對

“android.permission.SYSTEM_ALERT_WINDOW”
“android.permission.WRITE_SETTINGS”

這兩個權限,實現方式跟上 之前在工作中,碰到一種情況,如果是運行在6.0的版本上是需要走新的權限模型,如果是運行在老的版本上,則需要進行一個判斷,此時碰到一個問題是, 在谷歌官方推薦中,在判斷app運行的系統是否在Android M上時,它的判斷是如下:  Build.VERSION.CODENAME.equals(“MNC”); 可是在我實際適配中,發現這句卻無效的,就改用Build.VERSION.SDK_INT >= 23。的,需要另外特殊處理。

針對SYSTEM_ALERT_WINDOW權限,需要向系統發送一個 ACTION_MANAGE_OVERLAY_PERMISSION .這樣一個動作,同時可以用 Settings.canDrawOverlays() 方法進行判斷之前是否已經授權過了。

針對WRITE_SETTINGS權限,需要向系統發送一個 ACTION_MANAGE_WRITE_SETTINGS 這樣一個動作,同時可以用 Settings.System.canWrite() . 方法進行判斷之前是否已經授權過了。

具體代碼:

Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

注意點

之前在工作中,碰到一種情況,如果是運行在6.0的版本上是需要走新的權限模型,如果是運行在老的版本上,則需要進行一個判斷,此時碰到一個問題是,在谷歌官方推薦中,在判斷app運行的系統是否在Android M上時,它的判斷是如下:  Build.VERSION.CODENAME.equals(“MNC”); 可是在我實際適配中,發現這句卻無效的,就改用Build.VERSION.SDK_INT >= 23。

談談Android 6.0運行時權限理解

總結

  1. 首先要知道6.0版本權限模型跟原來版本是不同的,不再是統一在manifest中默認系統授權,而是有需要的時候,向系統請求授權,提高用戶體驗。
  2. 了解權限檢測流程,一點注意點是如果系統權限彈窗提示框被不再提醒了,需要我們自定義提示彈窗,引導用戶去授權。
  3. 明白權限類型,分為normal和dangerous類型,同時,在dangerous中還需要注意一點,SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS這兩個特殊授權請求方式,跟一般授權請求方式不同。
  4. 在判斷APP是否運行在Android M上,可以用版本號來判斷,可以准確點。

參考

有個具體demo: https://github.com/SpikeKing/wcl-permission-demo

流程圖: http://blog.csdn.net/caroline_wendy/article/details/50587230

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved