Android M動態申請獲取權限android.permission.READ_PHONE_STATE

Android M對應用的授權策略做了變動,如果我們想調用getDeviceId()獲取手機串碼,只在Manifest裏添加android.permission.READ_PHONE_STATE權限是不夠的,如果不做權限的動態申請和處理,可能會報如下錯誤:

AndroidRuntime: java.lang.SecurityException: getDeviceId: Neither user 10201 nor current process has android.permission.READ_PHONE_STATE.1

那如何在代碼中動態申請權限呢?分四步進行:

第一步,在Manifest文件中添加權限:

1

第二步, 要獲取權限進行操作的Activity實現 ActivityCompat.OnRequestPermissionsResultCallback接口(這一步貌似不是必須):

public class MainActivity extends Activity
implements ActivityCompat.OnRequestPermissionsResultCallback {

第三步,動態申請權限並做處理:

    int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE);

    if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, REQUEST_READ_PHONE_STATE);
    } else {
        //TODO
    }

其中REQUEST_READ_PHONE_STATE 是自定義的類常量,可以像下面這樣在activity中定義:
public final static int REQUEST_READ_PHONE_STATE = 1;

第四步, 重寫onRequestPermissionsResult()方法,對權限申請結果做處理:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case REQUEST_READ_PHONE_STATE:
            if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                //TODO
            }
            break;

        default:
            break;
    }
}

下面對關鍵方法做一個解釋:

1、檢查是否有權限:
ActivityCompat.checkSelfPermission

eg:檢查是否有讀取聯繫人權限
ActivityCompat.checkSelfPermission(this,Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED

2、是否重新請求授權(用戶之前拒絕過):
ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.READ_CONTACTS)
如果應用之前請求過此權限但用戶拒絕了請求,此方法將返回 true,意思是說要給用戶一個 解釋,告訴用戶爲什麼要這個權限。
然而,在實際開發中,很多手機對原生系統做了修改,比如小米4的6.0的shouldShowRequestPermissionRationale 就一直返回false,而且在申請權限時,如果用戶選擇了拒絕,則不會再彈出對話框了。如果是這樣,我們可以在回調裏面處理,如果用戶拒絕了這個權限,則打開本應用信息界面,由用戶自己手動開啓這個權限。

3、請求授權:
ActivityCompat.requestPermissions
注意的是,調用此方法後,系統會彈出一個權限申請框,供用戶選擇,這個選擇框我們無法更改:
這裏寫圖片描述

而且此時activity會調用onPause()方法,用戶做了選擇之後,此對話框消失,onResume()方法又會執行。

注:在華爲設備上測試,如果用戶勾選了“不再詢問”的選項的話,shouldShowRequestPermissionRationale會返回false。而且如果再次調用requestPermissions申請權限,就不會有申請框彈出,而是直接返回申請失敗。但是activity的生命週期方法的執行順序和有系統提示框彈出時的順序是一樣的。

4、搜權結果,通過 ActivityCompat.OnRequestPermissionsResultCallback 回調獲取授權結果,判斷是否授權。

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_CODE_INFO_OF_PHONE_SETTINGS) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            L.d("imei", "permission is granted after requested!");
        } else if (grantResults[0] == PackageManager.PERMISSION_DENIED){
            L.d("imei", "permission is not granted after requested!");
            //這裏表示申請權限後被用戶拒絕了
        } else {
            L.d("imei", "permission is not granted after requested!");
        }
    }
}

關於更多運行時請求權限的問題,可以查看https://developer.android.com/training/permissions/requesting.html
更詳細請看http://mdsa.51cto.com/art/201508/489882_all.htm#topx

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