之前在操作手机短信的时候,碰见一个这样的问题。当用户用我的软件进行删除短信时,出现操作失败。(声明一下,在清单文件中已添加了操作的短信数据库的权限)
出现这样的情况主要是,Android5.0之后默认是把操作短信数据库的权限禁用了,类似于MIUI把第三方用户的弹窗权限禁用。这里知道原因,那就开始寻找解决办法呗,既然可以禁用,那肯定可以恢复。
经过查证,发现Android有一个原生应用程序权限管理软件(AppOps),只不过被Google给隐藏掉了。既然知道有这样的软件,那就好办了呗。
这里列举一下,部分重要的API接口。AppOpsManager这里就不介绍了。
如下:
int |
Op对应一个权限操作,该接口来检测应用是否具有该项操作权限。此方法最终调用了如下方法
int checkOp(int op, int uid, String packageName) 而此方法被隐藏了,我们要用它的话,可以通过反射形式
int |
和checkOp基本相同,但是在检验后会做记录。
int | checkOpNoThrow(String op, int uid, String packageName) |
和checkOp类似,但是权限错误,不会抛出SecurityException,而是返回AppOpsManager.MODE_ERRORED.
int | noteOpNoThrow(String op, int uid, String packageName) |
类似noteOp,但不会抛出SecurityException。
void setMode ( int code, int uid, String packageName, int mode)
这个是我们最需要的方法,改变app的权限设置,但偏偏被google隐藏了。
code代表具体的操作权限, mode代表要更改成的类型(允许 /禁止 / 提示)
最后贴出自行开启操作短息数据库权限方法
public static void setPermission(Context context) {
AppOpsManager mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Class<?> mAppOpsManagerClass;
try {
mAppOpsManagerClass = Class.forName("android.app.AppOpsManager");
int uid = context.getApplicationInfo().uid;
String pkg = context.getPackageName();
//返回 0 就代表有权限,1代表没有权限,-1函数出错啦
if (((int) mAppOpsManagerClass
.getDeclaredMethod("checkOp", int.class, int.class, String.class).invoke
(mAppOps, 15, uid, pkg)) != 0) {
Method method = mAppOpsManagerClass
.getDeclaredMethod("setMode", int.class, int.class, String.class, int
.class);
method.invoke(mAppOps, 15, uid, pkg, AppOpsManager.MODE_ALLOWED);
}
} catch (Exception e) {
System.out.println(e);
e.printStackTrace();
}
}