Android6.0運行時權限管理

自從Android6.0發佈以來,在權限上作出了很大的變更,再也不是以前的只要在manifest設置就能夠任意獲取權限,而是更加的注重用戶的隱私和體驗,不會再強迫用戶因拒毫不該擁有的權限而致使的沒法安裝的事情,也不會再不徵求用戶受權的狀況下,就能夠任意的訪問用戶隱私,並且即便在受權以後也能夠及時的更改權限。這就是6.0版本作出的更擁護和注重用戶的一大致現。android

1、認知

今天咱們就來學習下Android6.0的權限管理。安全

Android6.0系統把權限分爲兩個級別:微信

一個是Normal Permissions,即普通權限,這類權限不會潛藏有侵害用戶隱私和安全的問題,好比,訪問網絡的權限,訪問WIFI的權限等;網絡

另外一類是Dangerous Permissions,即危險權限,這類權限會直接的威脅到用戶的安全和隱私問題,好比說訪問短信,相冊等權限。框架

可是到底哪些是普通權限和危險權限呢,這裏給出分類,你們在使用時以便參考。佈局

一、Normal Permissions (普通權限)學習

  • 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

使用以上權限是不會威脅到用戶安全的,因此這類權限是能夠直接的在manifest裏面直接的使用,並且在安裝後也會直接的生效了。gradle

二、Dangerous Permissions (危險權限)優化

  • SMS(短信)
    • SEND_SMS
    • RECEIVE_SMS
    • READ_SMS
    • RECEIVE_WAP_PUSH
    • RECEIVE_MMS
  • STORAGE(存儲卡)
    • READ_EXTERNAL_STORAGE
    • WRITE_EXTERNAL_STORAGE
  • CONTACTS(聯繫人)
    • READ_CONTACTS
    • WRITE_CONTACTS
    • GET_ACCOUNTS
  • PHONE(手機)
    • READ_PHONE_STATE
    • CALL_PHONE
    • READ_CALL_LOG
    • WRITE_CALL_LOG
    • ADD_VOICEMAIL
    • USE_SIP
    • PROCESS_OUTGOING_CALLS
  • CALENDAR(日曆)
    • READ_CALENDAR
    • WRITE_CALENDAR
  • CAMERA(相機)
    • CAMERA
  • LOCATION(位置)
    • ACCESS_FINE_LOCATION
    • ACCESS_COARSE_LOCATION
  • SENSORS(傳感器)
    • BODY_SENSORS
  • MICROPHONE(麥克風)
    • RECORD_AUDIO

危險權限和普通權限也有區別,普通權限是單條的權限,而危險權限是以組展現的,也就是說,當你接受一個危險權限時,不但但接受的是界面上展現的這一個權限,而是它所在這個組裏面的其餘全部訪問權限也將會被自動獲取權限,好比,一旦WRITE_CONTACTS被受權了,App也有READ_CONTACTS和GET_ACCOUNTS的權限了。
值得注意的是,這類權限也是須要在manifest中註冊的。ui

ok,光說不練不是咱的風格,咱寫東西都是基於本身遇到的問題,而後認真的學習後才記錄下來的。一方面鞏固本身的知識,另外一方面也但願能幫助他人提供一點解決方案。

2、實戰

實戰部分分爲幾種狀況,由於根據咱們的目標SDK版本和Android真機版本的不一樣會有不一樣的情景,針對普通權限你們都熟悉,就不介紹了,下面一一介紹危險權限的使用情景:

在介紹使用情景以前,先看下個人開發和真機的Android版本。

咱們這裏以讀取短信息爲例講解整個權限的使用:

一、沒有訪問權限的狀況下:

首先咱們先來設計下佈局,以下:

看下代碼,很簡單,就直接讀取短息:

而後,點擊界面上的「讀取收件箱中的短信」,相信你們都會知道發生什麼狀況,果真不出意外的程序直接崩潰了,打下日誌:

日誌中很清晰的告訴咱們,這個異常是由於沒有權限而形成的,那麼咱們就直接給它加上讀取短信的權限來看看吧。

二、在manifest中添加了權限:

在manifest中加了對讀取短信的權限,你應該很高興的等待着總共有多少條短信出如今咱們的界面上,可是,事實很讓人崩潰:

再次出現了沒有權限的異常,這是爲何呢?

這裏咱們先不解決這個問題,先來想象一種實際的狀況,假如你現有的APP裏面有不少使用到了危險權限,有時候你並徹底清楚到底在哪裏使用了,可是你的目標版本又是像個人版本同樣指向了6.0,而有可能用戶的手機是6.0以上的版本,那麼這時候你的APP就有可能會出現這種,那麼在你還沒查清楚有哪些地方使用了危險權限是,該怎麼解決呢?

那麼你能夠這麼解決:

修改你build.gradle 中的 targetSdkVersion 目標版本號:

而後手機版本仍是6.0以上,來看看結果:

能夠了,哈哈,你很高興,確實是能夠了。

那麼聰明的你或許意識到什麼了,是的,以版本23,也就是android6.0位分割線,咱們能夠得出一個小結論:

當targetSdkVersion >= 23,且真機版本 >= 23時,即便在manifest中添加了相應的危險權限,在沒有作相應的處理時(至於怎麼處理後面會講),還時會出現限權的異常,這時manifest中的危險權限並無起做用,可是還必須聲明。

