Android6.0運行時權限簡

Android6.0發佈距離現在快1年了,雖然它市場佔有率仍在龜速上升中,但還是有一些App開發者已經在打包應用時將targetSDKVersion設置到了23,也就是說把App適配到了Android6.0。以前調用Android系統中需要聲明權限的API時,只需要在AndroidManifest.xml文件中一次性列出來。但是如果在build.gradle文件裏將targetSDKVersion設爲23以後,除了在AndroidManifest.xml聲明,我們還需要根據App運行時所在的手機的系統版本,在調用權限之前向用戶申請授權,並在用戶允許以後,纔可以安全的調用對應的API。

簡單舉個例子,我的App有一個地理位置讀取的功能,需要ACCESS_COARSE_LOCATION(粗略的地理位置信息)權限,如果Apk是以targetSDKVersion=22的方式進行打包的,那麼在安裝時用戶將不得授權我的App這個權限,否則他將無法安裝這個應用;如果是以targetSDKVersion=23的形式打包的,而且用戶使用的手機是Android6.0的系統,那麼在安裝時我的App是沒有獲得讀取地理位置權限的,我們需要調用系統提供的requestPermissions接口來申請權限。這時候你可能會說那我還設置targetSDKVersion=23幹嘛?還不如直接用22打包得了。。

不要高興得太早,下面我們會說理由。因爲只要用戶使用的是6.0系統的手機,他是可以在安裝完成以後,在手機的設置界面取消一些dangerous權限的。

下圖就是6.0系統上權限管理的界面。

app-cancel-perm

targetSDKVersion和compileSDKVersion的作用

build.gradle中有這麼一段:

android {

    compileSdkVersion 23
    buildToolsVersion "23.0.2"
    ...
    
    defaultConfig {
        ...
        targetSdkVersion 22
        ...
    }

  • targetSDKVersion:簡單來說就代表着你的App能夠適配的系統版本,意味着你的App在這個版本的手機上做了充分的前向兼容性處理和實際測試。其實我們寫代碼時都是經常幹這麼一件事,就是if(Build.VERSION.SDK_INT >= 23) { ... },這就是兼容性處理最典型的一個例子。如果你的target設置得越高,其實調用系統提供的API時,所得到的處理也是不一樣的,甚至有些新的API是隻有新的系統纔有的,例如前一篇博客裏用到WebView的setWebContentsDebuggingEnabled(boolean))方法,這是Android4.4以後纔可以用的一個API。

  • compileSdkVersion:是你SDK的版本號,也就是你在編程時引用的android.jar的版本。一般都會和targetSDKVersion相等,或者比targetSDKVersion高。

因此,如果我們要把自己的App適配到Android6.0系統,首先要把targetSDKVersioncompileSDKVersion全部設置爲23

Android6.0運行時權限系統到底是幹嘛的?

介紹了targetSDKVersion和compileSDKVersion以後,我們就知道什麼叫做適配到Android X.X了。那麼Android6.0這個運行時權限系統和以前最大的不同就在於:將我們以前一股腦兒以<permission>標籤方式寫在AndroidManifest.xml文件中的權限劃分成了normal permission 和 dangerous permission

  • Normal Permission:你寫在xml文件裏,那麼App安裝時就會默認獲得這些權限,即使是在Android6.0系統的手機上,用戶也無法在安裝後動態取消這些normal權限,這和以前的權限系統是一樣的,不變。

  • Dangerous Permission:你還是得寫在xml文件裏,但是App安裝時具體如果執行授權分以下幾種情況:

    • targetSDKVersion < 23 & API(手機系統) < 6.0:安裝時默認獲得權限,且用戶無法在安裝App之後取消權限。
    • targetSDKVersion >= 23 & API(手機系統) < 6.0:安裝時默認獲得權限,且用戶無法在安裝App之後取消權限。
    • targetSDKVersion < 23 & API(手機系統) >= 6.0:安裝時默認獲得權限,但是用戶可以在安裝App完成後動態取消授權(取消時手機會彈出提醒,告訴用戶這個是爲舊版手機打造的應用,讓用戶謹慎操作)。
    • targetSDKVersion >= 23 & API(手機系統) >= 6.0:安裝時不會獲得權限,可以在運行時向用戶申請權限。用戶授權以後仍然可以在設置界面中取消授權。

6.0手機上取消授權的界面如下,如果是targetSDKVersion < 23打包的應用,取消權限時,會:

app-權限

我們可以看到其實只有在6.0的機器上,打包了適配到6.0的App,才需要做一些明顯的權限適配工作。但是實話說,不論是不是適配6.0系統,我們都應該在調用需要權限的接口前,檢查一下是否具有具有該權限。因爲我們會遇到廠商的修改過權限系統的ROM,也有可能自己忘記在xml里加上權限清單。當然這裏面也會有坑,因爲有時在不同廠商手機上直接調用checkCallingOrSelfPermission方法得到的結果並不準確。

如果我不target到23會怎麼樣?

很顯然,如果不target到23,短期內還可以不寫權限適配的代碼。但是!!!前面提到了,用戶仍然可以在6.0的手機上取消安裝時默認賦予的dangerous權限。那麼這時候會發生什麼????如果這個API原本應該返回的是對象,那麼這時將返回null;如果這個API原本應該返回的是數字,這時就是0。可想而知,如果你只是對返回的null或者0做了一些不恰當的處理,App還是可能會crash的。所以這不是長久之計,儘快地處理好權限申請纔是王道,這也是一種對App、對用戶更負責的做法。

如何在運行時申請權限 & 官方的權限分級列表

  • 關於如何適配到6.0的權限系統,網上有非常多的例子,我覺得看了這篇文章基本上就OK了,因爲網上很多貌似都翻譯自這篇文章,強力推薦一下:things-you-need-to-know-about-android-m-permission

  • Google官方的RuntimePermissions介紹:runtime-permissions

  • Google官方的dangerous權限及分組:permissions: normal-dangerous

  • 開源社區-權限適配組件:偉大的開源社區已經有輪子了,可以學習一下!

    • PermissionHelper
    • PermissionsDispatcher
    • PermissionGen
    • TedPermission:不用自己調用checkSelfPermission(), requestPermissions(),然後再處理回調onRequestPermissionsResult(), onActivityResult()。只要一行代碼,設置一個listener就可以監聽授權的結果,使用起來非常簡單。內部實現採用的是類似event bus的otto實現的。

舉個栗子(坑):WRITE_EXTERNAL_STORGE的Android6.0適配問題

見下篇博客Android6.0權限適配之WRITE_EXTERNAL_STORAGE(SD卡寫入)


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