一、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};
}
}
}