Android深入学习之各种隐私权限判断和获取方法总结

  从Android SDK 23 开始, Android就改变了权限的管理模式。对于一些涉及用户隐私的权限则需要用户的授权才可以使用。在此之前,开发者只需要在AndroidManifest.xml中注册,如网络权限、wifi权限等等:权限即可,但是现在除了注册还需要进行手动的授权。
  没有涉及用户隐私的权限申请的方式比较简单,即只需要在AndroidManifest.xml中注册,如网络权限、wifi权限等等:

  本文主要研究涉及用户隐私权限的判断和申请方法,根据需要用户的操作不同,将这类权限分为三类:

  1. 在应用中直接打开权限申请框,由用户确定打开;
  2. 打开对应权限的设置页面,由用户找到指定应用并勾选;
  3. 打开应用对应的详情设置页面,由用户找到所需权限并打开。

1.在应用中直接打开权限申请框,由用户确定

  以申请手机识别码和申请读写手机存储权限为例,具体代码如下:

boolean hasPhoneStatePermission = false;boolean hasWriteStorePermission = false;// 判断是否具有某权限的方法ContextCompat.checkSelfPermission()if (ContextCompat.checkSelfPermission()(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {    hasPhoneStatePermission = true;}if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {    hasWriteStorePermission = true;}if (hasPhoneStatePermission && hasWriteStorePermission) {    return;}// 可一次申请多个权限的方法ActivityCompat.requestPermissions(),会依次弹出对应的权限弹框ActivityCompat.requestPermissions(this, { Manifest.permission.READ_PHONE_STATE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, CODE);

  PS:权限必须在AndroidMainifest.xml里面声明,否则不生效:

2.打开对应权限的设置页面,由用户找到指定应用再勾选

  首页需要判断是否已具有要申请的权限,不同的权限判断方法不同,需要单独区分权限,本文罗列几个常用权限通知栏读取权限、无障碍权限以及悬浮窗权限的判断方法:
  是否具有通知栏读取权限判断方法:

public static boolean isNoticationEnabled(String packageName) {    String allowedInfo = Settings.Secure.getString(getContentResolver(), "enabled_notification_listeners");    if (allowedInfo == null || !allowedInfo.contains(packageName)) {        return false;    } else {        return true;    }}

  是否具有无障碍权限判断方法:

public static boolean isAccessibilityServiceEnabled(String packageName) {    AccessibilityManager accessibilityManager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);    List accessibilityServices = accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);    for (AccessibilityServiceInfo info : accessibilityServices) {        if (info != null && info.getId().contains(packageName)) {            Toast.makeText(this, "恭喜你,你的应用已具有无障碍权限!!!", Toast.LENGTH_SHORT).show();            return true;        }    }    return false;}

  是否具有悬浮窗权限判断方法:

public static boolean checkAlertWindowsPermission(Context context) {    try {        Object object = context.getSystemService(Context.APP_OPS_SERVICE);        if (object == null) {            return false;        }        Class localClass = object.getClass();        Class[] arrayOfClass = new Class[3];        arrayOfClass[0] = Integer.TYPE;        arrayOfClass[1] = Integer.TYPE;        arrayOfClass[2] = String.class;        Method method = localClass.getMethod("checkOp", arrayOfClass);        if (method == null) {            return false;        }        Object[] arrayOfObject1 = new Object[3];        arrayOfObject1[0] = 24;        arrayOfObject1[1] = Binder.getCallingUid();        arrayOfObject1[2] = context.getPackageName();        int m = ((Integer) method.invoke(object, arrayOfObject1));        return m == AppOpsManager.MODE_ALLOWED;    } catch (Exception ex) {    }    return false;}

  在判断没有需要申请的权限的情况下,需要跳转到对应权限开启页面,由用户手动打开,本文罗列几个常用权限通知栏读取权限、无障碍权限以及悬浮窗权限的开启方法:
  通知栏读取权限界面开启方法:

startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));

  无障碍权限界面开启方法:

startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));

  悬浮窗权限界面开启方法:

Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);intent.setData(Uri.parse("package:" + packageName)); // packageName为对应应用包名startActivity(intent);

3.打开应用对应的详情设置页面,打开需要申请的权限

  首页需要判断是否已具有要申请的权限,这个类别的以通知栏显示权限的判断方法为例:
  是否具有通知栏显示权限判断方法:

private static final String CHECK_OP_NO_THROW = "checkOpNoThrow";private static final String OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION";public static boolean areNotificationsEnabled(Context context) {    boolean flag = true;    NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);    if (Build.VERSION.SDK_INT >= 24) {        try {            Class cls = Class.forName("android.app.NotificationManager");            Method method = cls.getDeclaredMethod("areNotificationsEnabled");            method.setAccessible(true);            flag = (boolean) method.invoke(manager,new Object[]{});        } catch (Exception e) {            e.printStackTrace();        }    } else if (Build.VERSION.SDK_INT >= 19) {        Object appOps = context.getSystemService("appops");        ApplicationInfo appInfo = context.getApplicationInfo();        String pkg = context.getApplicationContext().getPackageName();        int uid = appInfo.uid;        try {            Class<?> appOpsClass = Class.forName("android.app.AppOpsManager");            Method checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE,                         Integer.TYPE, String.class);            Field opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION);            int value = (int) opPostNotificationValue.get(Integer.class);            int v = (int) checkOpNoThrowMethod.invoke(appOps, value, uid, pkg);            return  v == 0;        } catch (Exception e) {            return true;        }    }    return flag;}

  打开应用对应的详情设置页面:

private void toSettingDetail() {    Intent intent = new Intent();    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);    if (Build.VERSION.SDK_INT >= 9) {        intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");        intent.setData(Uri.fromParts("package", Constants.PACKAGE_NAME, null));    } else if (Build.VERSION.SDK_INT <= 8) {        intent.setAction(Intent.ACTION_VIEW);        intent.setClassName("com.android.settings", "com.android.setting.InstalledAppDetails");        intent.putExtra("com.android.settings.ApplicationPkgName", packageName); // packageName为对应应用包名    }    startActivity(intent);}

更多相关文章

  1. Android拷贝工程不覆盖原工程的配置方法
  2. Android(安卓)管理多个fragment(处理Activity被回收的情况)
  3. J2me游戏如何快速移植到Android(安卓)(2)
  4. 关于 android app 返回键模拟 home键 功能的介绍_仿QQ返回键 又
  5. 无标题文浅入浅出 Android(安卓)安全 (三) Android(安卓)本地用户
  6. android 地理位置共享服务
  7. Android的多媒体技术――MediaPlayer实现音频与视频的播放
  8. 【揭秘】极光推送ios、Android消息推送达率的原理
  9. Android热修复(一):底层替换、类加载原理总结 及 DexClassLoader类

随机推荐

  1. Android中的样式和主题(Styles and Themes
  2. Android中利用“反射”动态加载R文件中的
  3. Android异步任务的处理方法
  4. 【已解决】Android真机设备调试时LogCat
  5. 将Android(安卓)Studio的设置恢复到初始
  6. 用android实现GB28181前端设备接入平台
  7. 组件化:腾讯 T3 Android(安卓)高级开发岗
  8. Android(安卓)消息循环知识
  9. android中如何让一个不知道高度的控件正
  10. 今天体会最深的一点就是android的生命周