1. 程式人生 > >Android M Permission 學習筆記

Android M Permission 學習筆記

Android應用許可權簡要介紹

一個Android應用預設情況下是不擁有任何許可權的, 這即是說, 在預設情況下, 一個應用是沒有權利去進行一些可能會造成不好影響的操作的. 這些不好的影響可能是對其它應用,作業系統,或者是使用者. 如果應用需要一些額外的能力,則它需要在AndroidManifest.xml中靜態地宣告相應的許可權. 如果應用沒有在manifest中宣告許可權, 卻使用了相應的功能, 在呼叫到相應功能的時候, 將會丟擲異常. 比如程式要傳送一個請求,卻忘記加Internet許可權, 那麼在傳送這個請求的時候程式就會丟擲異常,一般不會catch這個異常,所以程式直接就崩潰了: Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?)
Android 6.0 (API 23) 釋出之前, 所有的許可權都在安裝應用的時候顯示給使用者,使用者選擇安裝則表示全部接受這些許可權, 之後無法撤銷對這些許可權的授權. Android 6.0開始, 一部分比較危險的許可權需要在程式執行時顯式彈框,請求使用者授權. 至於什麼時候彈這個框,由應用程式自己決定. 對於其他許可權,認為不是很危險,所以仍然保持原來的做法,在使用者安裝應用程式時就予以授權. 還需要注意的是,在設定中,對於應用的危險許可權,使用者可以選擇性地進行授權或者關閉.

Permission的保護等級

permission的保護等級通過protectionLevel屬性設定, 共有4種: normal,dangerous,signature,signatureOrSystem.
簽名相關的比較不常用, 剩下的兩種是normaldangerous. 總結下來就是: 所有的許可權仍然在manifest中靜態宣告, normal許可權的在安裝的時候自動授權, 而dangerous的許可權需要應用明確地請求使用者授權. 當然對於Android 6.0以下的手機,或者以前開發的舊應用來說, dangerous許可權也是安裝時授權的, 具體看下一節的討論. Dangerous Permissions:  想要檢視所有dangerous的許可權, 也可以用命令: adb shell pm list permissions -g -d

手機版本和程式版本的不同處理

這裡引用一段Guildes裡面的原文:
  • If the device is running Android 6.0 (API level 23) or higher, and the app's targetSdkVersion is 23 or higher, the app requests permissions from the user at run-time. The user can revoke the permissions at any time, so the app needs to check whether it has the permissions every time it runs. For more information about requesting permissions in your app, see the Working with System Permissions training guide.
  • If the device is running Android 5.1 (API level 22) or lower, or the app's targetSdkVersion is 22 or lower, the system asks the user to grant the permissions when the user installs the app. If you add a new permission to an updated version of the app, the system asks the user to grant that permission when the user updates the app. Once the user installs the app, the only way they can revoke the permission is by uninstalling the app.
這裡頭要注意and和or的使用,說明了只有滿足targetSdkVersion和實際使用裝置的版本都在23及以上的時候,才會採用新的動態許可權機制. 其他情況, 跟之前一樣, 在安裝和升級應用的時候就授權了所有的許可權. 可以總結為: 1.所有的許可權都在manifest中宣告. 2.如果(1)你的app的targetSdkVersion是23及以上,並且(2)app執行在Android 6.0及以上的裝置,危險許可權必須動態請求. 當權限被拒絕,app理應還是能夠使用的,只不過許可權相關的部分功能不能用. 3.上一條中的兩個條件(1)(2)沒有同時滿足,即屬於其他情況, 所有許可權在安裝時請求,如果使用者不接受,則不安裝. 特別注意這種情況: 舊應用新系統. 如果targetSdkVersion小於23,即被認為是Android 6.0釋出之前開發的應用, 還沒有相容6.0. 這種應用即便是被裝在Android 6.0的機器上,也是採用原來的安裝即授予許可權邏輯, 所有許可權在應用安裝時全部被授權. 在Android 6.0的裝置上安裝targetSdkVersion小於23的應用之後, 可以在應用的設定中檢視,發現所有的dangerous許可權狀態都是開啟.  所以不用擔心老的應用在Android 6.0上會各種亂崩. 但是使用者仍然可以在系統設定中禁用許可權: 在模擬器上點選授權開關的時候彈出了以下提示: 如果使用者執意要取消授權, 應用雖然不會直接崩潰,但是功能變為默默無作為狀態, 返回值可能變為null或者0,進而引起無法預料的行為或者崩潰. 

