应用安装大致有四中方式:
1,通过Adb进行安装,命令如下:
adb install xxx.apk
该命令是通过adb调用system/bin/pm脚本来生效的,命令对应的代码文件定义在commandline.cpp路径为system/core/adb/commandline.cpp
adb install命令在commandline中对应的方法是:
int adb_commandline(int argc, const char** argv) {
......
......
while (argc > 0) {
......
......
else if (!strcmp(argv[0], "install")) {
if (argc < 2) return syntax_error("install requires an argument");
if (_use_legacy_install()) {
return install_app_legacy(argc, argv);
}
return install_app(argc, argv);
}
......
......
}
接下来会去调用system/bin/pm这个脚本,脚本代码如下:
# Script to start "pm" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/pm.jar //设置环境变量
exec app_process $base/bin com.android.commands.pm.Pm "$@" //$@表示传给脚本的所有参数的列表
该脚本主要功能就是通过app_process来执行pm.jar 的main函数,多说一句,在android中java程序是通过app_process启动的,可以去了解一下app_process的用法,pm.jar的main函数就相当于java进程的入口函数,
接下来分析Pm.java:
public static void main(String[] args) {
int exitCode = 1;
try {
exitCode = new Pm().run(args);
} catch (Exception e) {
Log.e(TAG, "Error", e);
System.err.println("Error: " + e);
if (e instanceof RemoteException) {
System.err.println(PM_NOT_RUNNING_ERR);
}
}
System.exit(exitCode);
}
main方法中new了一个Pm()对象,然后调用它的run方法:
public int run(String[] args) throws RemoteException {
boolean validCommand = false;
if (args.length < 1) {
return showUsage();
}
mAm = IAccountManager.Stub.asInterface(ServiceManager.getService(Context.ACCOUNT_SERVICE));
mUm = IUserManager.Stub.asInterface(ServiceManager.getService(Context.USER_SERVICE));
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
......
......
if ("install".equals(op)) {
return runInstall(); //adb install命令对应此方法
}
......
......
}
runInstall又做了什么呢?
private int runInstall() throws RemoteException {
long startedTime = SystemClock.elapsedRealtime();
final InstallParams params = makeInstallParams();
final String inPath = nextArg();
if (params.sessionParams.sizeBytes == -1 && !STDIN_PATH.equals(inPath)) {
File file = new File(inPath);
if (file.isFile()) {
try {
ApkLite baseApk = PackageParser.parseApkLite(file, 0);
PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null,
null, null);
params.sessionParams.setSize(
PackageHelper.calculateInstalledSize(pkgLite, false,
params.sessionParams.abiOverride));
} catch (PackageParserException | IOException e) {
System.err.println("Error: Failed to parse APK file: " + e);
return 1;
}
} else {
System.err.println("Error: Can't open non-file: " + inPath);
return 1;
}
}
final int sessionId = doCreateSession(params.sessionParams,
params.installerPackageName, params.userId);
try {
if (inPath == null && params.sessionParams.sizeBytes == -1) {
System.err.println("Error: must either specify a package size or an APK file");
return 1;
}
if (doWriteSession(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
return 1;
}
Pair<String, Integer> status = doCommitSession(sessionId, false /*logSuccess*/);
if (status.second != PackageInstaller.STATUS_SUCCESS) {
return 1;
}
Log.i(TAG, "Package " + status.first + " installed in " + (SystemClock.elapsedRealtime()
- startedTime) + " ms");
System.out.println("Success");
return 0;
} finally {
try {
mInstaller.abandonSession(sessionId);
} catch (Exception ignore) {
}
}
}
调用了PackageParser轻量级解析了这个文件,得到了ApkLite对象