Android权限

6.0之前(APi<23)

google原生为:只要manifest中注册了权限,用户安装后就默认授予了所声明的权限。

中国制造:用户安装应用后可以取消权限的授予

解决办法:

1.在使用部分权限时进行权限查询,查询所需权限是否仍是授予状态

2.进行错误抓取,保证程序活跃,进行错误处理,包括try,catch,检查返回数据

6.0之后(API>=23)

google原生与中国制造基本一致:加入了运行时权限概念,权限大致分为普通权限和危险权限。

中国制造:可能会有用户拒绝权限申请但是没有返回或返回授予成功的情况,此情况需要额外进行处理。

对于运行时权限应用必须在使用的时候进行申请,用户自主选择是否授予。如果拒绝授予应用亦不会crash,只是用户无法使用这一部分功能。

危险权限一共有9组24种,只要用户授予了每一组内的任一权限,对应的权限组都会被授予。

对应方法:

查询权限

public static int checkSelfPermission(Context context,String permission)

申请权限

public static void requestPermissions(final Activity activity, final String[] permissions,final int requestCode)

申请结果返回

public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults)

当权限申请被拒绝后,该方法将返回true,我们可以在此时对所需权限进行详细说明

public static boolean shouldShowRequestPermissionRationale(Activity activity,String permission)

附加知识:自定义权限

声明:

<permission android:name="com.example.selfpermissondemo.permisson.OPEN_ACTIVITY" android:protectionLevel="normal" android:label="自定义权限"/>

使用例子:

<activity android:name=".PermissionActivity" android:permission="com.example.selfpermissondemo.permisson.OPEN_ACTIVITY"> <intent-filter> <action android:name="com.example.selfpermissondemo.permission.activity"></action> <category android:name="android.intent.category.DEFAULT"></category> </intent-filter> </activity>

国产ROM

途径:可以使用AppOpsManager#noteOp 类进行权限检测

但是国产ROM的此类被@hide标注,开发者无法直接使用,可以使用google在V4包推出的AppOpsManager 类进行权限检测,该类从API4向后兼容。

权限检测例子:

AppOpsManagerCompat 在API<23的版本下无法正常使用会全部返回true或MODE_IGNORED

API>=23:

/** * 检测权限,小米上使用 * * @param context * @param permission * @return */ *

*private static boolean hasSelfPermissionForXiaomi(Context context, String permission) { *

// 将permission转换成OP_ String permissionToOp = AppOpsManagerCompat.permissionToOp(permission);

if (permissionToOp == null) {

// 不支持的权限,或者是normal permission

return true;

}

int noteOp = AppOpsManagerCompat.noteOp(context, permissionToOp, android.os.Process.myUid(), context.getPackageName());

// AppOpsManagerCompat 与 checkSelfPermission都检测过则表明权限被开启

return noteOp == AppOpsManagerCompat.MODE_ALLOWED && ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED; }

API<23

使用反射对AppOpsManager#noteOp 类进行访问

/** * 通过反射调用 AppOpsManager#noteOp * * @param context * @param op * @return */

public static boolean noteOp(Context context, int op) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);

if (appOpsManager != null) {

try {

Method method = AppOpsManager.class.getDeclaredMethod("noteOp", Integer.TYPE, Integer.TYPE, String.class);

int noteOp = (int) method.invoke(appOpsManager, op, Process.myUid(), context.getPackageName());

return noteOp == AppOpsManager.MODE_ALLOWED;

}

catch (Exception e) {

e.printStackTrace();

} } }

return false;

}

国产ROM总结: 对于权限检测:

  1. Build.VERSION.SDK_INT >= 23时,直接使用我们上面的hasSelfPermissionForXiaomi方法
  2. Build.VERSION.SDK_INT < 23时,使用我们上面的反射方法noteOp

对于权限申请:

  1. Build.VERSION.SDK_INT >= 23时,使用上节介绍的标准运行时权限申请方式
  2. Build.VERSION.SDK_INT < 23时,没有办法申请API,只能通过引导用户跳转权限设置页进行配置。

特殊权限

SYSTEM_ALERT_WINDOW 和WRITE_SETTINGS

这两种权限为特别敏感的权限,需要用户在系统设置界面进行手动授权

例子:

// 定义权限申请request code

public static int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE= 123;

public void requestPermission() {

// 通过Settings.canDrawOverlays(this)可以检测是否包含SYSTEM_ALERT_WINDOW权限

if (!Settings.canDrawOverlays(this)) {

// 申请权限,跳转到系统权限设置页面

Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));

startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);

} }

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

// 在onActivityResult中判断是否授权成功

if (requestCode == ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE) {

if (Settings.canDrawOverlays(this)) {

// 授权成功

} } }

附加:悬浮窗实现可以使用LayoutParams.TYPE_TOAST 替换 LayoutParams.TYPE_SYSTEM_ALERTLayoutParams.TYPE_TOAST的使用不需要权限。(LayoutParams.TYPE_TOAST限制就是Android 4.4 (API level 18)及以下使用TYPE_TOAST无法接收触摸事件)

补充:“不依赖Activity”进行权限申请

可自己注册一个activity专门用作申请权限使用

demo中我会用到

注意

当系统要求用户授予权限时,用户可以选择指示系统不再要求提供该权限。这种情况下,无论应用在什么时候使用 requestPermissions() 再次要求该权限,系统都会立即拒绝此请求。系统会调用您的 onRequestPermissionsResult() 回调方法,并传递 PERMISSION_DENIED,如果用户再次明确拒绝了您的请求,系统将采用相同方式操作。这意味着当您调用 requestPermissions() 时,您不能假设已经发生与用户的任何直接交互。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值