為什麼要及時升級targetSdkVersion

這是因為每一個版本的API有可能會產生新的許可權,這些新增的許可權, 對於targetSdkVersion比該API低的應用是自動獲取的. 所以targetSdkVersion最好是能及時寫到最新,這樣避免應用自動獲取到新API新增的許可權. 結論: 對targetSdkVersion還不存在的許可權是自動獲取到的. 其中”Automatic permission adjustments”那段.

Permission group

所有的許可權都有自己的permission group. 系統彈框請求某一個permission時也是隻說明了它的類別,當用戶同意,系統會給予它該條permission.(只有這一條). 但是如果app已經有了該group下的另一條permission,系統將會自動授予許可權(也即請求許可權的callback直接返回),這過程中不與使用者互動.

動態許可權請求的實現

因為許可權動態檢查相關的API是Android 6.0才加入的, 所以minSdkVersion不是23時,推薦使用SupportLibrary來實現,好處是: 程式裡不必加if來判斷當前裝置的版本.

1.檢查許可權狀態

如果執行的操作需要一個dangerous permission, 那麼每次在執行操作的地方都必須check你是否有這個permission, 因為使用者可以在應用設定裡隨意地更改授權情況, 所以必須每次在使用前都檢查是否有許可權. 比如:
if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_CONTACTS)) {
    //has permission, do operation directly
    ContactsUtils.readPhoneContacts(this);
    Log.i(DEBUG_TAG, "user has the permission already!");
} else {
    //do not have permission

2.動態請求許可權

如果上面許可權檢查的結果是DENIED, 那麼就需要顯式地向用戶請求這個許可權了. Android提供了幾個方法來動態請求許可權, 呼叫這些方法會顯示出一個標準的Dialog, 這個Dialog目前是不能被定製的. 2.1有時候可能需要解釋為什麼需要這個許可權 有時候你可能會需要跟使用者解釋一下許可權的用途. 注意不是每條許可權都需要解釋,顯而易見的那種可以不解釋,太多的解釋會降低使用者體驗. 一種方式是,當用戶拒絕過這個許可權,但是又用到了這個功能, 那麼很可能使用者不是很明白為什麼app需要這個許可權, 這時候就可以先向使用者解釋一下. 如果app之前請求過該許可權,被使用者拒絕, 這個方法就會返回true. 如果使用者之前拒絕許可權的時候勾選了對話方塊中”Don’t ask again”的選項,那麼這個方法會返回false. 如果裝置策略禁止應用擁有這條許可權, 這個方法也返回false. 注意具體解釋原因的這個dialog需要自己實現, 系統沒有提供. 2.2請求許可權 請求許可權的方法是: requestPermissions() 傳入一個Activity, 一個permission名字的陣列, 和一個整型的request code. 這個方法是非同步的,它會立即返回, 當用戶和dialog互動完成之後,系統會呼叫回撥方法,傳回使用者的選擇結果和對應的request code. 程式碼: 複製程式碼
if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_CONTACTS)) {
    //has permission, do operation directly
    ContactsUtils.readPhoneContacts(this);
    Log.i(DEBUG_TAG, "user has the permission already!");
} else {
    //do not have permission
    Log.i(DEBUG_TAG, "user do not have this permission!");

    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
            Manifest.permission.READ_CONTACTS)) {

        // Show an explanation 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.
        Log.i(DEBUG_TAG, "we should explain why we need this permission!");
    } else {

        // No explanation needed, we can request the permission.
        Log.i(DEBUG_TAG, "==request the permission==");

        ActivityCompat.requestPermissions(MainActivity.this,
                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.
    }
}
複製程式碼 這個對話方塊是系統的,不能自定義. 經驗證, 請求許可權對話方塊中的”Don’t ask again”的選項, 只有該條許可權之前的狀態是Denied的時候,才會出現. 以前從未授權(即第一次彈框), 或者之前的狀態是Granted(當然這種情況一般不會彈框詢問), 出現的彈框都是不帶該不再詢問的選項的. 2.3處理請求許可權的響應 這個回撥中request code即為呼叫requestPermissions()時傳入的引數,是app自定義的一個整型值. 如果請求取消,返回的陣列將會為空. 程式碼: 複製程式碼
@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.
                ContactsUtils.readPhoneContacts(this);
                Log.i(DEBUG_TAG, "user granted the permission!");

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
                Log.i(DEBUG_TAG, "user denied the permission!");
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}
複製程式碼 系統自動回撥的情況:  有一些情形下,呼叫

