Android6.0權限管理

臨近放假了時間比較充裕,就琢磨着乾點啥,想來想去6.0運行時權限一直沒弄過而且項目也總有一天要升級的,既然這樣,那就趁熱來一發吧

那麼爲了學到原滋原味的6.0權限,官方文檔是第一選擇,這裏附上鍊接https://developer.android.com/training/permissions/index.html

關於6.0如何選擇compileSdkVersion, minSdkVersion 和 targetSdkVersion可以看我另一篇博文
如何選擇compileSdkVersion, minSdkVersion 和 targetSdkVersion


在文檔上可以看到6.0在權限上有幾處改變

  1. 系統權限分爲兩類
    1. 普通權限
      正常的權限不涉及用戶的隱私風險。如果你的應用程序清單列出了一個正常的權限,系統自動授予許可。
    2. 危險權限
      危險的權限可以讓應用程序訪問用戶的機密數據,如果列出一個危險的權限,用戶必須授權許可
  2. 如果設備運行Android 5.1或更低,或應用程序的targetSdk是22或更低:你在清單列表申明的危險權限,用戶授予權限許可是在安裝應用程序時.(測試時候發現部分國產rom的手機在低於6.0的版本依舊是運行時授予確實強大^_^)
    如果設備運行Android 6.0或更高版本,並且你的應用程序的targetSdk是23或更高:應用中危險的權限,將在應用程序運行時用戶授予。(我用的6.0系統的華爲v8測試的,如果程序的targetSdk是23或者更高,當需要使用權限的時候,系統並未自己彈起權限請求,需要自己寫代碼請求才行)

這裏列出危險權限
這裏寫圖片描述


下面介紹api

檢查權限是否獲取

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

這裏寫圖片描述
如果返回值 PackageManager.PERMISSION_GRANTED表示權限已經獲取,可以執行操作.如果返回值 PackageManager.PERMISSION_DENIED表示權限未授予,需要請求權限

是否需要解釋爲什麼請求該權限

ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,Manifest.permission.WRITE_CALENDAR)

這裏寫圖片描述
在用戶拒絕過該權限並且未勾選不在提示,再次請求該權限的時候shouldShowRequestPermissionRationale方法將會返回true,這個時候可以給用戶一個獲取該權限的解釋,比如彈出一個說明.

請求權限

ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

這裏寫圖片描述
調用該方法後.系統會顯示一個標準的對話框給用戶,應用程序不能配置或者改變對話框的內容,即請求權限彈窗不能自定義.舉個栗子,如果你請求READ_CONTACTS許可,該系統對話框只是說你的應用程序需要訪問設備的聯繫人。一旦用戶同意。那麼同權限組的其他權限,系統自動賦予他們,不在彈窗提示

此外,權限組的劃分在未來的安卓版本可能會改變,所以每一個需要權限的地方都需要請求權限,即使用戶已經允許另一個同組的權限。

結果回調

@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {


}

當系統要求用戶授予權限,用戶可以選擇不在詢問或者不在提醒,這種情況下系統不會彈出請求權限彈窗,而是直接回調onRequestPermissionsResult方法並且結果爲PackageManager.PERMISSION_DENIED。

用戶拒絕了權限並且勾選了不在詢問這種情況,可以在onRequestPermissionsResult回調方法中判斷,即返回結果爲PackageManager.PERMISSION_DENIED並且該權限的shouldShowRequestPermissionRationale方法返回值爲false

@Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        if(grantResults[0] == PackageManager.PERMISSION_DENIED && 
                !ActivityCompat.shouldShowRequestPermissionRationale(this,permissions[0])){

        }
    }

因爲這種情況下沒法彈出系統請求權限彈窗,所以我們需要手動的寫一個dialog去引導用戶到設置界面打開權限.

這裏附上文檔中的例子

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

api是不是很簡單很方便.但是實際項目中我還是使用第三方庫 哈哈哈


關於6.0權限的庫還是很多的..這裏我使用的是google官方提供的 easypermissions

使用比較簡單這裏我稍微講解下.
1.流程圖
這裏寫圖片描述

2.sample中代碼稍加註釋提示下

public class MainActivity extends AppCompatActivity implements
        EasyPermissions.PermissionCallbacks {

    private static final String TAG = "MainActivity";

    private static final int RC_CAMERA_PERM = 123;
    private static final int RC_SETTINGS_SCREEN = 125;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Button click listener that will request one permission.
        findViewById(R.id.button_camera).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cameraTask();
            }
        });

    }

    //用戶手動修改權限請求回調
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == RC_SETTINGS_SCREEN) {
            // Do something after user returned from app settings screen, like showing a Toast.
            Toast.makeText(this, R.string.returned_from_app_settings_to_activity, Toast.LENGTH_SHORT)
                    .show();
        }
    }

    @AfterPermissionGranted(RC_CAMERA_PERM)
    public void cameraTask() {
        //判斷權限是否授予
        if (EasyPermissions.hasPermissions(this, Manifest.permission.CAMERA)) {//已經授予
            // Have permission, do the thing!
            Toast.makeText(this, "TODO: Camera things", Toast.LENGTH_LONG).show();
        } else {//未授予
            // Ask for one permission
            EasyPermissions.requestPermissions(this, getString(R.string.rationale_camera),
                    RC_CAMERA_PERM, Manifest.permission.CAMERA);
        }
    }



    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        // EasyPermissions handles the request result.
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);//權限回調傳給EasyPermissions.onRequestPermissionsResult(),他會根據權限獲取成功與否回調onPermissionsGranted()與onPermissionsDenied
    }

    //獲取權限成功回調
    @Override
    public void onPermissionsGranted(int requestCode, List<String> perms) {
        Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size());
    }

    //獲取權限失敗回調
    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
        Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());

        // 判斷是否拒絕了權限請求並且勾選了不在提示,如果是將會彈出引導手動設置權限的dialog,引導用戶到設置中心手動修改權限
        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            new AppSettingsDialog.Builder(this, getString(R.string.rationale_ask_again))
                    .setTitle(getString(R.string.title_settings_dialog))
                    .setPositiveButton(getString(R.string.setting))
                    .setNegativeButton(getString(R.string.cancel), null /* click listener */)
                    .setRequestCode(RC_SETTINGS_SCREEN)
                    .build()
                    .show();
        }
    }
}

到此基本就介紹的差不多啦.有什麼疑問歡迎留言,今天是祖國母親生日的第一天,祝大家國慶快樂

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