一、6.0權限組的概念我就不介紹了,不懂的隨便百度一下就有很多答案。
參考別人寫的較好的
Android 采用AOP方式封裝6.0權限管理
RxPermissions
二、網上有很多權限的框架,為什么還要自己封裝呢?
1. 網上別人寫的,自己拿來用運氣好是沒問題。運氣不好碰到問題,搞半天都搞不好。
2. 還有一些是國外寫的框架, 在國內就不定適用。
3. 自己寫的,可以隨時修改,可以做一些通用的業務處理等等。
三、關于權限的一個申請流程
1.判斷系統是不是6.0+.
2.判斷申請的一個或者多個權限,用戶是否已經授權。
3.申請權限。
4.申請結果的處理。
四、先寫一個權限判斷的工具類。
/**
* 申請權限的幫助工具類
*/
public class PermissionUtils {
/**
* 獲取用戶未授權的權限列表
*/
public static List<String> getDeniedPermissions(Activity activity, String... permissions) {
List<String> list = new ArrayList<>();
if (permissions == null) {
return list;
}
for (String p : permissions) {
int permission = ContextCompat.checkSelfPermission(activity, p);
if (permission != PackageManager.PERMISSION_GRANTED) {
list.add(p);
}
}
return list;
}
/**
* 判斷版本是不是大于6.0
*/
public static boolean isUpAndroidM() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
/**
* 檢查所給權限List是否需要給提示
*
* @param activity Activity
* @param permissions 權限list
* @return 如果某個權限需要提示則返回true
*/
public static boolean shouldShowRequestPermissionRationale(Activity activity, List<String> permissions) {
for (String permission : permissions) {
// 用戶拒絕是true 用戶選擇不再提示是:false
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
return true;
}
}
return false;
}
}
里面包含三個方法:
- 判斷系統是不是6.0+
- 獲取用戶未授權的權限列表
- 判斷未獲取的權限列表用戶是不是都拒絕了
五、權限申請怎么樣才能簡單點?
1. 權限申請的回調在Activity或者Fragment的onRequestPermissionsResult方法里面。
2. 在申請權限的頁面,怎么樣去避開重復的復寫這個方法??
3. 我個人其實能力也有限,但我懶,所以我還是參考別的框架寫好的一些代碼。
大概就是添加一個沒有View的Fragment,所有的權限處理在這個Fragment處理,然后接口回調。
六、權限申請回調接口
/**
* 申請權限成功的回調
*/
public interface PermissionListener {
void onSucceed();
}
別問我為什么沒有失敗的接口,因為我懶,所以失敗統一處理。如有需要自己去改。
七、權限申請的Fragment
/**
* 申請權限的Fragment
*/
@SuppressLint("ValidFragment")
public class PermissionFragment extends Fragment {
/**
* 請求碼
*/
private static final int CODE = 66;
private static final int REQUEST_PERMISSION_SETTING = 55;
/**
* 回調
*/
private PermissionListener mPermissionListener;
private Activity mActivity;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
/**
* 設置成功回調的監聽
*/
public void setPermissionListener(PermissionListener permissionListener) {
mPermissionListener = permissionListener;
}
/**
* 成功回調
*/
public void onSucceed() {
if (mPermissionListener != null) {
mPermissionListener.onSucceed();
}
}
/**
* 顯示Dialog提示用戶去設置頁面
*/
public void showSettingDialog() {
new AlertDialog.Builder(mActivity)
.setTitle("權限被拒絕")
.setMessage("去打開拒絕的權限?")
.setPositiveButton("去打開", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
openSetting();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.show();
}
/**
* 顯示Toast
*/
private void showToast(String text) {
Toast toast = Toast.makeText(mActivity, text, Toast.LENGTH_LONG);
toast.show();
}
/**
* 打開應用設置頁面
*/
private void openSetting() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", mActivity.getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, REQUEST_PERMISSION_SETTING);
}
/**
* 申請權限
*/
@RequiresApi(api = Build.VERSION_CODES.M)
public void requestPermissions(Activity activity, String[] permissions) {
this.mActivity = activity;
requestPermissions(permissions, CODE);
}
/**
* 授權回調
*/
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == CODE) {
// 獲取未申請的權限列表
List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(mActivity, permissions);
if (deniedPermissions.size() > 0) {
// 執行失敗的方法
// 如果所有的權限:用戶選擇不再提示
if (!PermissionUtils.shouldShowRequestPermissionRationale(mActivity, deniedPermissions)) {
showSettingDialog();
} else {
showToast("權限被拒絕");
}
} else {
// 執行成功的方法
onSucceed();
}
}
}
@Override
public void onDestroy() {
mActivity = null;
mPermissionListener = null;
super.onDestroy();
}
}
這個類,最主要是申請權限和對權限申請結果的處理。
Fragment調用setRetainInstance的原理
八、權限申請的幫助類
/**
* 6.0權限申請的幫助類
*/
public class XPermission {
private PermissionFragment mPermissionFragment;// 申請權限的中間Fragment
private String[] mPermissions;
private static final String TAG = "XPermission";
private Activity mActivity;
public XPermission(Activity activity) {
this.mActivity = activity;
this.mPermissionFragment = getPermissionsFragment(activity);
}
public static XPermission with(Activity activity) {
return new XPermission(activity);
}
private PermissionFragment getPermissionsFragment(Activity activity) {
PermissionFragment permissionsFragment = findPermissionsFragment(activity);
boolean isNewInstance = permissionsFragment == null;
if (isNewInstance) {
permissionsFragment = new PermissionFragment();
FragmentManager fragmentManager = activity.getFragmentManager();
fragmentManager
.beginTransaction()
.add(permissionsFragment, TAG)
.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
}
return permissionsFragment;
}
/**
* 去找權限的Fragment
*/
private PermissionFragment findPermissionsFragment(Activity activity) {
return (PermissionFragment) activity.getFragmentManager().findFragmentByTag(TAG);
}
/**
* 要申請的權限
*/
public XPermission permissions(String... permissions) {
mPermissions = permissions;
return this;
}
/**
* 請求申請權限
*/
@SuppressLint("NewApi")
public void request(PermissionListener permissionListener) {
mPermissionFragment.setPermissionListener(permissionListener);
// 1.判斷一下是不是6.0以上的系統
if (!PermissionUtils.isUpAndroidM()) {
// 執行成功的方法
mPermissionFragment.onSucceed();
return;
}
// 2.獲取未申請的權限列表
List<String> deniedPermissions = PermissionUtils.getDeniedPermissions(mActivity, mPermissions);
if (deniedPermissions.size() > 0) {
// 3.要去申請權限
mPermissionFragment.requestPermissions(mActivity, deniedPermissions.toArray(new String[deniedPermissions.size()]));
} else {
// 執行成功的方法
mPermissionFragment.onSucceed();
}
}
}
這個類有兩個重要的方法,permissions,request。代碼簡單,看看就懂。
九、最后就是使用了
new XPermission(activity)
.permissions(Permission.CAMERA)// 看補充
.request(new PermissionListener() {
@Override
public void onSucceed() {
// TODO
}
});
是不是很簡單,爽YY。
十、補充Permission類,這個類是權限申請的封裝,方便權限申請調用。
/**
* 權限申請的封裝
*/
public class Permission {
public static final String[] CALENDAR; // 讀寫日歷。
public static final String[] CAMERA; // 相機。
public static final String[] CONTACTS; // 讀寫聯系人。
public static final String[] LOCATION; // 讀位置信息。
public static final String[] MICROPHONE; // 使用麥克風。
public static final String[] PHONE; // 讀電話狀態、打電話、讀寫電話記錄。
public static final String[] SENSORS; // 傳感器。
public static final String[] SMS; // 讀寫短信、收發短信。
public static final String[] STORAGE; // 讀寫存儲卡。
static {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
CALENDAR = new String[]{};
CAMERA = new String[]{};
CONTACTS = new String[]{};
LOCATION = new String[]{};
MICROPHONE = new String[]{};
PHONE = new String[]{};
SENSORS = new String[]{};
SMS = new String[]{};
STORAGE = new String[]{};
} else {
CALENDAR = new String[]{
Manifest.permission.READ_CALENDAR,
Manifest.permission.WRITE_CALENDAR};
CAMERA = new String[]{
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
CONTACTS = new String[]{
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS,
Manifest.permission.GET_ACCOUNTS};
LOCATION = new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION};
MICROPHONE = new String[]{
Manifest.permission.RECORD_AUDIO};
PHONE = new String[]{
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.CALL_PHONE,
Manifest.permission.READ_CALL_LOG,
Manifest.permission.WRITE_CALL_LOG,
Manifest.permission.USE_SIP,
Manifest.permission.PROCESS_OUTGOING_CALLS};
SENSORS = new String[]{
Manifest.permission.BODY_SENSORS};
SMS = new String[]{
Manifest.permission.SEND_SMS,
Manifest.permission.RECEIVE_SMS,
Manifest.permission.READ_SMS,
Manifest.permission.RECEIVE_WAP_PUSH,
Manifest.permission.RECEIVE_MMS};
STORAGE = new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
}
}
}