1. 程式人生 > >Android6.0執行時許可權處理-超簡單封裝

Android6.0執行時許可權處理-超簡單封裝

之前除錯的時候,出現了一個問題,就是當我開啟二維碼掃描介面的時候,對於一部分手機一直不會出現那個掃描框,這點我也很是鬱悶,這不好整啊,畢竟二維碼介面是用的別人的,怎麼改啊?這個時候我分析了一下原因,最後知道只有部分6.0的手機才會出現這種情況,那麼這就簡單了。下面我就對關於6.0手機動態申請安全許可權做一下講解:

對於6.0以下的許可權及在安裝的時候,根據許可權宣告產生一個許可權列表,使用者只有在同意之後才能完成app的安裝,造成了我們想要使用某個app,就只能預設接受其一些不必要的許可權,而在6.0以後,當app需要我們授予不恰當的許可權的時候,我們可以予以拒絕。但是這些許可權也是有限制的,比如說只是針對一些安全許可權做動態授權處理,如開啟手機攝像頭、開啟聯絡人、開啟錄音等等,這些涉及到使用者安全許可權的時候,就要我們開發者手動去請求使用者開啟許可權。廢話就到這裡,下面看具體實現。

1、檢查許可權:
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
}else{
//
}
ContextCompat.checkSelfPermission,主要用於檢測某個許可權是否已經被授予,方法返回值為PackageManager.PERMISSION_DENIED或者PackageManager.PERMISSION_GRANTED。當返回DENIED就需要進行申請授權了。

2、申請許可權:
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
第二個引數是需要申請的許可權的字串陣列,第三個引數為請求碼,主要用於回撥的時候檢測。可以從方法名requestPermissions以及第二個引數看出,是支援一次性申請多個許可權的,系統會通過彈出對話方塊一個個的詢問使用者是否授權。

3、許可權的申請回調:
@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;
}
}
}
首先驗證請求碼並結合你的申請,然後驗證grantResults對應的申請的結果,如果你申請的許可權陣列有兩個許可權,那麼grantResults的length就為2

還有一點:
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.
}
這個方法就是給使用者一個許可權申請作出必要的解釋,比如使用者第一次拒絕過你的許可權申請,現在你又點選拍照,那麼久需要呼叫這個方法,作出一個解釋,解釋為什麼需要拍照許可權。

好了,到這裡估計你會說,怎麼感覺有點小麻煩呢! 沒錯,勞資也感覺是很麻煩啊,我的理念就是統統一條方法解決一個問題,那麼,這時候上面的都不要再去看了,什麼鬼東西,只需要在你的BaseActivity或者BaseFragment中新增幾行我的下面的程式碼,然後呼叫的時候,就是一行程式碼搞定。(上面的部分統統略去,下面的才是今天的主要)

在你的BaseActivity或者BaseFragment中新增幾行下面的程式碼就行了:

private int mPermissionIdx = 0x10;//請求許可權索引
private SparseArray mPermissions = new SparseArray<>();//請求許可權執行列表

@SuppressLint("Override")
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    GrantedResult runnable = mPermissions.get(requestCode);
    if (runnable == null) {
        return;
    }
    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        runnable.mGranted = true;
    }
    runOnUiThread(runnable);
}

public void requestPermission(String[] permissions, String reason, GrantedResult runnable) {
    if(runnable == null){
        return;
    }
    runnable.mGranted = false;
    if (Build.VERSION.SDK_INT < 23 || permissions == null || permissions.length == 0) {
        runnable.mGranted = true;//新新增
        runOnUiThread(runnable);
        return;
    }
    final int requestCode = mPermissionIdx++;
    mPermissions.put(requestCode, runnable);

    /*
        是否需要請求許可權
     */
    boolean granted = true;
    for (String permission : permissions) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            granted = granted && checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
        }
    }

    if (granted) {
        runnable.mGranted = true;
        runOnUiThread(runnable);
        return;
    }

    /*
        是否需要請求彈出窗
     */
    boolean request = true;
    for (String permission : permissions) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            request = request && !shouldShowRequestPermissionRationale(permission);
        }
    }

    if (!request) {
        final String[] permissionTemp = permissions;
        AlertDialog dialog = new AlertDialog.Builder(this)
                .setMessage(reason)
                .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            requestPermissions(permissionTemp, requestCode);
                        }
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        GrantedResult runnable = mPermissions.get(requestCode);
                        if (runnable == null) {
                            return;
                        }
                        runnable.mGranted = false;
                        runOnUiThread(runnable);
                    }
                }).create();
        dialog.show();
    } else {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(permissions, requestCode);
        }
    }
}

public static abstract class GrantedResult implements Runnable{
    private boolean mGranted;
    public abstract void onResult(boolean granted);
    @Override
    public void run(){
        onResult(mGranted);
    }
}

那麼最最重要的來了,那就是用法咯:(往下接著看)
比如說你需要點選一下拍照按鈕就開啟系統的攝像頭進行拍照,那麼就在你開啟按鈕的監聽事件中這麼寫:(比如說是在CarmerActivity中,繼承BaseActivity)

openCarmer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
requestPermission(new String[]{Manifest.permission.CAMERA}, “請求裝置相機許可權”, new GrantedResult() {
@Override
public void onResult(boolean granted) {
if(granted){//表示使用者允許
createLocalStream();
}else {//使用者拒絕
Toast.makeText(MainActivity.this,”許可權拒絕”,Toast.LENGTH_SHORT).show();
}
}
});
}
});

ok,大功告成!!!