Android 開發技巧 - Android 6.0 以上權限大坑和權限檢查基類封裝
簡單介紹
關于運行時權限的說法,早在Google發布android 6.0的時候,大家也聽得蠻多的。從用戶的角度來講,用戶是受益方,更好的保護用戶的意思,而對于開發者來說,無疑增加了工作量。
對于6.0以下的權限在安裝時,會根據權限聲明產生一個權限列表,用戶只有同意才能完成app的安裝。而在6.0以后,不需要先對權限授權就可以安裝app,對于權限的授權我們可以選擇禁止。
在新的權限機制中,Google將權限分為兩類:
Normal Permissions(普通權限):不涉及用戶隱私,不需要用戶進行授權,比如訪問網絡等;
Dangerous Permission(危險權限):涉及到用戶隱私,需要用戶進行授權,比如相機訪問、讀取SD卡等。
PS:運行時權限只適合APP運行在Android 6.x以上的機器,對于危險權限Google官方也對其進行了分組,只要一組中的某一權限被授權,同組的權限也同樣會被授權。
操作步驟
簡單的介紹了關于運行時權限的使用方法,操作步驟如下
-
在Androidmanifest.xml文件聲明相關權限
-
通過ContextCompat.checkSelfPermission方法檢查某項權限被授予情況
-
申請授權
-
權限回調處理
封裝調用
權限的申請我們一般的做法都在Activity被創建的時候,才開始申請危險權限。而每次都得重復上述的操作,想想都覺得煩。為此,筆者將運行時權限的使用進行了進一步的歸納總結。將權限的檢查統一封裝在基類中,子類繼承并實現抽象方法,傳入權限數組等即可。
1)通過抽象方法getNeedPermissions( )獲取需要進行檢測的權限數組,檢查相關權限是否授權,如果未授權則開始申請權限
/**
* 檢查所有權限,無權限則開始申請相關權限
*/
protected void checkAllNeedPermissions() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) {
ActivityCompat.requestPermissions(this, needRequestPermissonList.toArray(
new String[needRequestPermissonList.size()]), REQUEST_CODE_PERMISSON);
}
}</code></pre>
2)權限授權情況回調處理,這里授權失敗默認彈框是否前往設置頁面授權
/**
* 權限授權結果回調
*
* @param requestCode
* @param permissions
* @param paramArrayOfInt
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] paramArrayOfInt) {
if (requestCode == REQUEST_CODE_PERMISSON) {
if (!verifyPermissions(paramArrayOfInt)) {
permissionGrantedFail();
showTipsDialog();
isNeedCheckPermission = false;
} else permissionGrantedSuccess();
}
}
PS:其中permissionGrantedSuccess()和permissionGrantedSuccess()為抽象方法,由子類實現。
3)簡單調用,子類繼承該基類,實現以下抽象方法即可
@Override
public String[] getNeedPermissions() {
return new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
}
@Override
protected void permissionGrantedSuccess() {
}
@Override
protected void permissionGrantedFail() {
}
有沒有覺得醬紫操作清晰了很多,也方便了不少。依然如此,就趕緊mark吧。
封裝類的完整代碼如下:
/**
* Created by chenyk on 2016/9/28.
* 檢查相關權限基類,適用于android 6.0 運行時權限
* 使用方法:需要運行時權限的activity繼承此類
*/
public abstract class BaseCheckPermissionActivity extends NeedBackActivity
implements OnRequestPermissionsResultCallback {
private static final int REQUEST_CODE_PERMISSON = 2020; //權限請求碼
private boolean isNeedCheckPermission = true; //判斷是否需要檢測,防止無限彈框申請權限
@Override
protected void onResume() {
super.onResume();
if (isNeedCheckPermission) {
checkAllNeedPermissions();
}
}
/**
* 檢查所有權限,無權限則開始申請相關權限
*/
protected void checkAllNeedPermissions() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
if (null != needRequestPermissonList && needRequestPermissonList.size() > 0) {
ActivityCompat.requestPermissions(this, needRequestPermissonList.toArray(
new String[needRequestPermissonList.size()]), REQUEST_CODE_PERMISSON);
}
}
/**
* 獲取權限集中需要申請權限的列表
*
* @param permissions
* @return
*/
private List<String> getDeniedPermissions(String[] permissions) {
List<String> needRequestPermissonList = new ArrayList<>();
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) !=
PackageManager.PERMISSION_GRANTED ||
ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
needRequestPermissonList.add(permission);
}
}
return needRequestPermissonList;
}
/**
* 所有權限是否都已授權
*
* @return
*/
protected boolean isGrantedAllPermission() {
List<String> needRequestPermissonList = getDeniedPermissions(getNeedPermissions());
return needRequestPermissonList.size() == 0;
}
/**
* 權限授權結果回調
*
* @param requestCode
* @param permissions
* @param paramArrayOfInt
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] paramArrayOfInt) {
if (requestCode == REQUEST_CODE_PERMISSON) {
if (!verifyPermissions(paramArrayOfInt)) {
permissionGrantedFail();
showTipsDialog();
isNeedCheckPermission = false;
} else permissionGrantedSuccess();
}
}
/**
* 檢測所有的權限是否都已授權
*
* @param grantResults
* @return
*/
private boolean verifyPermissions(int[] grantResults) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
/**
* 顯示提示對話框
*/
protected void showTipsDialog() {
new AlertDialog.Builder(this).setTitle("提示信息").setMessage("當前應用缺少" + getDialogTipsPart()
+ "權限,該功能暫時無法使用。如若需要,請單擊【確定】按鈕前往設置中心進行權限授權。")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startAppSettings();
}
}).show();
}
/**
* 啟動當前應用設置頁面
*/
private void startAppSettings() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
/**
* 獲取彈框提示部分內容
*
* @return
*/
protected String getDialogTipsPart() {
return "必要";
}
/**
* 獲取需要進行檢測的權限數組
*/
protected abstract String[] getNeedPermissions();
/**
* 權限授權成功
*/
protected abstract void permissionGrantedSuccess();
/**
* 權限授權失敗
*/
protected abstract void permissionGrantedFail();
來自:http://www.jianshu.com/p/a0ca49f7cb61