之前調試的時候,出現了一個問題,就是當我打開二維碼掃描界面的時候,對于一部分手機一直不會出現那個掃描框,這點我也很是郁悶,這不好整啊,畢竟二維碼界面是用的別人的,怎么改啊?這個時候我分析了一下原因,最后知道只有部分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 userasynchronously– 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();
}
}
});
}
});
同樣的在fragment中一樣可以使用,即((AbsBaseActivity)getActivity()).requestPermission(...)這種方式即可,當首次彈出系統授權彈出框,如果用戶點擊拒絕的話,那么第二次再次需要該權限的話,會打開自定義的提示框且提示自定義的提示描述,所以動態授權還是非常的人性化的。最后提示一下,如果你覺得在應用內每次都是用到的時候才去授權比較麻煩,那么你也可以在用戶剛進入應用后的啟動頁面一次性開啟所有的安全權限,這種方式更加的簡便。
ok,大功告成!!!