Android 6.0动态权限及小米(MIUI)权限的特殊处理
2017-09-30 10:24
561 查看
前言
常规操作权限的页面及流程
权限说明
权限授取流程
小米权限特殊处理
各个android操作系统跳转到设置页面的公共方法
总结
不多说,先上代码及效果图
源码
源码下载
效果图
允许授权
二次授权
用户第一次使用并允许授权的流程
如果用户第一次使用的时候,取消了部分关键授权,直接影响到app的使用的二次授权流程
如果用户第一次使用的时候,取消了部分关键授权,针对小米MIUI5以上的系统的授权流程
直接在AndroidManifest.xml中获取即可
ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
REQUEST_INSTALL_PACKAGES
SET_ALARM
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
UNINSTALL_SHORTCUT
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
危险权限,需要动态申请的权限
Build.VERSION.SDK_INT >= 23
检测权限是否开启
授权多个权限
所有权限授取之后的回调
判断授权管理界面中的权限授取
这里需要注意的是需要对权限进行一个个的判断,无法像上面一样用个集合就进行判断了;具体应用需要那些这里就去判断那些就好了。
MIUI不听版本,跳帧授权管理界面的方式不一样
各个不同系统的设置界面跳转请参考博客末尾的帮助类,以下代码摘自其中。
小米系统测试效果
初次允许授权
二次授权
源码下载
常规操作权限的页面及流程
权限说明
权限授取流程
小米权限特殊处理
各个android操作系统跳转到设置页面的公共方法
总结
前言
从android6.0之后,android对用户的权限进行相对教严格的管控,针对重要的权限,用户在第一安装并使用的时候,系统以弹框的形式向用户获取,用户的权限授取直接关乎着应用是否能正常使用对应的功能;因此这里对android 6.0之后的动态权限获取进行整理并记录备忘;由于国内的android系统各大手机厂商都有所定制;对于6.0之后权限,小米系统是存在2个地方的权限授取,必须2个地方都启动,才能正常使用;因此带来了一些不必要的坑;这里一起进行整理记录不多说,先上代码及效果图
源码
源码下载
效果图
允许授权
二次授权
常规操作权限的页面及流程
为了不影响用户的正使用,我们一般都会在应用的启动页对该应用所用到的所有权限进行授权;避免用户在使用过程中还存在权限授取的动作,具体流程如下:用户第一次使用并允许授权的流程
如果用户第一次使用的时候,取消了部分关键授权,直接影响到app的使用的二次授权流程
如果用户第一次使用的时候,取消了部分关键授权,针对小米MIUI5以上的系统的授权流程
权限说明
普通权限直接在AndroidManifest.xml中获取即可
ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
REQUEST_INSTALL_PACKAGES
SET_ALARM
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
UNINSTALL_SHORTCUT
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
危险权限,需要动态申请的权限
权限授取流程
检测是否是6.0以上的系统Build.VERSION.SDK_INT >= 23
检测权限是否开启
/** * 检测权限 * * @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); }
小米系统测试效果
初次允许授权
二次授权
各个android操作系统跳转到设置页面的公共方法
以下代码为结合网友提供的再根据情况调整了一下小米相关的跳转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市场的复杂性,可能存在不兼容的情况,主要的问题也应该是在授权设置哪里;可以根据特定的手机进行调整即可;源码下载
相关文章推荐
- 小米6.0动态权限特殊处理
- Android 6.0+ 动态权限 一种清爽的封装过程(以及多个权限的处理)
- Android 6.0动态权限介绍与处理
- android 6.0 动态权限处理
- Android 6.0: 动态权限管理的处理
- Android 6.0 动态权限申请简单简洁优雅的处理方式
- Android 6.0+ 动态权限 一种清爽的封装过程(以及多个权限的处理)
- [置顶] android 6.0动态权限在进入MainActivity之前的统一处理
- Android 6.0+ 动态权限 一种清爽的封装过程(以及多个权限的处理)
- android 6.0 动态权限处理
- Android 6.0 动态权限申请封装的处理方式
- RxPermissions源码分析:使用RxJava处理Android 6.0运行时动态权限获取
- RxPermissions源码分析:使用RxJava处理Android 6.0运行时动态权限获取
- Android 6.0动态权限申请的处理
- Android 6.0 权限检测处理
- android 6.0权限处理
- Android 6.0 蓝牙搜索不到设备原因,MIUI权限申请机制方法
- Android 6.0权限处理
- Android 6.0: 动态权限管理的解决方案
- Android 6.0 运行时权限处理完全解析