当前位置:   article > 正文

【Android 插件化】VirtualApp 源码分析 ( 安装应用源码分析 | HomePresenterImpl 添加应用 | AppRepository.addVirtualApp )_virtualapp 添加不了

virtualapp 添加不了





一、安装应用源码分析




1、HomePresenterImpl 添加应用


mPresenter.addApp(info); 实际上调用的是 io.virtualapp.home.HomePresenterImpl 类的 addApp() 方法 , 安装应用 , 传入 AppInfoLite info 参数 , 封装如下值 :

packageName : com.example.filepath , path : /storage/emulated/0/./app-debug.apk , fastOpen : false
  • 1

通过 VirtualCore.get().getInstalledAppInfo(info.packageName, 0); 代码 , 获取该应用是否安装过 ,

  • 如果应用安装过 , 则该安装操作是克隆应用 ;
  • 如果应用没有安装过 , 则该安装操作是从 SD 卡安装 ; 如果是从 SD 卡安装 , 则调用 InstallResult res = mRepo.addVirtualApp(info); 进行安装操作 ;
class HomePresenterImpl implements HomeContract.HomePresenter {
    @Override
    public void addApp(AppInfoLite info) {
        class AddResult {
            private PackageAppData appData;
            private int userId;
            private boolean justEnableHidden;
        }
        AddResult addResult = new AddResult();
        VUiKit.defer().when(() -> {
            // 获取安装的应用信息 , 该应用之前是否安装过
            // 这里应该是判断 克隆应用 / SD 卡 APK 文件
            InstalledAppInfo installedAppInfo = VirtualCore.get().getInstalledAppInfo(info.packageName, 0);

            // 是否隐藏 , 如果之前有安装过 , 即这是第二次安装 , 则需要隐藏 , 命中 if (addResult.justEnableHidden) 分支
            addResult.justEnableHidden = installedAppInfo != null;
            if (addResult.justEnableHidden) { // 克隆应用
                int[] userIds = installedAppInfo.getInstalledUsers();
                int nextUserId = userIds.length;
                /*
                  Input : userIds = {0, 1, 3}
                  Output: nextUserId = 2
                 */
                for (int i = 0; i < userIds.length; i++) {
                    if (userIds[i] != i) {
                        nextUserId = i;
                        break;
                    }
                }
                addResult.userId = nextUserId;

                if (VUserManager.get().getUserInfo(nextUserId) == null) {
                    // user not exist, create it automatically.
                    String nextUserName = "Space " + (nextUserId + 1);
                    VUserInfo newUserInfo = VUserManager.get().createUser(nextUserName, VUserInfo.FLAG_ADMIN);
                    if (newUserInfo == null) {
                        throw new IllegalStateException();
                    }
                }
                boolean success = VirtualCore.get().installPackageAsUser(nextUserId, info.packageName);
                if (!success) {
                    throw new IllegalStateException();
                }
            } else { // SD 卡 APK 文件 , 如果是第一次安装 , 则命中该分支
                InstallResult res = mRepo.addVirtualApp(info);
                if (!res.isSuccess) {
                    throw new IllegalStateException();
                }
            }
        }).then((res) -> {
            addResult.appData = PackageAppDataStorage.get().acquire(info.packageName);
        }).done(res -> {
            boolean multipleVersion = addResult.justEnableHidden && addResult.userId != 0;
            if (!multipleVersion) {
                PackageAppData data = addResult.appData;
                data.isLoading = true;
                mView.addAppToLauncher(data);
                handleOptApp(data, info.packageName, true);
            } else {
                MultiplePackageAppData data = new MultiplePackageAppData(addResult.appData, addResult.userId);
                data.isLoading = true;
                mView.addAppToLauncher(data);
                handleOptApp(data, info.packageName, false);
            }
        });
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

2、AppRepository.addVirtualApp 安装 SD 卡 APK 应用


InstallResult res = mRepo.addVirtualApp(info); 方法调用的是 AppRepository 类的 addVirtualApp 方法 ;

public class AppRepository implements AppDataSource {
    @Override
    public InstallResult addVirtualApp(AppInfoLite info) {
    	// int COMPARE_VERSION = 0X01 << 3;
    	// int SKIP_DEX_OPT = 0x01 << 6;
        int flags = InstallStrategy.COMPARE_VERSION | InstallStrategy.SKIP_DEX_OPT;
        // fastOpen 值是 false , 该分支没有命中
        if (info.fastOpen) {
            flags |= InstallStrategy.DEPEND_SYSTEM_IF_EXIST;
        }
        // 安装 SD 卡中的 APK 文件
        return VirtualCore.get().installPackage(info.path, flags);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

原始数据 AppInfoLite info 如下 :

I/HSL: packageName : com.example.filepath , path : /storage/emulated/0/./app-debug.apk , fastOpen : false
  • 1

此处找到了可以直接调用的 API 方法 , 调用 VirtualCore.get().installPackage( SD卡绝对路径 , 0X01 << 3 | 0x01 << 6); API 安装某个路径中中的 APK 文件 ;


flags 值参考 : 0X01 << 3 | 0x01 << 6 ;

    	// int COMPARE_VERSION = 0X01 << 3;
    	// int SKIP_DEX_OPT = 0x01 << 6;
        int flags = InstallStrategy.COMPARE_VERSION | InstallStrategy.SKIP_DEX_OPT;
  • 1
  • 2
  • 3

InstallStrategy 常量类定义 :

public interface InstallStrategy {
	int TERMINATE_IF_EXIST = 0x01 << 1;
	int UPDATE_IF_EXIST = 0x01 << 2;
	int COMPARE_VERSION = 0X01 << 3;
	int IGNORE_NEW_VERSION = 0x01 << 4;
	int DEPEND_SYSTEM_IF_EXIST = 0x01 << 5;
	int SKIP_DEX_OPT = 0x01 << 6;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/178987
推荐阅读
相关标签
  

闽ICP备14008679号