这篇文章,来学习apk的安装流程,在开始之前,先看看我们在APP中是通过下面代码来安装apk的
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.parse("file://" + path),"application/vnd.android.package-archive");
context.startActivity(intent);
构造一个intent,并且setDataAndType,然后启动这个activity,此时系统默认的安装apk的PackageInstallerActivity界面就出现了。
##使用PackageInstallerActivity安装apk的流程##
在PackageInstallerActivity中定义了这样的字符串
private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
这个是在PackageManagerService中匹配的。
PackageInstallerActivity也是一个activity,所以当该界面显示的时候,会首先调用其onCreate方法,我们来看看。
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
mPm = getPackageManager(); //是一个PackageManager实例,具体用来执行安装操作的
mInstaller = mPm.getPackageInstaller(); // PackageInstaller实例,在该实例中包含了安装apk的基本信息
mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
final Intent intent = getIntent();
//set view
setContentView(R.layout.install_start);
mInstallConfirm = findViewById(R.id.install_confirm_panel);
mInstallConfirm.setVisibility(View.INVISIBLE);
// Block the install attempt on the Unknown Sources setting if necessary.
if (!requestFromUnknownSource) {
// 为安装操作,执行一些初始化的工作
initiateInstall();
return;
}
}
可以看到,在onCreate中,主要通过initiateInstall();为安装操作,执行一些初始化的工作。
private void initiateInstall() {
// 当前apk的包名
String pkgName = mPkgInfo.packageName;
// Check if there is already a package on the device with this name
// but it has been renamed to something else.
String[] oldName = mPm.canonicalToCurrentPackageNames(new String[] { pkgName });
if (oldName != null && oldName.length > 0 && oldName[0] != null) {
pkgName = oldName[0];
mPkgInfo.packageName = pkgName;
mPkgInfo.applicationInfo.packageName = pkgName;
}
try {
// 通过PackageManager从系统中获取没有安装的apk的信息
mAppInfo = mPm.getApplicationInfo(pkgName,
PackageManager.GET_UNINSTALLED_PACKAGES);
// 如果已经安装,在后面会给出用户是否替换的提示
if ((mAppInfo.flags& ApplicationInfo.FLAG_INSTALLED) == 0) {
mAppInfo = null;
}
} catch (PackageManager.NameNotFoundException e) {
mAppInfo = null;
}
// 调用startInstallConfirm进行进一步的安装操作
startInstallConfirm();
}
上面代码最终主要该通过startInstallConfirm来进一步安装apk
private void startInstallConfirm() {
mInstallConfirm.setVisibility(View.VISIBLE);
mOk = (Button)findViewById(R.id.ok_button);
mCancel = (Button)findViewById(R.id.cancel_button);
mOk.setOnClickListener(this);
mCancel.setOnClickListener(this);
}
PackageInstallerActivity实现了OnClicklistener
public void onClick(View v) {
if (v == mOk) {
startInstall();
} else if(v == mCancel) {
// Cancel and finish
setResult(RESULT_CANCELED);
finish();
}
}
private void startInstall() {
// 安装apk,构造intent,这里会跳转到InstallAppProgress里
Intent newIntent = new Intent();
// 传递数据
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
mPkgInfo.applicationInfo);
newIntent.setData(mPackageURI);
newIntent.setClass(this, InstallAppProgress.class);
newIntent.putExtra(InstallAppProgress.EXTRA_MANIFEST_DIGEST, mPkgDigest);
newIntent.putExtra(
InstallAppProgress.EXTRA_INSTALL_FLOW_ANALYTICS, mInstallFlowAnalytics);
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 != VerificationParams.NO_UID) {
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);
}
// 进入InstallAppProgress
startActivity(newIntent);
finish();
}
可以看到在startInstall方法中,主要构造一个intent,并且传递必要的数据,跳转到InstallAppProgress类,在该类中有一个initView方法
public void initView() {
setContentView(R.layout.op_progress);
int installFlags = 0;
PackageManager pm = getPackageManager();
// 判断当前apk是否已经安装过
try {
PackageInfo pi = pm.getPackageInfo(mAppInfo.packageName,
PackageManager.GET_UNINSTALLED_PACKAGES);
if(pi != null) {
installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
}
} catch (PackageManager.NameNotFoundException e) {
}
// 省略代码
// 构造一个PackageInstallObserver,当安装完成以后,回调对应的方法
PackageInstallObserver observer = new PackageInstallObserver();
if ("package".equals(mPackageURI.getScheme())) {
try {
// 调用PackageManagerService服务的installExistingPackage进行安装
pm.installExistingPackage(mAppInfo.packageName);
observer.packageInstalled(mAppInfo.packageName,
PackageManager.INSTALL_SUCCEEDED);
} catch (PackageManager.NameNotFoundException e) {
observer.packageInstalled(mAppInfo.packageName,
PackageManager.INSTALL_FAILED_INVALID_APK);
}
} else {
pm.installPackageWithVerificationAndEncryption(mPackageURI, observer, installFlags,
installerPackageName, verificationParams, null);
}
}
这里具体的PackageManagerService服务安装的过程我们稍后会进行学习,先看下当安装完成以后通过PackageInstallObserver执行的回调方法
class PackageInstallObserver extends IPackageInstallObserver.Stub {
public void packageInstalled(String packageName, int returnCode) {
Message msg = mHandler.obtainMessage(INSTALL_COMPLETE);
msg.arg1 = returnCode;
mHandler.sendMessage(msg);
}
}
发送”INSTALL_COMPLETE”这样的消息到自身,在handleMessage中主要做了下面的操作:
mLaunchIntent = getPackageManager().getLaunchIntentForPackage(
mAppInfo.packageName);
mLaunchButton.setOnClickListener(InstallAppProgress.this);
mDoneButton.setOnClickListener(InstallAppProgress.this);
获取启动当前apk的intent,并且为done和lunch按钮设置点击事件
public void onClick(View v) {
if(v == mDoneButton) {
if (mAppInfo.packageName != null) {
Log.i(TAG, "Finished installing "+mAppInfo.packageName);
}
finish();
} else if(v == mLaunchButton) {
startActivity(mLaunchIntent);
finish();
}
}
好了,到现在为止,使用PackageInstallerActivity安装apk的整个流程已经梳理完毕,实际上真正执行安装操作的都是交给了PackageManagerService服务的installExistingPackage进行安装的
##PackageManagerService安装apk流程##
平时我们可以使用下面两个命令来安装apk
pm get-install-location 查找安装apk的位置 一般默认 为0[auto]
pm set-install-location 设置位置
这里最终都是通过PackageManagerService来实现安装具体包的操作
调用PackageManagerService#installPackage方法开始apk的安装过程
public void installPackage(String originPath, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, VerificationParams verificationParams,
String packageAbiOverride) {
installPackageAsUser(originPath, observer, installFlags, installerPackageName,
verificationParams, packageAbiOverride, UserHandle.getCallingUserId());
}
@Override
public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, VerificationParams verificationParams,
String packageAbiOverride, int userId) {
// 检查是否有install权限
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
final int callingUid = Binder.getCallingUid();
enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser");
// 判断当前用户是否被Restricted,回调onPackageInstalled方法,安装失败
if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
try {
if (observer != null) {
observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null);
}
} catch (RemoteException re) {
}
return;
}
// 代码省略,主要是判断当前安装的方式设置对应的installFlags
final File originFile = new File(originPath);
final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
// 发送"INIT_COPY" 消息,构造InstallParams参数
final Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(origin, null, observer, installFlags, installerPackageName,
null, verificationParams, user, packageAbiOverride, null);
mHandler.sendMessage(msg);
}
整个PackageHandler是PackageManagerService的一个内部类
witch (msg.what) {
case INIT_COPY: {
HandlerParams params = (HandlerParams) msg.obj;
//这里获取当前需要安装的apk个数,mPendingInstalls保存着所有需要安装的apk解析出来的HandlerParams参数
int idx = mPendingInstalls.size();
if (DEBUG_INSTALL) Slog.i(TAG, "init_copy idx=" + idx + ": " + params);
// 如果没有绑定DefaultContainerService,则进行那个绑定,DefaultContainerService主要负责计算当前存储和拷贝工作
if (!mBound) {
if (!connectToService()) {
params.serviceError();
return;
} else {
mPendingInstalls.add(idx, params);
}
} else {
mPendingInstalls.add(idx, params);
if (idx == 0) {
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
break;
}
继续发送”MCS_BOUND”参数到自己处理,表示绑定DefaultContainerService服务完成
case MCS_BOUND: {
if (msg.obj != null) {
mContainerService = (IMediaContainerService) msg.obj;
}
if (mContainerService == null) {
// 绑定DefaultContainerService服务失败,回调serviceError方法
if (!mBound) {
Slog.e(TAG, "Cannot bind to media container service");
for (HandlerParams params : mPendingInstalls) {
params.serviceError();
}
mPendingInstalls.clear();
} else {
Slog.w(TAG, "Waiting to connect to media container service");
}
} else if (mPendingInstalls.size() > 0) {
// 总是安装队列中的第一个
HandlerParams params = mPendingInstalls.get(0);
if (params != null) {
if (params.startCopy()) { //首先拷贝当前apk到对应的目录下
// We are done... look for more work or to
// go idle.
if (mPendingInstalls.size() > 0) { // 将第一个移除当前队列
mPendingInstalls.remove(0);
}
if (mPendingInstalls.size() == 0) { //size等于0,表示所有的apk都已经安装完成,unbind当前DefaultContainerService服务
if (mBound) {
if (DEBUG_SD_INSTALL) Log.i(TAG,
"Posting delayed MCS_UNBIND");
removeMessages(MCS_UNBIND);
Message ubmsg = obtainMessage(MCS_UNBIND);
// Unbind after a little delay, to avoid
// continual thrashing.
sendMessageDelayed(ubmsg, 10000);
}
} else {
//继续安装下一个需要安装的包
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
}
} else {
Slog.w(TAG, "Empty queue");
}
break;
}
可以看到,其实所有的安装apk的代码都放到了HandlerParams#startCopy方法中,看下HandlerParams
private abstract class HandlerParams {
final boolean startCopy() {
boolean res;
try {
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
if (++mRetries > MAX_RETRIES) {
Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
mHandler.sendEmptyMessage(MCS_GIVE_UP);
handleServiceError();
return false;
} else {
// 这里的具体copy处理是由其子类来完成的
handleStartCopy();
res = true;
}
} catch (RemoteException e) {
if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
mHandler.sendEmptyMessage(MCS_RECONNECT);
res = false;
}
// handleReturnCode,该方法会在handleStartCopy执行玩拷贝相关动作之后,根据在handleStartCopy中的做进一步处理
handleReturnCode();
return res;
}
final void serviceError() {
if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
handleServiceError();
handleReturnCode();
}
abstract void handleStartCopy() throws RemoteException;
abstract void handleServiceError();
abstract void handleReturnCode();
}
}
这里是由InstallParams来处理copy操作的。
public void handleStartCopy() throws RemoteException {
int ret = PackageManager.INSTALL_SUCCEEDED;
if (origin.staged) {
if (origin.file != null) {
installFlags |= PackageManager.INSTALL_INTERNAL;
installFlags &= ~PackageManager.INSTALL_EXTERNAL;
} else if (origin.cid != null) {
installFlags |= PackageManager.INSTALL_EXTERNAL;
installFlags &= ~PackageManager.INSTALL_INTERNAL;
} else {
throw new IllegalStateException("Invalid stage location");
}
}
// 是否安装到sdcard或者内部存储中
final boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
final boolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
PackageInfoLite pkgLite = null;
if (onInt && onSd) {
// 用户同时设置安装到sdcard和内部存储
Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else {
pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
packageAbiOverride);
.......
//代码省略,主要根据存储情况,释放当前存储空间
}
// 根据当前InstallParams构造具体的InstallArgs实现类,在该实现类中做具体的拷贝操作
final InstallArgs args = createInstallArgs(this);
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
/*
* ADB installs appear as UserHandle.USER_ALL, and can only be performed by
* UserHandle.USER_OWNER, so use the package verifier for UserHandle.USER_OWNER.
*/
int userIdentifier = getUser().getIdentifier();
if (userIdentifier == UserHandle.USER_ALL
&& ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0)) {
userIdentifier = UserHandle.USER_OWNER;
}
final int requiredUid = mRequiredVerifierPackage == null ? -1
: getPackageUid(mRequiredVerifierPackage, userIdentifier);
if (!origin.existing && requiredUid != -1
&& isVerificationEnabled(userIdentifier, installFlags) &&
isVerificationRequired()) { // 对当前的包做验证操作
final Intent verification = new Intent(
Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
PACKAGE_MIME_TYPE);
verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
final List<ResolveInfo> receivers = queryIntentReceivers(verification,
PACKAGE_MIME_TYPE, PackageManager.GET_DISABLED_COMPONENTS,
0 /* TODO: Which userId? */);
final int verificationId = mPendingVerificationToken++;
verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
installerPackageName);
verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS,
installFlags);
verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME,
pkgLite.packageName);
verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
pkgLite.versionCode);
if (verificationParams != null) {
if (verificationParams.getVerificationURI() != null) {
verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
verificationParams.getVerificationURI());
}
if (verificationParams.getOriginatingURI() != null) {
verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
verificationParams.getOriginatingURI());
}
if (verificationParams.getReferrer() != null) {
verification.putExtra(Intent.EXTRA_REFERRER,
verificationParams.getReferrer());
}
if (verificationParams.getOriginatingUid() >= 0) {
verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
verificationParams.getOriginatingUid());
}
if (verificationParams.getInstallerUid() >= 0) {
verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
verificationParams.getInstallerUid());
}
}
final PackageVerificationState verificationState = new PackageVerificationState(
requiredUid, args);
mPendingVerification.append(verificationId, verificationState);
final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
receivers, verificationState);
// Apps installed for "all" users use the device owner to verify the app
UserHandle verifierUser = getUser();
if (verifierUser == UserHandle.ALL) {
verifierUser = UserHandle.OWNER;
}
/*
* If any sufficient verifiers were listed in the package
* manifest, attempt to ask them.
*/
if (sufficientVerifiers != null) {
final int N = sufficientVerifiers.size();
if (N == 0) {
Slog.i(TAG, "Additional verifiers required, but none installed.");
ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
} else {
for (int i = 0; i < N; i++) {
final ComponentName verifierComponent = sufficientVerifiers.get(i);
final Intent sufficientIntent = new Intent(verification);
sufficientIntent.setComponent(verifierComponent);
mContext.sendBroadcastAsUser(sufficientIntent, verifierUser);
}
}
}
final ComponentName requiredVerifierComponent = matchComponentForVerifier(
mRequiredVerifierPackage, receivers);
if (ret == PackageManager.INSTALL_SUCCEEDED
&& mRequiredVerifierPackage != null) {
/*
* Send the intent to the required verification agent,
* but only start the verification timeout after the
* target BroadcastReceivers have run.
*/
verification.setComponent(requiredVerifierComponent);
mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final Message msg = mHandler
.obtainMessage(CHECK_PENDING_VERIFICATION);
msg.arg1 = verificationId;
mHandler.sendMessageDelayed(msg, getVerificationTimeout());
}
}, null, 0, null, null);
/*
* We don't want the copy to proceed until verification
* succeeds, so null out this field.
*/
mArgs = null;
}
} else {
// 执行拷贝操作
ret = args.copyApk(mContainerService, true);
}
}
mRet = ret;
}
上面主要做了这样的事情:
- 判断安装默认存储
- 若当前存储不够,则释放储存空间
- 如果需要,对当前包做验证操作
-
执行拷贝操作
就安装而言,最重要的还是最后的执行拷贝操作,这里是InstallArgs#copyApk
static abstract class InstallArgs
包含三个子类
- FileInstallArgs apk安装到内部存储器时使用。
- AsecInstallArgs 安装到sdcard或者ForwardLocked时使用
-
MoveInstallArgs 移动包的位置,比如从内部存储移动到sdcard上
在构造方法中根据InstallParams会构造出具体类型
private InstallArgs createInstallArgs(InstallParams params) {
if (params.move != null) {
return new MoveInstallArgs(params);
} else if (installOnExternalAsec(params.installFlags) || params.isForwardLocked()) {
return new AsecInstallArgs(params);
} else {
return new FileInstallArgs(params);
}
}
这里我们以AsecInstallArgs为例,进行说明
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
if (origin.staged) {
if (DEBUG_INSTALL) Slog.d(TAG, origin.cid + " already staged; skipping copy");
cid = origin.cid;
setMountPath(PackageHelper.getSdDir(cid));
return PackageManager.INSTALL_SUCCEEDED;
}
if (temp) {
createCopyFile();
} else {
/*
* Pre-emptively destroy the container since it's destroyed if
* copying fails due to it existing anyway.
*/
PackageHelper.destroySdDir(cid);
}
//copyPackageToContainer执行真正的拷贝操作
final String newMountPath = imcs.copyPackageToContainer(
origin.file.getAbsolutePath(), cid, getEncryptKey(), isExternalAsec(),
isFwdLocked(), deriveAbiOverride(abiOverride, null /* settings */));
if (newMountPath != null) {
setMountPath(newMountPath);
return PackageManager.INSTALL_SUCCEEDED; //这里安装成功之后,会将mRet赋值为PackageManager.INSTALL_SUCCEEDED
} else {
return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
}
}
到现在为止,copyApk的操作已经完成,接下来交给handleReturnCode处理
@Override
void handleReturnCode() {
// mArgs是在handleStartCopy中创建的
if (mArgs != null) {
processPendingInstall(mArgs, mRet);
}
}
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
// 由于安装可能耗时操作,所以这里开启了一个线程
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
// Result object to be returned
PackageInstalledInfo res = new PackageInstalledInfo();
res.returnCode = currentStatus;
res.uid = -1;
res.pkg = null;
res.removedInfo = new PackageRemovedInfo();
// 如果之前copyApk正常执行完成,这里res.returnCode == PackageManager.INSTALL_SUCCEEDED成立
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
args.doPreInstall(res.returnCode); //安装前的准备工作
synchronized (mInstallLock) {
installPackageLI(args, res); //执行安装操作
}
args.doPostInstall(res.returnCode, res.uid); //安装完成以后的曹操作
}
.........
Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0); // 安装完成后发送"POST_INSTALL"广播
mHandler.sendMessage(msg);
}
});
}
看下进一步安装的相关步骤
private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {
......
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setDisplayMetrics(mMetrics);
pp.setRuntimeSkinBlacklist(mRuntimeSkinManager.getBlacklistedPackages());
final PackageParser.Package pkg;
try {
// PackageParser解析manifest文件
pkg = pp.parsePackage(tmpPackageFile, parseFlags);
} catch (PackageParser.PackageParserException e) {
res.setError("Failed parse during installPackageLI", e);
return;
}
// Mark that we have an install time CPU ABI override.
pkg.cpuAbiOverride = args.abiOverride;
String pkgName = res.name = pkg.packageName;
// Mark that we have an install time CPU ABI override.
pkg.cpuAbiOverride = args.abiOverride;
String pkgName = res.name = pkg.packageName;
// 根据用户策略,判断当前用户是否允许安装apk,否则直接返回
boolean installForAllUsers = ((installFlags & PackageManager.INSTALL_ALL_USERS) != 0);
int user = args.user == null ? -1 : args.user.getIdentifier();
if (isInstallationBlockedByDevicePolicy(pkgName, installForAllUsers, user)) {
res.returnCode = PackageManager.INSTALL_FAILED_USER_RESTRICTED;
return;
}
// 签名相关信息
try {
pp.collectCertificates(pkg, parseFlags);
pp.collectManifestDigest(pkg);
} catch (PackageParser.PackageParserException e) {
res.setError("Failed collect during installPackageLI", e);
return;
}
........
// 如果已经安装当前应用,则替换,否则安装
if (replace) {
replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
installerPackageName, volumeUuid, res);
} else {
installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
args.user, installerPackageName, volumeUuid, res);
}
}
可以看到上面的代码主要做了下面操作:
- 解析manifest文件,并且将解析结果封装成PackageParser对象
- 判断当前安装条件四是否满足,否则直接返回,比如:根据用户策略,判断当前用户是否允许安装apk,否则直接返回
- 获取签名相关信息,并且做校验
- 安装或者替换当前应用installNewPackageLI或者replacePackageLI
PackageParser解析manifest文件,PackageParser#parsePackage —-> PackageParser#parseClusterPackage —> PackageParser#parseBaseApk
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
String volumeUuid = null;
if (apkPath.startsWith(MNT_EXPAND)) {
final int end = apkPath.indexOf('/', MNT_EXPAND.length());
volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
}
mParseError = PackageManager.INSTALL_SUCCEEDED;
mArchiveSourcePath = apkFile.getAbsolutePath();
if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
Resources res = null;
XmlResourceParser parser = null;
try {
res = new Resources(assets, mMetrics, null);
assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
// 解析manifest文件
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final String[] outError = new String[1];
final Package pkg = parseBaseApk(res, parser, flags, outError);
if (pkg == null) {
throw new PackageParserException(mParseError,
apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
}
pkg.volumeUuid = volumeUuid;
pkg.applicationInfo.volumeUuid = volumeUuid;
pkg.baseCodePath = apkPath;
pkg.mSignatures = null;
return pkg;
} catch (PackageParserException e) {
throw e;
} catch (Exception e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to read manifest from " + apkPath, e);
} finally {
IoUtils.closeQuietly(parser);
}
}
通过installNewPackageLI执行安装操作
/*
* Install a non-existing package.
*/
private void installNewPackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags,
UserHandle user, String installerPackageName, String volumeUuid,
PackageInstalledInfo res) {
// Remember this for later, in case we need to rollback this install
String pkgName = pkg.packageName;
.......
try {
// 核心的调用
PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanFlags,
System.currentTimeMillis(), user);
updateSettingsLI(newPackage, installerPackageName, volumeUuid, null, null, res, user);
//如果安装失败,则执行回退操作,删除创建的文件夹等缓存文件
if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
deletePackageLI(pkgName, UserHandle.ALL, false, null, null,
dataDirExists ? PackageManager.DELETE_KEEP_DATA : 0,
res.removedInfo, true);
}
} catch (PackageManagerException e) {
res.setError("Package couldn't be installed in " + pkg.codePath, e);
}
}
private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
boolean success = false;
try {
final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags,
currentTime, user);
success = true;
// 程序走到这里说明安装成功了,这里会返回根据解析构建的Package对象,该对象中包含了该apk对应的manifest中的信息
return res;
} finally {
if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
removeDataDirsLI(pkg.volumeUuid, pkg.packageName);
}
}
}
终于走到了scanPackageDirtyLI方法,安装apk的核心方法:
在该方法中,会根据之前解析出来的内容,添加到对应的list中,方便以后query查询
// Currently known shared libraries.
final ArrayMap<String, SharedLibraryEntry> mSharedLibraries =
new ArrayMap<String, SharedLibraryEntry>();
// All available activities, for your resolving pleasure.
final ActivityIntentResolver mActivities =
new ActivityIntentResolver();
// All available receivers, for your resolving pleasure.
final ActivityIntentResolver mReceivers =
new ActivityIntentResolver();
// All available services, for your resolving pleasure.
final ServiceIntentResolver mServices = new ServiceIntentResolver();
// All available providers, for your resolving pleasure.
final ProviderIntentResolver mProviders = new ProviderIntentResolver();
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
.......
int N = pkg.providers.size();
StringBuilder r = null;
int i;
for (i=0; i<N; i++) {
PackageParser.Provider p = pkg.providers.get(i);
p.info.processName = fixProcessName(pkg.applicationInfo.processName,
p.info.processName, pkg.applicationInfo.uid);
// 添加provider
mProviders.addProvider(p);
p.syncable = p.info.isSyncable;
if (p.info.authority != null) {
String names[] = p.info.authority.split(";");
p.info.authority = null;
for (int j = 0; j < names.length; j++) {
if (j == 1 && p.syncable) {
// We only want the first authority for a provider to possibly be
// syncable, so if we already added this provider using a different
// authority clear the syncable flag. We copy the provider before
// changing it because the mProviders object contains a reference
// to a provider that we don't want to change.
// Only do this for the second authority since the resulting provider
// object can be the same for all future authorities for this provider.
p = new PackageParser.Provider(p);
p.syncable = false;
}
if (!mProvidersByAuthority.containsKey(names[j])) {
mProvidersByAuthority.put(names[j], p);
if (p.info.authority == null) {
p.info.authority = names[j];
} else {
p.info.authority = p.info.authority + ";" + names[j];
}
if (DEBUG_PACKAGE_SCANNING) {
if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
Log.d(TAG, "Registered content provider: " + names[j]
+ ", className = " + p.info.name + ", isSyncable = "
+ p.info.isSyncable);
}
} else {
PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
Slog.w(TAG, "Skipping provider name " + names[j] +
" (in package " + pkg.applicationInfo.packageName +
"): name already used by "
+ ((other != null && other.getComponentName() != null)
? other.getComponentName().getPackageName() : "?"));
}
}
}
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(p.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Providers: " + r);
}
N = pkg.services.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Service s = pkg.services.get(i);
s.info.processName = fixProcessName(pkg.applicationInfo.processName,
s.info.processName, pkg.applicationInfo.uid);
// 添加service
mServices.addService(s);
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(s.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Services: " + r);
}
N = pkg.receivers.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.receivers.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
// 添加receivers
mReceivers.addActivity(a, "receiver");
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
}
N = pkg.activities.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.activities.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
// 添加activity
mActivities.addActivity(a, "activity");
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Activities: " + r);
}
N = pkg.permissionGroups.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
if (cur == null) {
// 添加权限
mPermissionGroups.put(pg.info.name, pg);
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(pg.info.name);
}
} else {
Slog.w(TAG, "Permission group " + pg.info.name + " from package "
+ pg.info.packageName + " ignored: original from "
+ cur.info.packageName);
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append("DUP:");
r.append(pg.info.name);
}
}
}
......
return pkg;
}
好了现在已经安装完成了,上面的代码,我们已经知道,安装分为三个阶段:
- 安装前的准备工作
- 安装工作
- doPostInstall 安装完成后的工作
int doPostInstall(int status, int uid) {
if (status != PackageManager.INSTALL_SUCCEEDED) {
// 主要清除之前创建的临时文件夹
cleanUp();
} else {
final int groupOwner;
final String protectedFile;
if (isFwdLocked()) {
groupOwner = UserHandle.getSharedAppGid(uid);
protectedFile = RES_FILE_NAME;
} else {
groupOwner = -1;
protectedFile = null;
}
if (uid < Process.FIRST_APPLICATION_UID
|| !PackageHelper.fixSdPermissions(cid, groupOwner, protectedFile)) {
Slog.e(TAG, "Failed to finalize " + cid);
PackageHelper.destroySdDir(cid);
return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
}
boolean mounted = PackageHelper.isContainerMounted(cid);
if (!mounted) {
PackageHelper.mountSdDir(cid, getEncryptKey(), Process.myUid());
}
}
return status;
}
可以看到在doPostInstall方法中,主要清除之前创建的临时文件夹
到现在,安装完成并且删除临时目录,发送”POST_INSTALL”消息,交给PackageHandler处理
case POST_INSTALL: {
.......
if (data != null) {
InstallArgs args = data.args;
PackageInstalledInfo res = data.res;
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
.....
// 安装完成之后发送"ACTION_PACKAGE_ADDED"广播
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
packageName, extras, null, null, firstUsers);
final boolean update = res.removedInfo.removedPackage != null;
if (update) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
packageName, extras, null, null, updateUsers);
// 如果当前应用已经安装,发送"ACTION_PACKAGE_REPLACED"广播
if (update) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
packageName, extras, null, null, updateUsers);
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
null, null, packageName, null, updateUsers);
// treat asec-hosted packages like removable media on upgrade
if (res.pkg.isForwardLocked() || isExternal(res.pkg)) {
if (DEBUG_INSTALL) {
Slog.i(TAG, "upgrading pkg " + res.pkg
+ " is ASEC-hosted -> AVAILABLE");
}
int[] uidArray = new int[] { res.pkg.applicationInfo.uid };
ArrayList<String> pkgList = new ArrayList<String>(1);
pkgList.add(packageName);
sendResourcesChangedBroadcast(true, true,
pkgList,uidArray, null);
}
}
if (res.removedInfo.args != null) {
// Remove the replaced package's older resources safely now
deleteOld = true;
}
}
// Force a gc to clear up things
Runtime.getRuntime().gc();
// We delete after a gc for applications on sdcard.
if (deleteOld) {
synchronized (mInstallLock) {
res.removedInfo.args.doPostDeleteLI(true);
}
}
if (args.observer != null) {
try {
Bundle extras = extrasForInstallResult(res);
// 回调onPackageInstalled方法
args.observer.onPackageInstalled(res.name, res.returnCode,
res.returnMsg, extras);
} catch (RemoteException e) {
Slog.i(TAG, "Observer no longer exists.");
}
}
} else {
Slog.e(TAG, "Bogus post-install token " + msg.arg1);
}
}
好了,关于apk的安装的大致流程就到这里了。下面画一张图来总结一下,如有遗漏或者不对的地方,欢迎指教。
欢 迎 关 注 我 的 公 众 号 “编 程 大 全”
专注技术分享,包括Java,python,AI人工智能,Android分享,不定期更新学习视频