android多用户下应用安装详解三(特殊需求实现)
2015-01-27 16:38
411 查看
前两篇已经对新应用安装和开机加载应用安装信息的流程做了详细梳理,下面来看一个需求。在说这个需求之前,我们了解一个背景:多用户下,如果使用adb install xxx.apk的话,会导致全用户安装。聪明的读者可能就知道了,这实际上破坏了多用户的独立性。而我所在的项目即利用到了多用户,这显然不能让人接受,尤其是很多pc上的android应用安装工具,会直接把一些应用安装到另外一个用户里。实际上这也是我调研这个问题的原因。
下面来分析全用户安装的原因:
1. packagemanagerservice安装入口installPackageWithVerificationAndEncryption()里:
UserHandle user;
if ((flags&PackageManager.INSTALL_ALL_USERS) != 0) {
user = UserHandle.ALL;
} else {
user = new UserHandle(UserHandle.getUserId(uid));
}
看到这里,可以大致猜测就是这个UserHandle.ALL导致的全用户安装的,实际的情况也确实是这样的,在层层传递之后,会进入com.android.server.pm.Settings.getPackageLPw(): 有一段逻辑是这样的:
List<UserInfo> users = getAllUsers();
if (users != null && allowInstall) {
for (UserInfo user : users) {
final boolean installed = installUser == null
|| installUser.getIdentifier() == UserHandle.USER_ALL
|| installUser.getIdentifier() == user.id;
p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT,
installed,
true, // stopped,
true, // notLaunched
false, // blocked
null, null, null);
writePackageRestrictionsLPr(user.id);
}
}
看到这里肯定就明白了,所以一个直观的想法就是修改这段逻辑
if ((flags&PackageManager.INSTALL_ALL_USERS) != 0) {
user = UserHandle.ALL;
}
改为:user = new UserHandle(ActivityManagerNative.getDefault().getCurrentUser().id); 即如果使用adb install的话就将安装用户设为当前前台用户,避免全用户安装。
2. 这个确实能屏蔽绝大部分情况,但是还是屏蔽不了所有的情况:
比如adb push xxx.apk /data/app, 当然这个需要系统权限,三方安装工具是没有这个权限的。
但还有一种情况,却是真的可能发生。就是安装过程中手机重启,尤其是一些国产手机比较容易出现,这样的情况就会如上篇中所讲,开机扫描到/data/app目录下有新apk的时候就会重新走安装流程。
private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
for (i=0; i<files.length; i++) {
................................................................................................................
PackageParser.Package pkg = scanPackageLI(file,
flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
这里面最后一个参数就是installUser, 如果等于null, 根据第一篇第7部分知道也会被全用户安装
................................................................................................................
}
}
3. 所以我们如果想彻底屏蔽全用户安装,需要找到一个所有情况都会走到的地方。
实际这个地方就是com.android.server.pm.Settings.getPackageLPw(String
name, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
String nativeLibraryPathString, int vc, int pkgFlags,
UserHandle installUser, boolean add, boolean allowInstall)方法,因为第一篇,第二篇的分析知道,不管是正常的安装流程,还是开机扫描/data/app目录,包括开机之后监听/data/app目录都会最终走到这个方法里。所以我们只需要在这个方法里将installUser设为当前用户即可。
即:
installUser = new UserHandle(ActivityManagerNative.getDefault().getCurrentUser().id);
ok.这就是延伸出来的一个需求修改。网上关于多用户分析的技术文章还比较少,有用的更是不可得,所以这里对自己的分析做一个记录分享。
下面来分析全用户安装的原因:
1. packagemanagerservice安装入口installPackageWithVerificationAndEncryption()里:
UserHandle user;
if ((flags&PackageManager.INSTALL_ALL_USERS) != 0) {
user = UserHandle.ALL;
} else {
user = new UserHandle(UserHandle.getUserId(uid));
}
看到这里,可以大致猜测就是这个UserHandle.ALL导致的全用户安装的,实际的情况也确实是这样的,在层层传递之后,会进入com.android.server.pm.Settings.getPackageLPw(): 有一段逻辑是这样的:
List<UserInfo> users = getAllUsers();
if (users != null && allowInstall) {
for (UserInfo user : users) {
final boolean installed = installUser == null
|| installUser.getIdentifier() == UserHandle.USER_ALL
|| installUser.getIdentifier() == user.id;
p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT,
installed,
true, // stopped,
true, // notLaunched
false, // blocked
null, null, null);
writePackageRestrictionsLPr(user.id);
}
}
看到这里肯定就明白了,所以一个直观的想法就是修改这段逻辑
if ((flags&PackageManager.INSTALL_ALL_USERS) != 0) {
user = UserHandle.ALL;
}
改为:user = new UserHandle(ActivityManagerNative.getDefault().getCurrentUser().id); 即如果使用adb install的话就将安装用户设为当前前台用户,避免全用户安装。
2. 这个确实能屏蔽绝大部分情况,但是还是屏蔽不了所有的情况:
比如adb push xxx.apk /data/app, 当然这个需要系统权限,三方安装工具是没有这个权限的。
但还有一种情况,却是真的可能发生。就是安装过程中手机重启,尤其是一些国产手机比较容易出现,这样的情况就会如上篇中所讲,开机扫描到/data/app目录下有新apk的时候就会重新走安装流程。
private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
for (i=0; i<files.length; i++) {
................................................................................................................
PackageParser.Package pkg = scanPackageLI(file,
flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
这里面最后一个参数就是installUser, 如果等于null, 根据第一篇第7部分知道也会被全用户安装
................................................................................................................
}
}
3. 所以我们如果想彻底屏蔽全用户安装,需要找到一个所有情况都会走到的地方。
实际这个地方就是com.android.server.pm.Settings.getPackageLPw(String
name, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
String nativeLibraryPathString, int vc, int pkgFlags,
UserHandle installUser, boolean add, boolean allowInstall)方法,因为第一篇,第二篇的分析知道,不管是正常的安装流程,还是开机扫描/data/app目录,包括开机之后监听/data/app目录都会最终走到这个方法里。所以我们只需要在这个方法里将installUser设为当前用户即可。
即:
installUser = new UserHandle(ActivityManagerNative.getDefault().getCurrentUser().id);
ok.这就是延伸出来的一个需求修改。网上关于多用户分析的技术文章还比较少,有用的更是不可得,所以这里对自己的分析做一个记录分享。
相关文章推荐
- 【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料
- 【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料
- 【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料
- 【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料
- 【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料
- 【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料
- 【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料
- android多用户下应用安装详解二(开机读取流程)
- 【Android应用开发详解】实现第三方授权登录、分享以及获取用户资料
- 【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料
- 【Android应用开发详解】第01期:第三方授权认证(一)实现第三方授权登录、分享以及获取用户资料
- android多用户下应用安装详解一(新应用安装情况)
- Android应用自动更新功能的实现!!!软件更新,自动下载,安装
- android应用后台安装,静默安装的代码实现方法
- Android实现应用下载并自动安装apk包
- [置顶] 【Android应用开发】-(18)静默方式实现批量安装卸载应用程序
- Android应用实现安装外部apk
- Android实现应用下载并自动安装apk包
- android应用后台安装,静默安装的代码实现方法
- Android实现应用下载并自动安装apk包