Best Practices

Best Practices 總結: 1.用Intent啟動其他應用來完成功能. 2.只用真的需要的許可權. 3.不要一次請求多個許可權來煩使用者,有的許可權可以等到要用的時候再請求. 4.向用戶解釋為什麼需要這個許可權. 5.從Android 6.0開始,每一條許可權,都需要測試開關兩種狀態下是不是都能讓應用正常執行,而不是崩潰. 並且相關的許可權可能會需要測試不同的組合.

ADB命令

可以用命令列來管理許可權: Use the adb tool to manage permssions from the command line:
  • List permissions and status by group:

    $ adb shell pm list permissions -d -g

  • Grant or revoke one or more permissions: $ adb shell pm [grant|revoke] <permission-name> ... 

參考資料:

第三方庫:  轉自:http://www.cnblogs.com/mengdd/p/4892856.html

相關推薦

Android M Permission 學習筆記

Android應用許可權簡要介紹 一個Android應用預設情況下是不擁有任何許可權的, 這即是說, 在預設情況下, 一個應用是沒有權利去進行一些可能會造成不好影響的操作的. 這些不好的影響可能是對其它應用,作業系統,或者是使用者. 如果應用需要一些額外的能力,則它需要在AndroidManifest.x

Android Room框架學習筆記

build tails accep new ignore Owner -m dice ike 一、使用 1、build.gradle引入 compile "android.arch.persistence.room:runtime:1.0.0" annotationPro

Android工作室開發學習筆記——3

