之前調(diào)試的時候,出現(xiàn)了一個問題,就是當我打開二維碼掃描界面的時候,對于一部分手機一直不會出現(xiàn)那個掃描框,這點我也很是郁悶,這不好整啊,畢竟二維碼界面是用的別人的,怎么改???這個時候我分析了一下原因,最后知道只有部分6.0的手機才會出現(xiàn)這種情況,那么這就簡單了。下面我就對關(guān)于6.0手機動態(tài)申請安全權(quán)限做一下講解:
對于6.0以下的權(quán)限及在安裝的時候,根據(jù)權(quán)限聲明產(chǎn)生一個權(quán)限列表,用戶只有在同意之后才能完成app的安裝,造成了我們想要使用某個app,就只能默認接受其一些不必要的權(quán)限,而在6.0以后,當app需要我們授予不恰當?shù)臋?quán)限的時候,我們可以予以拒絕。但是這些權(quán)限也是有限制的,比如說只是針對一些安全權(quán)限做動態(tài)授權(quán)處理,如打開手機攝像頭、打開聯(lián)系人、打開錄音等等,這些涉及到用戶安全權(quán)限的時候,就要我們開發(fā)者手動去請求用戶打開權(quán)限。廢話就到這里,下面看具體實現(xiàn)。
1、檢查權(quán)限:
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
}else{
//
}
ContextCompat.checkSelfPermission,主要用于檢測某個權(quán)限是否已經(jīng)被授予,方法返回值為PackageManager.PERMISSION_DENIED或者PackageManager.PERMISSION_GRANTED。當返回DENIED就需要進行申請授權(quán)了。
2、申請權(quán)限:
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
第二個參數(shù)是需要申請的權(quán)限的字符串數(shù)組,第三個參數(shù)為請求碼,主要用于回調(diào)的時候檢測。可以從方法名requestPermissions以及第二個參數(shù)看出,是支持一次性申請多個權(quán)限的,系統(tǒng)會通過彈出對話框一個個的詢問用戶是否授權(quán)。
3、權(quán)限的申請回調(diào):
@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;
}
}
}
首先驗證請求碼并結(jié)合你的申請,然后驗證grantResults對應的申請的結(jié)果,如果你申請的權(quán)限數(shù)組有兩個權(quán)限,那么grantResults的length就為2
還有一點:
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS))
// Show an expanation to the userasynchronously– don’t block
// this thread waiting for the user’s response! After the user
// sees the explanation, try again to request the permission.
}
這個方法就是給用戶一個權(quán)限申請作出必要的解釋,比如用戶第一次拒絕過你的權(quán)限申請,現(xiàn)在你又點擊拍照,那么久需要調(diào)用這個方法,作出一個解釋,解釋為什么需要拍照權(quán)限。
好了,到這里估計你會說,怎么感覺有點小麻煩呢! 沒錯,勞資也感覺是很麻煩啊,我的理念就是統(tǒng)統(tǒng)一條方法解決一個問題,那么,這時候上面的都不要再去看了,什么鬼東西,只需要在你的BaseActivity或者BaseFragment中添加幾行我的下面的代碼,然后調(diào)用的時候,就是一行代碼搞定。(上面的部分統(tǒng)統(tǒng)略去,下面的才是今天的主要)
在你的BaseActivity或者BaseFragment中添加幾行下面的代碼就行了:
private int mPermissionIdx = 0x10;//請求權(quán)限索引
private SparseArray mPermissions = new SparseArray<>();//請求權(quán)限運行列表
@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);
/*
是否需要請求權(quán)限
*/
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);
}
}
那么最最重要的來了,那就是用法咯:(往下接著看)
比如說你需要點擊一下拍照按鈕就打開系統(tǒng)的攝像頭進行拍照,那么就在你打開按鈕的監(jiān)聽事件中這么寫:(比如說是在CarmerActivity中,繼承BaseActivity)
openCarmer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
requestPermission(new String[]{Manifest.permission.CAMERA}, “請求設(shè)備相機權(quán)限”, new GrantedResult() {
@Override
public void onResult(boolean granted) {
if(granted){//表示用戶允許
createLocalStream();
}else {//用戶拒絕
Toast.makeText(MainActivity.this,”權(quán)限拒絕”,Toast.LENGTH_SHORT).show();
}
}
});
}
});
同樣的在fragment中一樣可以使用,即((AbsBaseActivity)getActivity()).requestPermission(...)這種方式即可,當首次彈出系統(tǒng)授權(quán)彈出框,如果用戶點擊拒絕的話,那么第二次再次需要該權(quán)限的話,會打開自定義的提示框且提示自定義的提示描述,所以動態(tài)授權(quán)還是非常的人性化的。最后提示一下,如果你覺得在應用內(nèi)每次都是用到的時候才去授權(quán)比較麻煩,那么你也可以在用戶剛進入應用后的啟動頁面一次性開啟所有的安全權(quán)限,這種方式更加的簡便。
ok,大功告成?。?!