Appops权限管理

注:本文是根据Android 5.0的代码为基础

1. Appops简介

Appops是Application Operations的简称,是关于应用权限管理的一套方案,但这里的应用指的是系统应用,这些API不对第三方应用开放。Google从4.3开始推出Appops, 但一直到最新的Android N都没有在Settings里面开放Appops的入口,但这套方案却一直在后台默默的运行着。

2. 在 Settings中打开Appops

  1. 在. /packages/apps/Settings/res/xml/security_settings_misc.xml中配置
 <Preference android:key="manage_device_admin"
          android:title="@string/manage_device_admin"
          android:summary="@string/manage_device_admin_summary"
          android:persistent="false" />                                             

+ <Preference android:key="app_ops_summary"
+         android:title="@string/app_ops_settings"
+         android:summary="@string/app_ops_settings_summary"
+         android:persistent="false"/>
  1. 添加相应处理代码
    在./packages/apps/Settings/src/com/android/settings/SecuritySettings.java的onPreferenceTreeClick方法中添加相应的处理函数即可。此处就不贴具体代码了。

  2. 效果图
    Appops权限管理_第1张图片
    每个权限有三种状态。允许(Allowed),禁止(Ignored),总是询问(Always ask),见

 /frameworks/base/core/java/android/app/AppOpsManager.java
     /**
     * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
     * allowed to perform the given operation.
     */
    public static final int MODE_ALLOWED = 0;

    /**
     * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
     * not allowed to perform the given operation, and this attempt should
     * silently fail (it should not cause the app to crash).
     */
    public static final int MODE_IGNORED = 1;

    /**
     * Result from {@link #checkOpNoThrow}, {@link #noteOpNoThrow}, {@link #startOpNoThrow}: the
     * given caller is not allowed to perform the given operation, and this attempt should
     * cause it to have a fatal error, typically a {@link SecurityException}.
     */
    public static final int MODE_ERRORED = 2;

    /**
     * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller should
     * use its default security check.  This mode is not normally used; it should only be used
     * with appop permissions, and callers must explicitly check for it and deal with it.
     */
    public static final int MODE_DEFAULT = 3;

    /**
     * @hide Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}:
     * AppOps Service should show a dialog box on screen to get user
     * permission.
     */
    public static final int MODE_ASK = 4;

3. Appops结构分析

3.1 Appops结构组织

Appops可以用如下图来描述其结构
Appops权限管理_第2张图片

可以看到Appops的两个重要组成部分是AppOpsManager和AppOpsService,它们是典型的客户端和服务端设计,通过Binder跨进程调用。

AppOpsManager提供标准的API供APP调用,但google有明确说明,大部分只针对系统应用。

/frameworks/base/core/java/android/app/AppOpsManager.java
/**
 * API for interacting with "application operation" tracking.
 *
 * 

This API is not generally intended for third party application developers; most * features are only available to system applications. Obtain an instance of it through * {@link Context#getSystemService(String) Context.getSystemService} with * {@link Context#APP_OPS_SERVICE Context.APP_OPS_SERVICE}.

*/
public class AppOpsManager {

AppOpsService是做最终检查的系统服务,它的注册名字是appops, 应用可以类似于
mAppOps=(AppOpsManager)getContext().getSystemService(Context.APP_OPS_SERVICE);的方式来获取这个服务。

3.2举例分析

当用户想要改变(比如禁止)某个应用的某个权限,通过AppOpsDetails.java调用AppOpsManager的setMode方法,进而调用AppOpsService的setMode方法,最后会把修改的值记录到/data/system/appops.xml中.

比如,当在Settings中禁掉Gallery的Camera权限,Appops会把记录 (26就是代表的Camera权限,1代表禁止)记录到appops.xml文件中,各种权限对应的值在AppOpsManager.java中查看

    /frameworks/base/core/java/android/app/AppOpsManager.java
    /** @hide */
    public static final int OP_SYSTEM_ALERT_WINDOW = 24;
    /** @hide */
    public static final int OP_ACCESS_NOTIFICATIONS = 25;
    /** @hide */
    public static final int OP_CAMERA = 26;

appops.xml中gallery相关的值前后变化如下

修改前:
Appops权限管理_第3张图片

修改后:
Appops权限管理_第4张图片

当应用需要去检查某个权限的时候,会调用checkOp或者noteOp去读取/data/system/appops.xml里面对应的值。

4.常用的接口

接口在AppOpsManager.java中,但大部分只针对系统应用。

  1. public int checkOp(String op, int uid, String packageName)
    检查某个应用(packageName)是否具有某个权限(op)

  2. public int checkOpNoThrow(String op, int uid, String packageName)
    同checkOp,但出错不会报异常,返回MODE_ERRORED

  3. public int noteOp(String op, int uid, String packageName)
    检查某个应用(packageName)是否具有某个权限(op),同时会做记录

  4. public int noteOpNoThrow(String op, int uid, String packageName)
    同checkOp,但出错不会报异常,返回MODE_ERRORED

  5. /* @hide /
    public void setMode(int code, int uid, String packageName, int mode)
    设置权限,code是权限的标识码,比如OP_READ_CONTACTS, mode是权限的状态,比如MODE_ALLOWED.

5. 系统工具Appops

Android提供了命令行的方式来更改某个应用的某个权限,进入adb shell可以查看相应用法:

root@ myPhone:/ # appops                                                        
usage: adb shell appops set <PACKAGE> <OP> <allow|ignore|deny|default> [--user <USER_ID>]
  <PACKAGE> an Android package name.
  <OP>      an AppOps operation.
  <USER_ID> the user id under which the package is installed. If --user is not
            specified, the current user is assumed.

6. Appops的不足

6.1 并不是所有的控制都生效

我们在3.2举的例子就是一个佐证,当禁掉Gallery的Camera的权限以后,在appops.xml里面也修改了相应的记录,但是当进入Gallery以后,还是可以拍照。
Appops权限管理_第5张图片

这里启动camera并没有走appops的流程,而是直接发送intent去启动 Camera.

6.2 没有统一提示的接口

对于那些控制生效的情况,给用户的提示简直就是五花八门,有的就直接没有提示,比如禁掉dialer的READ_CONTACT权限,当进入Dialer查看联系人时,直接是显示没有联系人。

又比如当禁止掉Camera的Camera权限,当启动Camera的时候,直接提示错误,让一般用户不知所以然。
Appops权限管理_第6张图片

7. 总结

Appops从Android 4.3就已经在后台运行,一直到即将推出的Android N也没有在Settings中打开入口,可以看出,这套方案并不是非常成熟。当然,整体的设计还是非常出色,值得我们借鉴。

你可能感兴趣的:(Android权限)