今天繼續深入Java知識,鞏固這門面向物件的語言。 1、this 與super this 指代當前物件,主要應用場合:  在一些容易混淆的場合,如成員方法的引數名與資料成員同名; 成員方法的區域性變數名與資料成員同名。   Public class test{  

Android設計模式學習筆記|一|面向物件的六大原則

單一職責原則、開閉原則、里氏替換原則、依賴倒置原則、介面隔離原則、迪米特原則。 一、單一職責原則(Single Responsibility Principle SRP) 定義:就一個類而言,應該就有一個引起它變化的原因。簡單來說,一個類中應該是一組相關性很高的函式、資料

Android設計模式學習筆記第一章-----面向物件的6大原則

一、單一職責原則 說明:每一個類中的屬性及方法都具有與這個類強相關的特點。如需要構建一個影象快取的功能,根據UML圖完成設計,則需要構建一個影象快取的類ImageCache,和一個影象載入的類ImageLoad。如果把這兩個類的功能共同放到影象快取類ImageCache中,

java/android 設計模式學習筆記(10)---建造者模式

  這篇部落格我們來介紹一下建造者模式(Builder Pattern),建造者模式又被稱為生成器模式,是創造性模式之一,與工廠方法模式和抽象工廠模式不同,後兩者的目的是為了實現多型性,而 Builder 模式的目的則是為了將物件的構建與展示分離。Builder

Android Span架構學習筆記

框架介紹 框架涉及到的類遵循以下四個定義規則: 如果一個Span影響字元層次上的文字格式,那麼需要繼承CharacterStyle類。 如果一個Span影響段落層次上的文字格式,那麼需要繼承ParagraphStyle介面。 如果一個Span修改字元層次上

java/android 設計模式學習筆記(15)---責任鏈模式

  這篇部落格我們來介紹一下責任鏈模式(Chain-of-responsibility Pattern),責任聯模式又稱為職責鏈模式,是行為型設計模式之一。顧名思義,責任鏈模式中存在一個鏈式結構,多個節點首尾相連,每個節點都可以被拆開再連線,因此,鏈式結構具有很

Handelr(二上)-- MarsChen Android 開發教程學習筆記

package com.shumin.lbs08;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.v7.app.ActionBarActivity;impor

weex+android原生開發學習筆記(一)

移動端開發(使用Weex+android原生開發筆記):         npm install weex-toolkit -g              2》、用 weex create 命令來建立一個空的模板專案:         weex create awes

java/android 設計模式學習筆記(20)---迭代器模式

  我們這篇部落格來介紹一下迭代器模式(Iterator Pattern),又稱為遊標(Cursor Pattern)模式,是行為型設計模式之一。迭代器模式算是一個比較古老的設計模式,其源於對容器的訪問,比如 Java 中的 List、Map、陣列等,我們知道對

android多媒體部分學習筆記六----音訊錄製 mediaRecorder

/** * * 使用意圖捕獲音訊 * * @time 下午12:58:03 * @author retacn yue * @Email [email protected] */ public class MediaRecorderDemoActivity exten

Andriod群英傳-Android Scroll 分析學習筆記

1.滑動效果的產生 1.1.Android座標系 Android座標系是以螢幕的左上角為座標系原點,從原點水平向右為X軸正方向,從原點豎直向下為Y軸正方向。 在觸控事件中,通過getRawX( ) , etRawY( )可以獲得對應的座標。 1

Android App開發學習筆記(001)——用Android Studio建立虛擬Android裝置時的注意事項-01

安裝了Android Studio 2.3,建立第一個預設的安卓專案,點選AS的run按鈕,在開啟的對話方塊裡建立了一個AVD(Android Virtual Device),然後就等著虛擬機器螢幕上顯示結果了,但是等了半天,AS的狀態條一直顯示“waiting for t

android核心剖析學習筆記:AMS(ActivityManagerService)內部原理和工作機制

      一、ActivityManagerService提供的主要功能:        (1)統一排程各應用程式的Activity        (2)記憶體管理        (3)程序管理       二、啟動一個Activity的方式有以下幾種:

Android 基礎視訊學習筆記 1 (完結)

綜述:               1 1G-4G的介紹:(瞭解) 1G  大哥大 2G  小靈通   gsm  發簡訊   wap.baidu.com                   3G  沃       7.2M                   4G :lt

Android中PackageManager學習筆記(2)-PackageInfo

PackageInfo 我們通過下面的方法獲得PackageInfo物件資訊: getInstalledPackages(int flags) 引數flags有如下的值: GET_ACTIVITIES :值為1.如果想獲得所有<activity>標籤的

java/android 設計模式學習筆記(12)---組合模式

  這篇我們來介紹一下組合模式(Composite Pattern),它也稱為部分整體模式(Part-Whole Pattern),結構型模式之一。組合模式比較簡單,它將一組相似的物件看作一個物件處理,並根據一個樹狀結構來組合物件,然後提供一個統一的方法去訪問相

Android單元測試學習筆記

按照文章內容,我總結如下: “單元測試,是為了測試某一個類的某一個方法能否正常工作,而寫的測試程式碼”: 方法有返回值(包括異常):使用JUnit框架方法無返回值: 1) 策略:mock, s

Android菜鳥學習筆記(WebView載入html頁面,頁面提交資料問題)

在開發過程中,有一個問卷調查功能,問卷是url用webView載入html頁面出來,在html頁面提交時發現session沒和webview的同步導致提交失敗,這個問題困擾了我很久,後來在前輩的共同研究下,終於找到辦法:獲取html頁面提交的url,然後對url做一次coo