如何在 MIUI 中打开 Draw Overlay 权限弹出窗口?

Posted

技术标签:

【中文标题】如何在 MIUI 中打开 Draw Overlay 权限弹出窗口?【英文标题】:How to open Draw Overlay permission popup in MIUI? 【发布时间】:2016-07-07 12:11:28 【问题描述】:

我想在MIUI中打开这个权限弹窗。我已经尝试过此代码,但这不会为特定应用打开权限管理器弹出窗口。

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;

【问题讨论】:

如果您找到了解决方案,请在此处添加跟进。 抱歉我还是没有解决办法 你找到解决办法了吗? 我还是没有办法 找到解决方案了吗? 【参考方案1】:

在你想使用这个permission的地方直接调用这个方法onDisplayPopupPermission()

查看权限是grantednot上面我又加了一个答案,请查看。

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;

它将重定向到显示弹出窗口权限屏幕,您可以手动将其更改为开启关闭

【讨论】:

有没有办法知道用户选择了接受还是拒绝? @SrikarReddy 您是否找到了知道是否选择了接受或拒绝的解决方案? @SrikarReddy 更新比较晚,但是我已经上传了检查权限的答案grantedNot 你可以试试。 @Gautam 你可以试试我上传的解决方案 您是如何找到这个解决方案的?【参考方案2】:

下面的代码对我有用。你需要这两个类 MIUIUtils.javaBuildProperties.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();
    

像这样调用你的代码:

     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");

        

【讨论】:

它只在Android 5.1的MIUI8中打开应用信息页面 在 Android O 上,抛出异常:java.io.FileNotFoundException: /system/build.prop (Permission denied)【参考方案3】:

要检查是否授予Display popup window 权限,使用onDisplayPopupPermission() 这个方法来自我上面的答案。

我正在使用canDrawOverlayViewsreflection 来检查permission is granted 是否是removed/changed in the latest releases

这个解决方案我已经尝试了MIUI8 它正在工作,不确定 最新更新。请在评论中提供更新,以便其他人可以更新。

1.步骤

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

    

2.步骤 检查是否授予权限

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()我在这里找到了这个解决方案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;  

【讨论】:

canDrawOverlaysUsingReflection() 方法是什么? @javaDroid 请检查更新我已经工作很长时间了,请确保它的工作和更新 我已经尝试过这个解决方案,它不适用于 MIUI 10 及更高版本,未在 上尝试过 @GastónSaillén 这个解决方案我已经尝试了MIUI8 它正在工作,对于 MIUI &gt; 8 请更新你的答案 我检查过了,但是Settings.canDrawOverlays(con);canDrawOverlayViews() 方法中总是返回false。

以上是关于如何在 MIUI 中打开 Draw Overlay 权限弹出窗口?的主要内容,如果未能解决你的问题,请参考以下文章

为特定应用打开 miui 省电模式

(最简单)MIUI7系统的usb调试模式在哪里打开的流程

红米k30pro怎么升级miui14

如何取消miui系统bug报告功能?

小米手机怎么打开root权限管理

miui12.5怎么root