3 807 2017-1-16 20:10 发表
之前提到有没有方法干预系统对应用安装位置的判断,前几天尝试了一下发现可行。经过下述修改后,所有的应用均自动安装到手机内部存储,不再失败,彻底绕过了BUG。

具体教程(对带odex的apk修改)参照此处的教程(XDA)。注意:修改系统文件有风险,操作需谨慎,且操作系统分区需要root权限。

需要的工具有:
(1) adb(这个可自行查找,只要能用的版本就行)
(2) smali和baksmali(最新版可以在此处找到,为方便起见,下载完后将其对应重命名为smali.jar和baksmali.jar)
(3) zipalign(windows版在教程的附件中有,也可参照这里

1、用adb提取系统的/system/priv-app/DefaultContainerService.apk和DefaultContainerService.odex到工作目录下。
adb pull /system/priv-app/DefaultContainerService.apk
adb pull /system/priv-app/DefaultContainerService.odex

同时,将/system/framework文件夹一并提取出来。
adb pull /system/framework

2、在工作目录中用baksmali将odex反汇编,结果位于新生成的out文件夹中。
java -jar baksmali.jar -d framework -x DefaultContainerService.odex

3、打开新生成的out文件夹,继续打开com\android\defcontainer,找到DefaultContainerService.smali,用文本编辑器打开,查找如下部分:
.method private recommendAppInstallLocation(ILjava/lang/String;IJ)I
    .locals 14
    .param p1, "installLocation"    # I
    .param p2, "archiveFilePath"    # Ljava/lang/String;
    .param p3, "flags"    # I
    .param p4, "threshold"    # J

    .prologue
    .line 688
    const/4 v3, 0x0

    .line 690
    .local v3, "checkBoth":Z
    and-int/lit8 v11, p3, 0x1

4、在刚才找到的地方插入下面蓝色标记的一行,最终效果如下:
.method private recommendAppInstallLocation(ILjava/lang/String;IJ)I
    .locals 14
    .param p1, "installLocation"    # I
    .param p2, "archiveFilePath"    # Ljava/lang/String;
    .param p3, "flags"    # I
    .param p4, "threshold"    # J

    .prologue
    .line 688
    const/4 v3, 0x0

    or-int/lit8 p3, p3, 0x10

    .line 690
    .local v3, "checkBoth":Z
    and-int/lit8 v11, p3, 0x1

5、完成后回到工作根目录,将修改的内容重新汇编成classes.dex。
java -jar smali.jar -o classes.dex out

6、用压缩软件打开DefaultContainerService.apk将新生成的classes.dex拖入其中,替换原有的classes.dex。之后使用zipalign工具将处理后的apk文件对齐。
zipalign -v 4 DefaultContainerService.apk DefaultContainerService_new.apk

7、将最终生成的DefaultContainerService_new.apk推回手机并将名称改回为DefaultContainerService.apk,用可以访问系统分区的文件管理器(如Root Explorer)将原来位于/system/priv-app的DefaultContainerService.apk覆盖,注意要将原来的DefaultContainerService.odex删除掉,以及将文件的权限设置为rw-r--r--(0644),和其他文件一样,否则系统可能无法启动
8、完成后重启手机,现在可以尝试下安装之前安装不了的应用,如果没有问题的话这些程序应该可以正常安装了。这个修改对直接安装APK和Play Store都有效。

这只是一个临时的修正手段,动手能力差的尽量不要冒险尝试。

本修正的原理在于在系统判断程序安装位置的时候,事先人为将“强制要求安装到内部存储”的标志位置上。这个标志位将使系统无视应用的设置强行将应用安装到手机存储。这样修改后,不管应用是什么设置,系统都安装到内部存储。由于安装到内部存储的过程中不创建asec容器(W3D无法正确创建asec容器,这是为什么之前部分应用安装失败的原因),安装因此能够正常进行并成功结束。

之所以在这里发布是希望以后官方能够发布正式的修正版,这个问题自W3D正式发布后就有,非常影响使用,且一直就没解决。
这个修改对应到Java差不多就是下面蓝色的那一行。
com/android/defcontainer/DefaultContainerService.java里面:
private int recommendAppInstallLocation(int installLocation, String archiveFilePath, int flags,
long threshold) {
        int prefer;
        boolean checkBoth = false;

        flags |= PackageManager.INSTALL_INTERNAL;

        final boolean isForwardLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;

        check_inner : {
            /*
             * Explicit install flags should override the manifest settings.
             */
            if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
                prefer = PREFER_INTERNAL;
                break check_inner;
            } else if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
                prefer = PREFER_EXTERNAL;
                break check_inner;
            }

L.S.S.
举报 使用道具
| 引用
3 个关于 W3D SD卡不能安装应用的问题的修正方法 的回复 最后回复于 2017-5-6 02:29
发表于 2017-1-17 11:35 | 显示全部楼层
楼主技术帝,支持
举报 使用道具
发表于 2017-1-20 19:11 来自手机 | 显示全部楼层
坐小凳学习
举报 使用道具
发表于 2017-5-6 02:29 来自手机 | 显示全部楼层
试了可以要装应用了,谢谢分享~
举报 使用道具
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

请选择 进入手机版 | 继续访问电脑版
快速回复 返回顶部 返回列表