前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Android 插件化】VirtualApp 源码分析 ( 安装应用源码分析 | HomePresenterImpl 添加应用 | AppRepository.addVirtualApp )

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

作者头像
韩曙亮
发布2023-03-29 19:25:23
3250
发布2023-03-29 19:25:23
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

一、安装应用源码分析


1、HomePresenterImpl 添加应用

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

代码语言:javascript
复制
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); 进行安装操作 ;
代码语言:javascript
复制
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 方法 ;

代码语言:javascript
复制
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 如下 :

代码语言:javascript
复制
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 ;

代码语言:javascript
复制
    	// int COMPARE_VERSION = 0X01 << 3;
    	// int SKIP_DEX_OPT = 0x01 << 6;
        int flags = InstallStrategy.COMPARE_VERSION | InstallStrategy.SKIP_DEX_OPT;

InstallStrategy 常量类定义 :

代码语言:javascript
复制
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;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-10-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、安装应用源码分析
    • 1、HomePresenterImpl 添加应用
      • 2、AppRepository.addVirtualApp 安装 SD 卡 APK 应用
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档