APK安装原理
2019-12-30 本文已影响0人
瑜小贤
基于android 5.0
-
有界面的安装方式
PackageInstallerActivity.java
InstallAppProgress.java
-
无界面安装 adb_commandline
int adb_commandline(int argc, char** argv){
//...
if(!strcmp(argv[0], "install")){
if(argc < 2) return usage();
//调用install_app函数进行处理
return install_app(ttype, serial, argc, argv);
}
}
int install_app(transport_type transport, char* serial, int argc, char** argv){
static const char *const DATA_DEST = "/data/local/tmp/%s";
static const char *const SD_DEST = "/sdcard/tmp/%s"
const char* where = DATA_DEST;
//...
int err = do_sync_push(apk_file, apk_dest, 0 /*no show progress*/);//将apk push到目标目录 进行解析安装
//...
pm_command(transport, serial, argc, argv);
//...
}
static int pm_command(transport_type transport, char* serial, int argc, char** argv){
char buf[4096];
snpintf(buf, sizeof(buf), "shell:pm"); //指向一个pm脚本文件
//...
send_shellcommand(transport, serial, buf);
return 0;
}
frameworks/base/cmds/pm/pm
base=/system
export CLASSPATH=$base/framework/pm.jar
exec app_process $base/bin com.android.commands.pm.P "$@"
frameworks/base/cmds/pm 下的工程源码,生成了上文的pm.jar,而工程源码中的唯一java文件是 Pm.java
public final class Pm{
//...
IPackageManager mPm;
IPackageInstaller mInstaller;
IUserManager mUm;
//...
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_RUNING_ERR);
}
}
System.exit(exitCode);
}
public int run(String[] args) throws IOException, RemoteException{
//...
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
//...
if("install".equals(op)){
return runInstall();
}
//...
}
private int runInstall(){
//...
try{
VerificationParams verificationParams = new VerificationParams(verificationURI,
originatingURI, referrerURI, VerificationParams.NO_UID, null);
mPm.installPackageAsUser(apkFilePath, obs.getBinder(), installFlags,
installerPackageName, verificationParams, abi, userId); //从Pm.java到PackageManagerService中
//...
}catch(RemoteException e){
//...
}
//...
}
//...
}
PackageManagerService.java
public class PackageManagerService extends IPackageManager.Stub{
//...
/**
* bind机制服务端
*
* @param originPath 要安装apk的路径
* @param observer 监听apk安装的结果信息
* @param installFlags 安装的相关参数
* @param installerPackageName 安装的包名
* @param userId userId
**/
@Override
public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, int userId){
//...
//组装消息,发送handler
final Message msg = mHandler.obtainMessage(INIT_COPY);
//...
mHandler.sendMessage(msg);
}
class PackageHandler extends Handler {
//...
void doHandleMessage(Message msg){
switch(msg.what){
case INIT_COPY:{
//...
mHadnler.sendEmptyMessage(MCS_BOUND);
//...
break;
}
case MCS_BOUND:{
//...
if(params.startCopy()){
//...
}
//...
break;
}
}
}
private abstract class HandlerParams {
private static final int MAX_RETRIES = 4;
//...
final boolean startCopy(){
boolean res;
try{
if(++mRetries > MAX_RETRIES){ //默认尝试安装4次
mHandler.sendEmptyMessage(MCS_GIVE_UP);
handleServiceError();
return false;
}else{
handleStartCopy();
res = true;
}
}catch(RemoteException e){
mHandler.sendEmptyMessage(MCS_RECONNECT);
res = false;
}
handleReturnCode();
return res;
}
//...
abstract void handleReturnCode();
}
//...
}
无界面安装
Apk安装的原理