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





一、安装应用源码分析




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

通过 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);
            }
        });
    }
}

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

原始数据 AppInfoLite info 如下 :

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

此处找到了可以直接调用的 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;

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;
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值