Android obtains the method of judging whether there is floating window authority

  • 2021-09-24 23:41:24
  • OfStack

Nowadays, many applications will use floating windows, and many domestic rom have added floating window permissions to control, so you need to judge whether there is floating window permissions, and then do corresponding operations.

Android has its own rights management, but it is hidden. Look at android source code in android. app has an AppOpsManager class.

Class description is as follows:


/**
 * API for interacting with "application operation" tracking.
 *
 * <p>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}.</p>
 */

The above explanation is only useful for system application, and rom vendors should use this AppOps mechanism to open some permission control.

What should we do if we have the authority? You can only judge by reflection.

The checkOp method of AppOpsManager, that is, the method that detects whether there is a certain permission, has these return values, which are allowed, ignored, error and default:


/**
 * 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
 * <em>silently fail</em> (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;

Only MODE_ALLOWED is determined to have permission.

The checkOp method in the class is as follows, and the three parameters are the operation id, uid and the package name:


/**
 * Do a quick check for whether an application might be able to perform an operation.
 * This is <em>not</em> 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) {
 }
 return MODE_IGNORED;
}

Operating id, that is, op, can find static value definitions in this class. There are 62 permissions in android23, and what we need is OP_SYSTEM_ALERT_WINDOW=24

Knowing this, we can write our method with reflection:


 /**
  *  Judge   Is Floating Window Permission Open 
  *
  * @param context
  * @return true  Allow  false Prohibit 
  */
 public static boolean getAppOps(Context context) {
  try {
   Object object = context.getSystemService("appops");
   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] = Integer.valueOf(24);
   arrayOfObject1[1] = Integer.valueOf(Binder.getCallingUid());
   arrayOfObject1[2] = context.getPackageName();
   int m = ((Integer) method.invoke(object, arrayOfObject1)).intValue();
   return m == AppOpsManager.MODE_ALLOWED;
  } catch (Exception ex) {
 
  }
  return false;
 }

Testing is possible on most models of Meizu Huawei Xiaomi, but this method cannot be guaranteed to be correct. Some models will return an error, that is, MODE_ERRORED, that is, the permission value cannot be obtained, so this method returns false, but in fact the floating window can be used.


Related articles: