文章目录
一、安装应用源码分析
1、HomePresenterImpl 添加应用
2、AppRepository.addVirtualApp 安装 SD 卡 APK 应用
一、安装应用源码分析
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); } }); } }
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; }