摘要:android系统的应用安装包是APK格式,这个APK格式如何安装到android设备的呢?

PackageManagerService

Android 系统的应用管理主要通过PackageManagerService来完成
PackageManagerService 启动时会扫描所有的APK文件 和JAR包 把他们的信息读出来保存到内存中,这样系统就能很快的找到各个应用和组件的信息
在android 5.0 以前 ,PackageManagerService会监听安装了应用的目录,一旦目录发生了变化,他讲重新扫描目录,完成自动安装,但是在5.0后 PackageManagerService 不会在监听,这是因为5.0后的目录结构发生了变化。5.0以前/data/app或者/system/app 下面直接存放的是应用APK,而5.0后存放的是应用名称的目录,目录下才是APK 还有个lib的目录 存放的so

Android应用两大类

  • 系统应用
    系统应用是设备内置的应用,通常情况下不能删除,存放在/system/app目录下,4.4以后 又出现了一个/system/priv-app/。两者的区别在于 app下存放的是普通的系统级应用 如 电话,相机等,而priv-app下存放的是 偏底层的系统应用如 系统页面,系统设置 等等
  • 普通应用
    普通应用是 用户安装的应用 在/data/app 目录下,同时可以安装的sd卡上

##安装应用

1:复制文件

调用PackageManager的installPackage()方法来开始安装过程,第一阶段就是把应用复制到/data/app目录下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Override
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) {
//检查调用进程权限
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
//检查进程的用户是否有权限安装
final int callingUid = Binder.getCallingUid();
enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser");
//检查制定用户是否被限制安装
if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
try {
if (observer != null) {
observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null);
}
} catch (RemoteException re) {
}
。。。。。。。。。。。。。
。。。。。。。。。。。。。
//发送消息
final Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(origin, observer, installFlags,
installerPackageName, verificationParams, user, packageAbiOverride);
mHandler.sendMessage(msg);
}

installPackage() 方法里先是做了一些检查工作,例如检查进程的用户是否有权限安装,最后向PackageHandler 发送了下次,然后执行安装,执行安装其实就是调用 HandlerParams的startCopy方法,看名字也知道 要开始复制了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
private abstract class HandlerParams {
private static final int MAX_RETRIES = 4;
/**
* Number of times startCopy() has been attempted and had a non-fatal
* error.
*/
private int mRetries = 0;
/** User handle for the user requesting the information or installation. */
private final UserHandle mUser;
HandlerParams(UserHandle user) {
mUser = user;
}
UserHandle getUser() {
return mUser;
}
final boolean startCopy() {
boolean res;
try {
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
//如果重试查过4次 就发送通知
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 {
//执行复制
handleStartCopy();
res = true;
}
} catch (RemoteException e) {
if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
mHandler.sendEmptyMessage(MCS_RECONNECT);
res = false;
}
//执行装载
handleReturnCode();
return res;
}

HandlerParams 是个抽象类,他的handleStartCopy 方法 和handleReturnCode 在InstallParams 里实现。
由于代码较长具体代码不贴了又兴趣的,可以研究下 ,到了这里apk
的复制算是完成了,然后进行下一步

###:2:装载应用
在上一步 最后调用了 handleReturnCode 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@Override
void handleReturnCode() {
// If mArgs is null, then MCS couldn't be reached. When it
// reconnects, it will try again to install. At that point, this
// will succeed.
if (mArgs != null) {
processPendingInstall(mArgs, mRet);
}
}
private void processPendingInstall(final InstallArgs args, final int currentStatus) {
// Queue up an async operation since the package installation may take a little while.
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();
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
//如果安装成功了
args.doPreInstall(res.returnCode);
synchronized (mInstallLock) {
//装载APP
installPackageLI(args, res);
}
args.doPostInstall(res.returnCode, res.uid);
}
。。。。。。。。
if (!doRestore) {
// No restore possible, or the Backup Manager was mysteriously not
// available -- just fire the post-install work request directly.
if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
//发送完成消息
Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
mHandler.sendMessage(msg);
}
}
});
}

在这个方法里主要调用了 installPackageLI 方法 来装载APP
installPackageLI 也比较长 主要就是 解析的apk文件创建了 判断是老应用还是新应用 如果是新应用就调用
installNewPackageLI来创建各种目录 跟文件

其实安装过程中还需要往PackageManagerService 里写入很多 缓存数据等等 这里就不分析了

卸载应用

PackageManagerService 的卸载方法是 deletePackage()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@Override
public void deletePackage(final String packageName,
final IPackageDeleteObserver2 observer, final int userId, final int flags) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DELETE_PACKAGES, null);
final int uid = Binder.getCallingUid();
if (UserHandle.getUserId(uid) != userId) {
mContext.enforceCallingPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
"deletePackage for user " + userId);
}
if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) {
try {
observer.onPackageDeleted(packageName,
PackageManager.DELETE_FAILED_USER_RESTRICTED, null);
} catch (RemoteException re) {
}
return;
}
boolean uninstallBlocked = false;
if ((flags & PackageManager.DELETE_ALL_USERS) != 0) {
int[] users = sUserManager.getUserIds();
for (int i = 0; i < users.length; ++i) {
if (getBlockUninstallForUser(packageName, users[i])) {
uninstallBlocked = true;
break;
}
}
} else {
uninstallBlocked = getBlockUninstallForUser(packageName, userId);
}
if (uninstallBlocked) {
try {
observer.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_OWNER_BLOCKED,
null);
} catch (RemoteException re) {
}
return;
}
if (DEBUG_REMOVE) {
Slog.d(TAG, "deletePackageAsUser: pkg=" + packageName + " user=" + userId);
}
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
final int returnCode = deletePackageX(packageName, userId, flags);
if (observer != null) {
try {
observer.onPackageDeleted(packageName, returnCode, null);
} catch (RemoteException e) {
Log.i(TAG, "Observer no longer exists.");
} //end catch
} //end if
} //end run
});
}

其实就是删除安装时 生成的apk 和目录 ,同时也删除了 PackageManagerService 里的信息