从android6.0之后,android对用户的权限进行相对教严格的管控,针对重要的权限,用户在第一安装并使用的时候,系统以弹框的形式向用户获取,用户的权限授取直接关乎着应用是否能正常使用对应的功能;因此这里对android 6.0之后的动态权限获取进行整理并记录备忘;由于国内的android系统各大手机厂商都有所定制;对于6.0之后权限,小米系统是存在2个地方的权限授取,必须2个地方都启动,才能正常使用;因此带来了一些不必要的坑;这里一起进行整理记录
不多说,先上代码及效果图
为了不影响用户的正使用,我们一般都会在应用的启动页对该应用所用到的所有权限进行授权;避免用户在使用过程中还存在权限授取的动作,具体流程如下:
普通权限
直接在AndroidManifest.xml中获取即可
检测权限是否开启
/**
* 检测权限
*
* @return true 所需权限全部授取 false 存在未授权的权限
*/
public boolean isAllGranted() {
/**
* 第 1 步: 检查是否有相应的权限
*/
boolean isAllGranted = checkPermissionAllGranted(
new String[]{
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}
);
return isAllGranted;
}
/**
* 检查是否拥有指定的所有权限
*/
private boolean checkPermissionAllGranted(String[] permissions) {
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
// 只要有一个权限没有被授予, 则直接返回 false
return false;
}
}
return true;
}
授权多个权限
// 一次请求多个权限, 如果其他有权限是已经授予的将会自动忽略掉
ActivityCompat.requestPermissions(
this,
new String[]{
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},
MY_PERMISSION_REQUEST_CODE
);
所有权限授取之后的回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == MY_PERMISSION_REQUEST_CODE) {
boolean isAllGranted = true;
// 判断是否所有的权限都已经授予了
for (int grant : grantResults) {
if (grant != PackageManager.PERMISSION_GRANTED) {
isAllGranted = false;
break;
}
}
if (isAllGranted) {
// 如果所有的权限都授予了, 跳转到主页
gotoHomeActivity();
} else {
// 弹出对话框告诉用户需要权限的原因, 并引导用户去应用权限管理中手动打开权限按钮
openAppDetails();
}
}
}
判断是否是小米系统
/**
* 检查手机是否是miui系统
*
* @return
*/
public boolean isMIUI() {
String device = Build.MANUFACTURER;
System.out.println("Build.MANUFACTURER = " + device);
if (device.equals("Xiaomi")) {
System.out.println("this is a xiaomi device");
Properties prop = new Properties();
try {
prop.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop")));
} catch (IOException e) {
e.printStackTrace();
return false;
}
return prop.getProperty(KEY_MIUI_VERSION_CODE, null) != null
|| prop.getProperty(KEY_MIUI_VERSION_NAME, null) != null
|| prop.getProperty(KEY_MIUI_INTERNAL_STORAGE, null) != null;
} else {
return false;
}
}
判断授权管理界面中的权限授取
这里需要注意的是需要对权限进行一个个的判断,无法像上面一样用个集合就进行判断了;具体应用需要那些这里就去判断那些就好了。
/**
* 判断小米MIUI系统中授权管理中对应的权限授取
*
* @return false 存在核心的未收取的权限 true 核心权限已经全部授权
*/
public boolean initMiuiPermission() {
AppOpsManager appOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
int locationOp = appOpsManager.checkOp(AppOpsManager.OPSTR_FINE_LOCATION, Binder.getCallingUid(), getPackageName());
if (locationOp == AppOpsManager.MODE_IGNORED) {
return false;
}
int cameraOp = appOpsManager.checkOp(AppOpsManager.OPSTR_CAMERA, Binder.getCallingUid(), getPackageName());
if (cameraOp == AppOpsManager.MODE_IGNORED) {
return false;
}
int phoneStateOp = appOpsManager.checkOp(AppOpsManager.OPSTR_READ_PHONE_STATE, Binder.getCallingUid(), getPackageName());
if (phoneStateOp == AppOpsManager.MODE_IGNORED) {
return false;
}
int readSDOp = appOpsManager.checkOp(AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, Binder.getCallingUid(), getPackageName());
if (readSDOp == AppOpsManager.MODE_IGNORED) {
return false;
}
int writeSDOp = appOpsManager.checkOp(AppOpsManager.OPSTR_WRITE_EXTERNAL_STORAGE, Binder.getCallingUid(), getPackageName());
if (writeSDOp == AppOpsManager.MODE_IGNORED) {
return false;
}
return true;
}
MIUI不听版本,跳帧授权管理界面的方式不一样
各个不同系统的设置界面跳转请参考博客末尾的帮助类,以下代码摘自其中。
public static void Xiaomi(Activity activity) {
// 只兼容miui v5/v6 的应用权限设置页面,否则的话跳转应用设置页面(权限设置上一级页面)
String miuiVersion = getMiuiVersion();
Intent intent = null;
if ("V5".equals(miuiVersion)) {
Uri packageURI = Uri.parse("package:" + activity.getApplicationInfo().packageName);
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
} else if ("V6".equals(miuiVersion) || "V7".equals(miuiVersion)) {
intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
intent.putExtra("extra_pkgname", activity.getPackageName());
} else if ("V8".equals(miuiVersion)) {
intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
intent.putExtra("extra_pkgname", activity.getPackageName());
} else {
}
if (null != intent)
activity.startActivity(intent);
}
以下代码为结合网友提供的再根据情况调整了一下小米相关的跳转
package com.lpf.permission;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.v7.appcompat.BuildConfig;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
*/
public class JumpPermissionManagement {
/**
* Build.MANUFACTURER
*/
private static final String MANUFACTURER_HUAWEI = "Huawei";//华为
private static final String MANUFACTURER_MEIZU = "Meizu";//魅族
private static final String MANUFACTURER_XIAOMI = "Xiaomi";//小米
private static final String MANUFACTURER_SONY = "Sony";//索尼
private static final String MANUFACTURER_OPPO = "OPPO";
private static final String MANUFACTURER_LG = "LG";
private static final String MANUFACTURER_VIVO = "vivo";
private static final String MANUFACTURER_SAMSUNG = "samsung";//三星
private static final String MANUFACTURER_LETV = "Letv";//乐视
private static final String MANUFACTURER_ZTE = "ZTE";//中兴
private static final String MANUFACTURER_YULONG = "YuLong";//酷派
private static final String MANUFACTURER_LENOVO = "LENOVO";//联想
/**
* 此函数可以自己定义
*
* @param activity
*/
public static void GoToSetting(Activity activity) {
switch (Build.MANUFACTURER) {
case MANUFACTURER_HUAWEI:
Huawei(activity);
break;
case MANUFACTURER_MEIZU:
Meizu(activity);
break;
case MANUFACTURER_XIAOMI:
Xiaomi(activity);
break;
case MANUFACTURER_SONY:
Sony(activity);
break;
case MANUFACTURER_OPPO:
OPPO(activity);
break;
case MANUFACTURER_LG:
LG(activity);
break;
case MANUFACTURER_LETV:
Letv(activity);
break;
default:
ApplicationInfo(activity);
Log.e("goToSetting", "目前暂不支持此系统");
break;
}
}
public static void Huawei(Activity activity) {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
ComponentName comp = new ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity");
intent.setComponent(comp);
activity.startActivity(intent);
}
public static void Meizu(Activity activity) {
Intent intent = new Intent("com.meizu.safe.security.SHOW_APPSEC");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
activity.startActivity(intent);
}
public static void Xiaomi(Activity activity) {
// 只兼容miui v5/v6 的应用权限设置页面,否则的话跳转应用设置页面(权限设置上一级页面)
String miuiVersion = getMiuiVersion();
Intent intent = null;
if ("V5".equals(miuiVersion)) {
Uri packageURI = Uri.parse("package:" + activity.getApplicationInfo().packageName);
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
} else if ("V6".equals(miuiVersion) || "V7".equals(miuiVersion)) {
intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
intent.putExtra("extra_pkgname", activity.getPackageName());
} else if ("V8".equals(miuiVersion)) {
intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
intent.putExtra("extra_pkgname", activity.getPackageName());
} else {
}
if (null != intent)
activity.startActivity(intent);
}
public static void Sony(Activity activity) {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
ComponentName comp = new ComponentName("com.sonymobile.cta", "com.sonymobile.cta.SomcCTAMainActivity");
intent.setComponent(comp);
activity.startActivity(intent);
}
public static void OPPO(Activity activity) {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
ComponentName comp = new ComponentName("com.color.safecenter", "com.color.safecenter.permission.PermissionManagerActivity");
intent.setComponent(comp);
activity.startActivity(intent);
}
public static void LG(Activity activity) {
Intent intent = new Intent("android.intent.action.MAIN");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
ComponentName comp = new ComponentName("com.android.settings", "com.android.settings.Settings$AccessLockSummaryActivity");
intent.setComponent(comp);
activity.startActivity(intent);
}
public static void Letv(Activity activity) {
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
ComponentName comp = new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.PermissionAndApps");
intent.setComponent(comp);
activity.startActivity(intent);
}
/**
* 只能打开到自带安全软件
*
* @param activity
*/
public static void _360(Activity activity) {
Intent intent = new Intent("android.intent.action.MAIN");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("packageName", BuildConfig.APPLICATION_ID);
ComponentName comp = new ComponentName("com.qihoo360.mobilesafe", "com.qihoo360.mobilesafe.ui.index.AppEnterActivity");
intent.setComponent(comp);
activity.startActivity(intent);
}
/**
* 应用信息界面
*
* @param activity
*/
public static void ApplicationInfo(Activity activity) {
Intent localIntent = new Intent();
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 9) {
localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
localIntent.setData(Uri.fromParts("package", activity.getPackageName(), null));
} else if (Build.VERSION.SDK_INT <= 8) {
localIntent.setAction(Intent.ACTION_VIEW);
localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
localIntent.putExtra("com.android.settings.ApplicationPkgName", activity.getPackageName());
}
activity.startActivity(localIntent);
}
/**
* 系统设置界面
*
* @param activity
*/
public static void SystemConfig(Activity activity) {
Intent intent = new Intent(Settings.ACTION_SETTINGS);
activity.startActivity(intent);
}
public static String getMiuiVersion() {
String line;
BufferedReader input = null;
try {
Process p = Runtime.getRuntime().exec("getprop ro.miui.ui.version.name");
input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
line = input.readLine();
input.close();
} catch (IOException ex) {
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
}
}
}
return line;
}
}
这里只找了部分的手机进行了测试;由于android市场的复杂性,可能存在不兼容的情况,主要的问题也应该是在授权设置哪里;可以根据特定的手机进行调整即可;
源码下载