當targetSdkVersion < 23,且真機版本 >= 23時,咱們並無作任何的相關處理,就獲得了想要的訪問權限,這說明在manifest中申請的危險權限起做用了。

咱們在來看另一種狀況,就是,假如個人手機比較舊,還沒更新6.0的系統,這種狀況下又該是什麼狀況呢?

此次咱們用個4.4.4版本的模擬機

目標targetSdkVersion 爲21 來看看結果:

也是能夠的,0條信息是由於個人模擬機上沒短信,這個數字多少和咱們沒有關係。假如targetSdkVersion 爲23呢,來看看結果:

很清晰的看出,咱們又獲得了正確的結果。

由此咱們也獲得了一個小結論:

當咱們的真機系統版本 < 23時,無論咱們的targetSdkVersion 值是否大於23,都不會影響咱們在manifest裏面申請的權限,也就是說這時候真機的系統版本在起着主導做用。

由上面的幾條結論,咱們應該很清晰的知道了訪問權限在真機中的使用情況,可是咱們的手機在升級,版本也會愈來愈高,所以咱們如今的應用不可能一直只支持低版本的使用也不考慮兼顧高版本。因此如今APP權限升級是必然的趨勢。

那麼如今回來解決上面遺留的問題,當真機和目標版本都大於6.0時出現的權限異常咱們該怎麼解決呢?

主要分爲三個步驟:

1:檢查是否擁有權限

2:假如沒有權限,則申請權限

3:處理權限回調

下面咱們分別來看看這幾個步驟。

1:檢查是否擁有權限

檢查是否已擁有了權限,可使用ContextCompat.checkSelfPermission(Context context, String permission);

checkSelfPermission方法中有兩個參數,分別是上下文,以及所申請的權限。

若是有權限,請讓它直接去讀取短信信息。若是沒有權限則去申請。

2:申請權限

申請權限則是使用:

public static void requestPermissions(final Activity activity,final String[] permissions, final int requestCode) {}

requestPermissions方法中須要三個參數,當前的activity,所申請的權限,能夠是多個,最後就是請求碼,既然有請求碼說明它會有一個回調,也就是咱們下面要講的處理回調。

3:處理權限回調

處理權限回調,須要在Activity中重寫onRequestPermissionsResult方法:

而後在方法內判斷用戶是受權了該權限組仍是拒絕受權,若是受權則就去獲取短信信息,不然,在這裏我只是顯示了一個toast提示框。

這裏再次說明下,權限組內只要有一個被受權,其餘的權限也就有了權限,這也是爲何直接使用grantResults[0] == PackageManager.PERMISSION_GRANTED的緣由。

ok,下面來具體的界面顯示:

咱們能夠看到,當咱們第一次點擊讀取短信時,它會先檢查該應用是否有權限,若是沒有,就去申請,這裏在界面上對應的就是顯示一個受權的對話框,第一次咱們選擇了拒絕受權,而後在回調裏面就會對應先打印了咱們的一個toast消失提醒咱們拒絕了受權,可是當咱們再次須要讀取短信時,它還會去申請受權,這時咱們容許受權,而後咱們就看到了,在顯示短信條數的TextView顯示了短信的條數。(這裏0條是由於的用的模擬器沒有短信,這不是重點。)

值得提醒的事,當咱們第一次選擇拒絕受權時,當再次點擊讀取短信時,這時在受權對話框中會多一個「再也不提醒」的提示,當咱們在拒絕了受權,並選擇再也不提醒時,那麼會出現什麼狀況呢?請看演示:

當屢次拒絕並選擇不提提醒,那麼下次再去讀取就不會在去申請受權,而是直接在回調中說明用戶已拒絕受權。

那麼這時候假如用戶出於某種須要必須得給應用受權該怎麼作呢,其實很簡單,在回調中,提醒用戶去「設置」裏面手動給應用受權,或是發個廣播打開設置界面等等均可,這裏和我顯示的提醒「權限已被拒絕」基本同樣,只需在稍微優化便可,這裏不在演示。

其實到這裏已經差很少講完,可是,有一個方法咱們能夠留一下,那就是shouldShowRequestPermissionRationale,這個方法默認返回false,但當用戶在上一次已經拒絕過這個權限申請時,再次須要申請該權限時,就會返回ture,它的寓意是你已經拒絕了一次,結果又彈出個受權框,你須要給我一個解釋,爲何要受權,也就是說對屢次受權這個權限作出解釋,以便用戶知道爲何必須受權了纔可以完成他操做。

下面,來看看它的使用:

我這裏就簡單的彈出個對話框,說明下爲何要用這個權限,而後再次去調用這個申請的權限的方法了,你們能夠同回調的方法一塊兒封裝下,能夠更好的應用。

看下界面操做:

講到這裏基本差不地講完了,這裏只是講了單個申請權限,多個一塊兒也是能夠的,你們能夠本身試試,基本是同樣的操做,另外在說明一點,可能咱們一個應用裏,須要多出的使用到危險權限,這樣就形成咱們須要屢次重寫同樣的代碼,很不便利,因此網上也就出現了不少關於權限框架的開源代碼,你們能夠自行的使用。

ok,到這裏就結束了,但願你們能學到點知識,同時也多本身的實操下,祝你們生活愉快。

更多資訊請關注微信平臺,有博客更新會及時通知。愛學習愛技術。

相關文章
相關標籤/搜索