How to open Draw Overlay permission popup in MIUI?
Asked Answered
U

3

19

I want to open this permission popup in MIUI. I have tried this code, but this will not open permission manager popup for a particular app.

public static Intent toPermissionManager(Context context, String packageName) {
    Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
    String version = getVersionName();
    if (MIUI_V5.equals(version)) {
        PackageInfo pInfo;
        try {
            pInfo = context.getPackageManager().getPackageInfo(packageName, 0);
        } catch (PackageManager.NameNotFoundException ignored) {
            return null;
        }
        intent.setClassName("com.android.settings", "com.miui.securitycenter.permission.AppPermissionsEditor");
        intent.putExtra("extra_package_uid", pInfo.applicationInfo.uid);
    } else { // MIUI_V6 and above
        final String PKG_SECURITY_CENTER = "com.miui.securitycenter";
        try {
            context.getPackageManager().getPackageInfo(PKG_SECURITY_CENTER, PackageManager.GET_ACTIVITIES);
        } catch (PackageManager.NameNotFoundException ignored) {
            return null;
        }
        intent.setClassName(PKG_SECURITY_CENTER, "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
        intent.putExtra("extra_pkgname", packageName);
    }
    return intent;
}
Umber answered 21/3, 2016 at 4:50 Comment(7)
Please add a follow up here if you have found a solution.Projector
sorry still i have no solutionUmber
did you find a solution ?Potentilla
still i have no solutionUmber
have find solution?Lintel
no i can't find solution for this issueUmber
@OmerKarakose , @ Mohammad Rizky Kurniawan,@ SanVed I have uploaded answer for this please check it .Hope It will solve your problemUmber
U
18

Call This method directly onDisplayPopupPermission() where you want to use this permission.

To check permission is granted or not I have added one more answer above, please check.

private void onDisplayPopupPermission() {
    if (!isMIUI()) {
        return;
    }
    try {
        // MIUI 8
        Intent localIntent = new Intent("miui.intent.action.APP_PERM_EDITOR");
        localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
        localIntent.putExtra("extra_pkgname", getPackageName());
        startActivity(localIntent);
        return;
    } catch (Exception ignore) {
    }
    try {
        // MIUI 5/6/7
        Intent localIntent = new Intent("miui.intent.action.APP_PERM_EDITOR");
        localIntent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
        localIntent.putExtra("extra_pkgname", getPackageName());
        startActivity(localIntent);
        return;
    } catch (Exception ignore) {
    }
    // Otherwise jump to application details
    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
    Uri uri = Uri.fromParts("package", getPackageName(), null);
    intent.setData(uri);
    startActivity(intent);
 }


private static boolean isMIUI() {
    String device = Build.MANUFACTURER;
    if (device.equals("Xiaomi")) {
        try {
            Properties prop = new Properties();
            prop.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop")));
            return prop.getProperty("ro.miui.ui.version.code", null) != null
                    || prop.getProperty("ro.miui.ui.version.name", null) != null
                    || prop.getProperty("ro.miui.internal.storage", null) != null;
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    return false;
}

It will redirect to display popup window permission screen you can manually change it to on off

Umber answered 20/7, 2017 at 6:33 Comment(8)
Is there a way to know if the user has selected Accept or Deny?Clamant
@SrikarReddy do you found the solution for knowing if accept or deny was selected?Fruiter
@SrikarReddy It's late to update but I have uploaded the answer to check permission granted or Not you can try for it.Umber
@Fruiter You can try for the solution that i have uploadedUmber
How did you find this solution?Gynecologist
On Android O, exception is thrown: java.io.FileNotFoundException: /system/build.prop (Permission denied)Dissogeny
@Dissogeny use getSystemProperty(String propName) from https://mcmap.net/q/667189/-how-to-start-activity-from-background-in-android-10-android-q-miui-11/4232793Seema
its not working in MIUI 11Neurath
P
6

This below code is working for me. You need these two class MIUIUtils.java and BuildProperties.java

MIUIUtils.java

public class MIUIUtils {
    private static final String MIUI_V5 = "V5";
    private static final String MIUI_V6 = "V6";

    private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code";
    private static final String KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name";
    private static final String KEY_MIUI_INTERNAL_STORAGE = "ro.miui.internal.storage";

    public static boolean isMIUI() {
        try {
            final BuildProperties prop = BuildProperties.newInstance();
            return prop.getProperty(KEY_MIUI_VERSION_CODE, null) != null
                || prop.getProperty(KEY_MIUI_VERSION_NAME, null) != null
                || prop.getProperty(KEY_MIUI_INTERNAL_STORAGE, null) != null;
        } catch (IOException e) {
            return false;
        }
    }

    public static boolean isMIUIV5() {
        return getVersionName().equals(MIUI_V5);
    }

    public static boolean isMIUIV6() {
        return getVersionName().equals(MIUI_V6);
    }

    public static String getVersionName() {
        try {
            final BuildProperties prop = BuildProperties.newInstance();
            return prop.getProperty(KEY_MIUI_VERSION_NAME);
        } catch (IOException e) {
            return "";
        }
    }

    public static boolean isFloatWindowOptionAllowed(Context context) {
        AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        Class localClass = manager.getClass();
        Class[] arrayOfClass = new Class[3];
        arrayOfClass[0] = Integer.TYPE;
        arrayOfClass[1] = Integer.TYPE;
        arrayOfClass[2] = String.class;
        try {
            Method method = localClass.getMethod("checkOp", arrayOfClass);
            if (method == null) {
                return false;
            }
            Object[] arrayOfObjects = new Object[3];
            arrayOfObjects[0] = Integer.valueOf(24);
            arrayOfObjects[1] = Integer.valueOf(Binder.getCallingUid());
            arrayOfObjects[2] = context.getPackageName();
            int m = ((Integer) method.invoke((Object) manager, arrayOfObjects)).intValue();
            return m == AppOpsManager.MODE_ALLOWED;
        } catch (Exception e) {
            return false;
        }
    }

    public static Intent toPermissionManager(Context context, String packageName) {
        Intent intent = new Intent("miui.intent.action.APP_PERM_EDITOR");
        String version = getVersionName();
        if (MIUI_V5.equals(version)) {
            PackageInfo pInfo;
            try {
                pInfo = context.getPackageManager().getPackageInfo(packageName, 0);
            } catch (PackageManager.NameNotFoundException ignored) {
                return null;
            }
            intent.setClassName("com.android.settings", "com.miui.securitycenter.permission.AppPermissionsEditor");
            intent.putExtra("extra_package_uid", pInfo.applicationInfo.uid);
        } else { // MIUI_V6 and above
            final String PKG_SECURITY_CENTER = "com.miui.securitycenter";
            try {
           context.getPackageManager().getPackageInfo(PKG_SECURITY_CENTER, PackageManager.GET_ACTIVITIES);
            } catch (PackageManager.NameNotFoundException ignored) {
                return null;
            }
            intent.setClassName(PKG_SECURITY_CENTER, "com.miui.permcenter.permissions.AppPermissionsEditorActivity");
            intent.putExtra("extra_pkgname", packageName);
        }
        return intent;
    }


    public static Intent toFloatWindowPermission(Context context, String packageName) {
        Uri packageUri = Uri.parse("package:" + packageName);
        Intent detailsIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageUri);
        detailsIntent.addCategory(Intent.CATEGORY_DEFAULT);
        if (isMIUIV5()) {
            return detailsIntent;
        } else {
            Intent permIntent = toPermissionManager(context, packageName);
            return permIntent == null ? detailsIntent : permIntent;
        }
    }
}

BuildProperties.java

public class BuildProperties {

    private final Properties properties;

    private BuildProperties() throws IOException {
        InputStream in = new FileInputStream(new File(Environment.getRootDirectory(), "build.prop"));
        properties = new Properties();
        properties.load(in);
        in.close();
    }

    public static BuildProperties newInstance() throws IOException {
        return new BuildProperties();
    }

    public boolean containsKey(final Object key) {
        return properties.containsKey(key);
    }

    public boolean containsValue(final Object value) {
        return properties.containsValue(value);
    }

    public Set<Map.Entry<Object, Object>> entrySet() {
        return properties.entrySet();
    }

    public String getProperty(final String name) {
        return properties.getProperty(name);
    }

    public String getProperty(final String name, final String defaultValue) {
        return properties.getProperty(name, defaultValue);
    }

    public boolean isEmpty() {
        return properties.isEmpty();
    }

    public Enumeration<Object> keys() {
        return properties.keys();
    }

    public Set<Object> keySet() {
        return properties.keySet();
    }

    public int size() {
        return properties.size();
    }

    public Collection<Object> values() {
        return properties.values();
    }
}

Call in your code like this:

     if (Build.VERSION.SDK_INT >= 19 && MIUIUtils.isMIUI() && !MIUIUtils.isFloatWindowOptionAllowed(context)) {
            Log.i(TAG, "MIUI DEVICE: Screen Overlay Not allowed");
            startActivityForResult(MIUIUtils.toFloatWindowPermission(context, getPackageName()), REQUEST_OVERLAY_PERMISSION);
        } else if (Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(context)) {
            Log.i(TAG, "SDK_INT > 23: Screen Overlay Not allowed");
            startActivityForResult(new Intent(
                            "android.settings.action.MANAGE_OVERLAY_PERMISSION", 
                            Uri.parse("package:" +getPackageName()))
                    , REQUEST_OVERLAY_PERMISSION
            );
        } else {
            Log.i(TAG, "SKK_INT < 19 or Have overlay permission");

        }
Pitchblende answered 9/12, 2016 at 13:21 Comment(2)
It opens only app info page in MIUI8 on Android 5.1Bornie
On Android O, exception is thrown: java.io.FileNotFoundException: /system/build.prop (Permission denied)Dissogeny
U
1

To check if Display popup window permission is Granted or not, using onDisplayPopupPermission() this method is from my above answer.

I am using canDrawOverlayViews and reflection to check permission is granted or not this may be removed/changed in the latest releases.

This solution I have tried up to MIUI8 it's working, not sure about the latest updates. Please give an update on the comment so others can have updates.

1.Step

if (!canDrawOverlayViews() && isXiaomi()) {
        //permission not granted
        Log.e("canDrawOverlayViews", "-No-");
       onDisplayPopupPermission(); 
        //write above answered permission code for MIUI here
    }else {

    }

2.Step Check if permission granted or not

public boolean canDrawOverlayViews() {
    if (Build.VERSION.SDK_INT < 21) {
        return true;
    }
    Context con = this;
    try {
        return Settings.canDrawOverlays(con);
    } catch (NoSuchMethodError e) {
        return canDrawOverlaysUsingReflection(con);
    }
}

public static boolean isXiaomi() {
    return "xiaomi".equalsIgnoreCase(Build.MANUFACTURER);
}

canDrawOverlaysUsingReflection() I have found this solution here here translate this page

public static boolean canDrawOverlaysUsingReflection(Context context) {

try {

    AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
    Class clazz = AppOpsManager.class;
    Method dispatchMethod = clazz.getMethod("checkOp", new Class[] { int.class, int.class, String.class });
    //AppOpsManager.OP_SYSTEM_ALERT_WINDOW = 24
    int mode = (Integer) dispatchMethod.invoke(manager, new Object[] { 24, Binder.getCallingUid(), context.getApplicationContext().getPackageName() });

    return AppOpsManager.MODE_ALLOWED == mode;

} catch (Exception e) {  return false;  }

}

Umber answered 8/10, 2018 at 11:33 Comment(6)
What is canDrawOverlaysUsingReflection() method?Alvin
@javaDroid please check to update Its been long time that I have worked on it please make sure its working and update on itUmber
I have tried this solution and it does not work for MIUI 10 and above, not tried on < 10Latoyia
@GastónSaillén This solution I have tried up to MIUI8 it's working, for MIUI > 8 Please update your answerUmber
I checked, but Settings.canDrawOverlays(con); in canDrawOverlayViews() method always return false.Alvin
has anyone found the solution to this issue?Griner

© 2022 - 2024 — McMap. All rights reserved.