小米手机6.0系统以上WRITE_SETTINGS和SYSTEM_ALERT_WINDOW权限回调结果总是返回False的解决方法

重点关注AppOpsManager这个类。要想知道这个类是干嘛的,直接去谷歌官方开发者文档中去了解。
在AppOpsManager这个类中,可以看到


Permissions.png

悬浮窗和修改系统设置的权限码是24和25。并且这个类的变量,方法都是隐藏的。
接下来,我们需要调用checkOp方法来返回真正的权限回调结果。

   /**
     * Do a quick check for whether an application might be able to perform an operation.
     * This is not a security check; you must use {@link #noteOp(int, int, String)}
     * or {@link #startOp(int, int, String)} for your actual security checks, which also
     * ensure that the given uid and package name are consistent.  This function can just be
     * used for a quick check to see if an operation has been disabled for the application,
     * as an early reject of some work.  This does not modify the time stamp or other data
     * about the operation.
     * @param op The operation to check.  One of the OP_* constants.
     * @param uid The user id of the application attempting to perform the operation.
     * @param packageName The name of the application attempting to perform the operation.
     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
     * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
     * causing the app to crash).
     * @throws SecurityException If the app has been configured to crash on this op.
     * @hide
     */
    public int checkOp(int op, int uid, String packageName) {
        try {
            int mode = mService.checkOperation(op, uid, packageName);
            if (mode == MODE_ERRORED) {
                throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
            }
            return mode;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

由于这个方法是隐藏的,所以需要用反射的方法来调用。也可以用这个库来进行调用 https://github.com/anggrayudi/android-hidden-api
这个库只要直接将原本的SDK替换成这个库的SDK就能够不用通过反射来调用隐藏方法。
反射调用checkOp的步骤:

 private static boolean isPermissionGranted(String permissionCode) {
        try {
            Object object = 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[] arrayOfObject = new Object[3];
            arrayOfObject[0] = Integer.valueOf(permissionCode);
            arrayOfObject[1] = Integer.valueOf(Binder.getCallingUid());
            arrayOfObject[2] = getPackageName();
            int m = ((Integer) method.invoke(object, arrayOfObject)).intValue();
            return m == AppOpsManager.MODE_ALLOWED;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

然后将悬浮窗和修改系统设置的权限码传进去就好。
最后返回的结果既是真正的权限回调的结果。

你可能感兴趣的:(小米手机6.0系统以上WRITE_SETTINGS和SYSTEM_ALERT_WINDOW权限回调结果总是返回False的解决方法)