Android安装过程会区分为预置应用和三方应用,预置应用在首次开机过程中便会扫描安装,而三方应用则由用户使用过程中来完成安装。
安装的方式主要分为以下几种:
- 安装预置应用,这部分在首次开机完成;
- 使用ADB命令或者Shell命令来完成,其过程相同,ADB会增加一层ADB调用;
- 通过应用商店或者在其他应用内下载安装;
- 在文件管理中或者浏览器中点击APK文件通过PackageInstaller包进行安装;
PackageManagerService内拷贝
所有的安装都离不开包管理器服务—PackageManagerService(PMS),除去预置应用安装属于系统行为,其余的安装过程都会用到PMS的公共对外接口installStage,并且还都会有拷贝的过程,将原始的应用包拷贝到/data/app/属于应用独自的文件目录,然后统一命名为base.apk。本文主要介绍应用安装过程中拷贝的方式,参照Android源码简要介绍一下对应的拷贝流程。
首先看一下PMS类中对应的拷贝过程,此过程是在doCopyApk方法中完成的,如果前期没有完成拷贝则会在此处完成,完成拷贝之后就开始真正的扫描、解析和安装了。
private int doCopyApk() {
//判断是否已经处于staged状态,处于该状态则跳过此次的拷贝;
//此处的判断也是根据原本的session是否有stageDir相关联;
if (origin.staged) {
if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy");
codeFile = origin.file;
resourceFile = origin.file;
return PackageManager.INSTALL_SUCCEEDED;
}
...
//调用拷贝方法
int ret = PackageManagerServiceUtils.copyPackage(
origin.file.getAbsolutePath(), codeFile);
if (ret != PackageManager.INSTALL_SUCCEEDED) {
Slog.e(TAG, "Failed to copy package");
return ret;
}
...
return ret;
}
拷贝过程在PackageManagerServiceUtils类中完成,这里不再列出详细的调用关系,只给出对应的关键code。从中可以看到通过FileUtils类的copy方法,将source对应文件描述符和destination对应的文件描述符给进去,进行stream传输从而完成拷贝过程,此时会有/data/app/“package”/base.apk存在,从而完成一次拷贝。
final File targetFile = new File(targetDir, targetName);//targetName是base.apk
final FileDescriptor targetFd = Os.open(targetFile.getAbsolutePath(),
O_RDWR | O_CREAT, 0644);
Os.chmod(targetFile.getAbsolutePath(), 0644