一、Android现在申请权限比较麻烦,在github查找到一个比较好用的库:AndPermission
依赖:
implementation 'com.yanzhenjie:permission:2.0.0-rc4'
在Fragment中要加上下面的语句,Activity中则可以省略,但我处理方式是都加上了,本身就是一个父类的重写方法,activity中用不用看自己。
// 在Fragment中这句话不能注释,否则Fragment接收不到获取权限的通知。
super.onRequestPermissionsResult(requestCode,permissions,grantResults);
获取多个权限:
// 先判断是否有权限。
if(AndPermission.hasPermission(this, Manifest.permission.READ_SMS)) {
// 有权限,直接do anything.
} else {
// 申请权限。
AndPermission.with(this)
.requestCode(100)
.permission(Manifest.permission.WRITE_CONTACTS, Manifest.permission.READ_SMS)
.send();
}
具体实现参考:https://blog.csdn.net/yanzhenjie1003/article/details/52503533
二、RxPermissions
依赖:
compile 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5@aar'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.5'
申请单个权限:
RxPermissions rxPermissions = new RxPermissions(MainActivity.this);
rxPermissions.request(Manifest.permission.READ_EXTERNAL_STORAGE)
.subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
Toast.makeText(MainActivity.this, "应用需要读写权限", Toast.LENGTH_SHORT).show();
}
@Override
public void onNext(Boolean value) {
if(value){
Toast.makeText(MainActivity.this, "同意权限", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this, "拒绝权限", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
同时申请多个权限并且分别判断权限是否授予:
RxPermissions rxPermission = new RxPermissions(getActivity());
rxPermission
.requestEach(Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_CALENDAR,
Manifest.permission.READ_CALL_LOG,
Manifest.permission.READ_CONTACTS,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.READ_SMS,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA,
Manifest.permission.CALL_PHONE,
Manifest.permission.SEND_SMS)
.subscribe(new Consumer() {
@Override
public void accept(Permission permission) throws Exception {
if (permission.granted) {
// 用户已经同意该权限
Log.d(TAG, permission.name + " is granted.");
} else if (permission.shouldShowRequestPermissionRationale) {
// 用户拒绝了该权限,没有选中『不再询问』(Never ask again),那么下次再次启动时,还会提示请求权限的对话框
Log.d(TAG, permission.name + " is denied. More info should be provided.");
} else {
// 用户拒绝了该权限,并且选中『不再询问』
Log.d(TAG, permission.name + " is denied.");
}
}
});
三、permissions4m(国产手机5.0、6.0权限适配框架/编译时注解框架)
引用
project 中的 build.gradle:
buildscript {
// ...
}
allprojects {
repositories {
// 请添加如下一行
maven { url 'https://jitpack.io' }
}
}
app 中的 build.gradle:
dependencies {
compile 'com.github.jokermonn:permissions4m:2.1.2-lib'
annotationProcessor 'com.github.jokermonn:permissions4m:2.1.2-processor'
}
多个权限申请:
Permissions4M.get(NormalFragment.this)
.requestPermissions(Manifest.permission.BODY_SENSORS, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CALENDAR)
.requestCodes(SENSORS_CODE, LOCATION_CODE, CALENDAR_CODE)
.requestListener(new Wrapper.PermissionRequestListener() {
@Override
public void permissionGranted(int code) {
switch (code) {
case LOCATION_CODE:
ToastUtil.show("地理位置权限授权成功 in fragment with annotation");
break;
case SENSORS_CODE:
ToastUtil.show("传感器权限授权成功 in fragment with annotation");
break;
case CALENDAR_CODE:
ToastUtil.show("读取日历权限授权成功 in fragment with annotation");
break;
default:
break;
}
}
@Override
public void permissionDenied(int code) {
switch (code) {
case LOCATION_CODE:
ToastUtil.show("地理位置权限授权失败 in fragment with annotation");
break;
case SENSORS_CODE:
ToastUtil.show("传感器权限授权失败 in fragment with annotation");
break;
case CALENDAR_CODE:
ToastUtil.show("读取日历权限授权失败 in fragment with annotation");
break;
default:
break;
}
}
@Override
public void permissionRationale(int code) {
switch (code) {
case LOCATION_CODE:
ToastUtil.show("请开启地理位置权限 in fragment with annotation");
break;
case SENSORS_CODE:
ToastUtil.show("请开启传感器权限 in fragment with annotation");
break;
case CALENDAR_CODE:
ToastUtil.show("请开启读取日历权限 in fragment with annotation");
break;
default:
break;
}
}
})
.requestCustomRationaleListener(new Wrapper.PermissionCustomRationaleListener() {
@Override
public void permissionCustomRationale(int code) {
switch (code) {
case LOCATION_CODE:
ToastUtil.show("请开启地理位置权限 in fragment with annotation");
Log.e("TAG", "permissionRationale: 请开启地理位置权限 ");
new AlertDialog.Builder(getActivity())
.setMessage("地理位置权限权限申请:\n我们需要您开启地理位置权限(in fragment with " +
"annotation)")
.setPositiveButton("确定", new DialogInterface
.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Permissions4M.get(NormalFragment.this)
.requestOnRationale()
.requestPermissions(Manifest.permission
.ACCESS_FINE_LOCATION)
.requestCodes(LOCATION_CODE)
.request();
}
})
.show();
break;
case SENSORS_CODE:
ToastUtil.show("请开启传感器权限 in fragment with annotation");
Log.e("TAG", "permissionRationale: 请开启传感器权限 ");
new AlertDialog.Builder(getActivity())
.setMessage("传感器权限申请:\n我们需要您开启传感器权限(in fragment with " +
"annotation)")
.setPositiveButton("确定", new DialogInterface
.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Permissions4M.get(NormalFragment.this)
.requestOnRationale()
.requestPermissions(Manifest.permission
.BODY_SENSORS)
.requestCodes(SENSORS_CODE)
.request();
}
})
.show();
break;
case CALENDAR_CODE:
ToastUtil.show("请开启读取日历权限 in fragment with annotation");
Log.e("TAG", "permissionRationale: 请开启读取日历权限 ");
new AlertDialog.Builder(getActivity())
.setMessage("日历权限申请:\n我们需要您开启日历权限(in fragment with " +
"annotation)")
.setPositiveButton("确定", new DialogInterface
.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Permissions4M.get(NormalFragment.this)
.requestOnRationale()
.requestPermissions(Manifest.permission
.READ_CALENDAR)
.requestCodes(CALENDAR_CODE)
.request();
}
})
.show();
break;
default:
break;
}
}
})
.request();
总起来说,第三个库更加方便简明,建议使用。