PackageInstaller 在 MIUI 优化模式下不起作用

Posted

技术标签:

【中文标题】PackageInstaller 在 MIUI 优化模式下不起作用【英文标题】:PackageInstaller does not work on MIUI optimization mode 【发布时间】:2021-08-15 11:51:34 【问题描述】:

我创建了一个用于安装 apk 文件的测试应用程序。 PackageInstaller 用于此。该应用程序运行良好。但是,对于 BroadcastReceiver 中的小米,我收到“INSTALL_FAILED_INTERNAL_ERROR: Permission Denied”错误。但是如果您启用开发者模式并禁用 MIUI 优化,那么应用程序也会成功安装包。我无法让我的应用程序的用户强制他们关闭优化模式,我该如何处理?在 MIUI 11 版本上测试

【问题讨论】:

【参考方案1】:

您可以检测用户是否启用了 MIUI 和优化模式,并显示一条消息,强制用户禁用它。使用这些实用方法(它是 Split APKs Installer 源代码的一部分):https://github.com/Aefyr/SAI/blob/master/app/src/main/java/com/aefyr/sai/utils/MiuiUtils.java

【讨论】:

【参考方案2】:

MIUI 20.2.20 似乎解决了这个不兼容问题。 solru's answer 对此进行检查。

如果 GitHub 链接停止工作:


    public static boolean isMiui() 
        return !TextUtils.isEmpty(Utils.getSystemProperty("ro.miui.ui.version.name"));
    

    public static String getMiuiVersionName() 
        String versionName = Utils.getSystemProperty("ro.miui.ui.version.name");
        return !TextUtils.isEmpty(versionName) ? versionName : "???";
    

    public static int getMiuiVersionCode() 
        try 
            return Integer.parseInt(Objects.requireNonNull(Utils.getSystemProperty("ro.miui.ui.version.code")));
         catch (Exception e) 
            return -1;
        
    

    public static String getActualMiuiVersion() 
        return Build.VERSION.INCREMENTAL;
    

    private static int[] parseVersionIntoParts(String version) 
        try 
            String[] versionParts = version.split("\\.");
            int[] intVersionParts = new int[versionParts.length];

            for (int i = 0; i < versionParts.length; i++)
                intVersionParts[i] = Integer.parseInt(versionParts[i]);

            return intVersionParts;
         catch (Exception e) 
            return new int[]-1;
        
    

    /**
     * @return 0 if versions are equal, values less than 0 if ver1 is lower than ver2, value more than 0 if ver1 is higher than ver2
     */
    private static int compareVersions(String version1, String version2) 
        if (version1.equals(version2))
            return 0;

        int[] version1Parts = parseVersionIntoParts(version1);
        int[] version2Parts = parseVersionIntoParts(version2);

        for (int i = 0; i < version2Parts.length; i++) 
            if (i >= version1Parts.length)
                return -1;

            if (version1Parts[i] < version2Parts[i])
                return -1;

            if (version1Parts[i] > version2Parts[i])
                return 1;
        

        return 1;
    

    public static boolean isActualMiuiVersionAtLeast(String targetVer) 
        return compareVersions(getActualMiuiVersion(), targetVer) >= 0;
    

    @SuppressLint("PrivateApi")
    public static boolean isMiuiOptimizationDisabled() 
        if ("0".equals(Utils.getSystemProperty("persist.sys.miui_optimization")))
            return true;

        try 
            return (boolean) Class.forName("android.miui.AppOpsUtils")
                    .getDeclaredMethod("isXOptMode")
                    .invoke(null);
         catch (Exception e) 
            return false;
        
    

    public static boolean isFixedMiui() 
        return isActualMiuiVersionAtLeast("20.2.20") || isMiuiOptimizationDisabled();
    

您最终要查找的函数是isMiuiisMiuiFixed

【讨论】:

以上是关于PackageInstaller 在 MIUI 优化模式下不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Android Lollipop - PackageInstaller.Session commit()

Android PackageInstaller,更新后重新打开应用程序

[RK3568][Android11]PackageInstaller(应用安装)流程介绍

[RK3568][Android11]PackageInstaller(应用安装)流程介绍

Android O PackageInstaller 解析

安卓引擎安装路径怎样修改