Android M 权限适配,简单实用
2016-11-18 本文已影响468人
四月一号
Android M的运行时权限确实是个麻烦的东西. 可能新的项目还好,对于旧项目的改造,就没那么轻松了.为了尽量减少原有代码的改动,简单的封装是有必要的.
先看看哪些权限是需要处理的:
-
电话 -- PHONE
READ_PHONE_STATE
CALL_PHONE
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS -
短信 -- SMS
SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS -
存储空间 -- STORAGE
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE -
摄像头 -- CAMERA
CAMERA -
通讯录 -- CONTACTS
READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS -
地理位置 -- LOCATION
ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION -
日历 -- CALENDAR
READ_CALENDAR
WRITE_CALENDAR -
麦克风 -- MICROPHONE
RECORD_AUDIO -
身体传感器 -- SENSORS
BODY_SENSORS
再看看google提供的相关API:
-
检查权限
public static int checkSelfPermission(@NonNull Context context, @NonNull String permission)
-
申请权限
// activity (android.support.v4.app.ActivityCompat) public static void requestPermissions(final @NonNull Activity activity, final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode) ... //fragment public final void requestPermissions(@NonNull String[] permissions, int requestCode)
-
申请权限的结果
// activity / fragment @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); }
-
判断是否需要权限解释---**关于这一对方法,总结起来就是:第一次请求,或者用户彻底拒绝,返回false;其它时候返回true. **
// activity public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity, @NonNull String permission) ... //fragment public boolean shouldShowRequestPermissionRationale(@NonNull String permission)
通过上面可以看出,权限申请不算难,但是对现有代码结构的破坏性却不小,这里提供一个简单的工具类:
public class PermissionManager {
private static final int GRANTED = PackageManager.PERMISSION_GRANTED;
private Map<String,String> tips = new ArrayMap<>();
private Object obj;
private boolean inActivity;
private String[] ps;
private CallBack callback;
public interface CallBack{
void granted();
}
public static PermissionManager init(@NonNull Activity activity){
return new PermissionManager(activity);
}
public static PermissionManager init(@NonNull Fragment fragment){
return new PermissionManager(fragment);
}
private PermissionManager(@NonNull Object obj) {
this.obj = obj;
inActivity = (obj instanceof Activity);
if(tips.isEmpty()){
tips.put(Manifest.permission.READ_PHONE_STATE,"电话");
tips.put(Manifest.permission.CALL_PHONE,"电话");
tips.put(Manifest.permission.ADD_VOICEMAIL,"电话");
tips.put(Manifest.permission.USE_SIP,"电话");
tips.put(Manifest.permission.PROCESS_OUTGOING_CALLS,"电话");
tips.put(Manifest.permission.SEND_SMS,"短信");
tips.put(Manifest.permission.RECEIVE_SMS,"短信");
tips.put(Manifest.permission.READ_SMS,"短信");
tips.put(Manifest.permission.RECEIVE_WAP_PUSH,"短信");
tips.put(Manifest.permission.RECEIVE_MMS,"短信");
tips.put(Manifest.permission.WRITE_EXTERNAL_STORAGE,"内存卡");
tips.put(Manifest.permission.CAMERA,"摄像头");
tips.put(Manifest.permission.READ_CONTACTS,"通讯录");
tips.put(Manifest.permission.WRITE_CONTACTS,"通讯录");
tips.put(Manifest.permission.GET_ACCOUNTS,"通讯录");
tips.put(Manifest.permission.ACCESS_FINE_LOCATION,"定位");
tips.put(Manifest.permission.ACCESS_COARSE_LOCATION,"定位");
tips.put(Manifest.permission.READ_CALENDAR,"日历");
tips.put(Manifest.permission.WRITE_CALENDAR,"日历");
tips.put(Manifest.permission.RECORD_AUDIO,"麦克风");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
tips.put(Manifest.permission.READ_CALL_LOG,"电话");
tips.put(Manifest.permission.WRITE_CALL_LOG,"电话");
tips.put(Manifest.permission.READ_EXTERNAL_STORAGE,"内存卡");
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
tips.put(Manifest.permission.BODY_SENSORS,"传感器");
}
}
}
/**
* 添加需要申请的权限
*/
public PermissionManager permissions(@NonNull String ... permissions){
ps = null;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && permissions.length > 0){
List<String> tempArr = new ArrayList<>();
for (String permission : permissions) {
if(ContextCompat.checkSelfPermission(inActivity ? (Activity) obj : ((Fragment)obj).getActivity(),permission) != GRANTED){
tempArr.add(permission);
}
}
ps = tempArr.toArray(new String[tempArr.size()]);
}
return this;
}
/**
* 权限申请
*/
public void request(@NonNull CallBack callback){
if(ps != null && ps.length > 0){
this.callback = callback;
if(inActivity){
ActivityCompat.requestPermissions((Activity) obj,ps,97);
}else {
((Fragment)obj).requestPermissions(ps,97);
}
}else {
callback.granted();
}
}
/**
* 申请结果回调(需要在activity 或 fragment 对应的方法中调用)
*/
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if(requestCode == 97 && permissions.length > 0){
int result = 0;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < grantResults.length; i++) {
if(grantResults[i] != GRANTED){
if(result == 0){
result = -1; // 权限被拒绝
}
if(builder.indexOf(tips.get(permissions[i])) < 0){
builder.append(tips.get(permissions[i])).append("、");
}
if(inActivity && !ActivityCompat.shouldShowRequestPermissionRationale((Activity) obj,permissions[i])){
result = -2; // 勾选不再提示
}else if(!inActivity && !((Fragment)obj).shouldShowRequestPermissionRationale(permissions[i])){
result = -2; // 勾选不再提示
}
}
}
if(result == 0){
callback.granted();
}else if(result == -1){
Toast.makeText(inActivity ? (Activity) obj : ((Fragment)obj).getActivity(),"缺少权限!",Toast.LENGTH_SHORT).show();
}else {
builder.deleteCharAt(builder.lastIndexOf("、"));
new AlertDialog.Builder(inActivity ? (Activity) obj : ((Fragment)obj).getActivity())
.setTitle("缺少权限")
.setMessage(builder.toString())
.setPositiveButton("去设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + (inActivity ? (Activity) obj : ((Fragment)obj).getActivity()).getPackageName()));
(inActivity ? (Activity) obj : ((Fragment)obj).getActivity()).startActivity(intent); } }).create().show();
}
}
}
}
功能说明:
- 兼容 activity 和 fragment,使用方式一模一样
- 支持多权限同时申请,使用方式和申请单一权限一模一样
- 默认处理了权限被拒绝
- 如果用户没有勾选不再提示: toast提示权限被拒绝
- 如果用户彻底拒绝权限,弹窗提示所有被拒绝的权限,点击打开权限设置
使用方式:
-
初始化
PermissionManager permissionManager = PermissionManager.init(this);
-
处理回调
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); permissionManager.onRequestPermissionsResult(requestCode, permissions, grantResults); }
-
申请权限
permissionManager.permissions( Manifest.permission.READ_PHONE_STATE, Manifest.permission.CAMERA, Manifest.permission.READ_CALENDAR).request(new PermissionManager.CallBack() { @Override public void granted() { Toast.makeText(getActivity(),"获得权限",Toast.LENGTH_SHORT).show(); } });
测试结果: