一. APK的安装步骤
安装步骤一:把APK的信息通过IO流的形式写入到PackageInstaller.Session中
安装步骤二:调用PackageInstaller.Session的commit方法,把APK的信息交给PackageManagerService处理
安装步骤三:进行Apk的Copy操作,进行安装
二. 点击安装后到完成APK的拷贝流程如下:

点击一个未安装的apk后,会弹出安装界面,点击确定按钮后,会进入PacakageInstallerActivity.java的bindUI()中的mAlert点击事件,点击apk后,弹出的安装界面底部显示的是一个Dialog,主要由bindUi构成,上面有取消和安装两个按钮,点击安装之后调用startInstall()进行安装。bingUi方法的代码如下:
private void bindUi() {
mAlert.setIcon(mAppSnippet.icon);
mAlert.setTitle(mAppSnippet.label);
mAlert.setView(R.layout.install_content_view);
mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install),
(ignored, ignored2) -> {
if (mOk.isEnabled()) {
if (mSessionId != -1) {
mInstaller.setPermissionsResult(mSessionId, true);
finish();
} else {
// 进行APK的安装
startInstall();
}
}
}, null);
mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
(ignored, ignored2) -> {
// Cancel and finish
setResult(RESULT_CANCELED);
if (mSessionId != -1) {
// 如果mSessionId存在,执行setPermissionResult()完成取消安装
mInstaller.setPermissionsResult(mSessionId, false);
}
finish();
}, null);
setupAlert();
mOk = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
mOk.setEnabled(false);
if (!mOk.isInTouchMode()) {
mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).requestFocus();
}
}
startInstall方法组装了一个Intent,并跳转到 InstallInstalling 这个Activity,并关闭掉当前的PackageInstallerActivity。InstallInstalling主要用于向包管理器发送包的信息并处理包管理的回调。
private void startInstall() {
// Start subactivity to actually install the application
Intent newIntent = new Intent();
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
mPkgInfo.applicationInfo);
newIntent.setData(mPackageURI);
// 设置Intent中的class为InstallInstalling,用来进行Activity跳转
newIntent.setClass(this, InstallInstalling.class);
String installerPackageName = getIntent().getStringExtra(
Intent.EXTRA_INSTALLER_PACKAGE_NAME);
if (mOriginatingURI != null) {
newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
}
if (mReferrerURI != null) {
newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI);
}
if (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN) {
newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid);
}
if (installerPackageName != null) {
newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME,
installerPackageName);
}
if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
}
newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
if(localLOGV) Log.i(TAG, "downloaded app uri="+mPackageURI);
startActivity(newIntent);
finish();
}
InstallInstalling 的Activity启动后,进入onCreate方法
主要分为6步:
1. 如果savedInstanceState不为null,获取此前保存的mSessionId和mInstallId,其中mSessionId是安装包的会话Id,mInstallId是等待的安装事件Id
2. 根据mInstallId向InstallEventReceiver注册一个观察者,launchFinishBasedOnResult会接收到安装事件的回调,无论安装成功或者是安装失败都会关闭当前的Activity(InstallInstalling)。如果saveInstanceState为null,代码的逻辑也是类似的。
3. 创建SessionParams,它用来代表安装会话的参数,组装Params
4. 根据mPackageUri对包(APK)进行轻量级的解析,并将解析的参数赋值给SessionParams
5. 向InstallEventReceiver注册一个观察者返回一个新的mInstallId
6. PackageInstaller的createSession方法内部会通过IPackageInstallerService进行进程间通信,最终调用的是PackageInstallerService的createSession方法来创建并返回mSessionId
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ApplicationInfo appInfo = getIntent()
.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
mPackageURI = getIntent().getData();
if ("package".equals(mPackageURI.getScheme())) {
try {
getPackageManager().installExistingPackage(appInfo.packageName);
launchSuccess();
} catch (PackageManager.NameNotFoundException e) {
launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
} else {
// 根据mPackageURI创建一个对应的File
final File sourceFile = new File(mPackageURI.getPath());
PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
mAlert.setIcon(as.icon);
mAlert.setTitle(as.label);
mAlert.setView(R.layout.install_content_view);
mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel),
(ignored, ignored2) -> {
if (mInstallingTask != null) {
mInstallingTask.cancel(true);
}
if (mSessionId > 0) {
getPackageManager().getPackageInstaller().abandonSession(mSessionId);
mSessionId = 0;
}
setResult(RESULT_CANCELED);
finish();
}, null);
setupAlert();
requireViewById(R.id.installing).setVisibility(View.VISIBLE);
// 1. 如果savedInstanceState不为null,获取此前保存的mSessionId和mInstallId,
// 其中mSessionId是安装包的会话Id,mInstallId是等待安装的事件Id
if (savedInstanceState != null) {
mSessionId = savedInstanceState.getInt(SESSION_ID);
mInstallId = savedInstanceState.getInt(INSTALL_ID);
// Reregister for result; might instantly call back if result was delivered while
// activity was destroyed
try {
// 2. 根据mInstallId向InstallEventReceiver注册一个观察者,
// launchFinishBasedOnResult会接收到安装事件的回调,无论安装成功还是失败
// 都会关闭当前的Activity(InstallInstalling)。如果savedInstanceState为
// null,代码的逻辑也是类似的
InstallEventReceiver.addObserver(this, mInstallId,
this::launchFinishBasedOnResult);
} catch (EventResultPersister.OutOfIdsException e) {
// Does not happen
}
} else {
//3. 创建SessionParams,它用来代表安装会话的参数,组装params
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
params.setInstallAsInstantApp(false);
params.setReferrerUri(getIntent().getParcelableExtra(Intent.EXTRA_REFERRER));
params.setOriginatingUri(getIntent()
.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI));
params.setOriginatingUid(getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
UID_UNKNOWN));
params.setInstallerPackageName(getIntent().getStringExtra(
Intent.EXTRA_INSTALLER_PACKAGE_NAME));
params.setInstallReason(PackageManager.INSTALL_REASON_USER);
// 4. 根据mPackageUri对包进行轻量级的解析,并将解析的参数赋值给SessionParams
File file = new File(mPackageURI.getPath());
try {
PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0);
params.setAppPackageName(pkg.packageName);
params.setInstallLocation(pkg.installLocation);
params.setSize(
PackageHelper.calculateInstalledSize(pkg, false, params.abiOverride));
} catch (PackageParser.PackageParserException e) {
Log.e(LOG_TAG, "Cannot parse package " + file + ". Assuming defaults.");

本文详细解析了Android APK的安装流程,包括通过IO流写入PackageInstaller.Session、调用commit方法、APK拷贝及实际安装过程。涉及关键步骤如创建Session、解析包信息、安装事件回调、拷贝APK、处理安装参数和调用installd守护进程进行最终安装。
最低0.47元/天 解锁文章
4598

被折叠的 条评论
为什么被折叠?



