我是靠谱客的博主 羞涩裙子,这篇文章主要介绍PackageManagerService的常用方法,现在分享给大家,希望可以做个参考。

getPackageArchiveInfo得到APK包含的信息

复制代码
1
public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags)

参数archiveFilePath表示一个APK文件的绝对路径。注意返回值PackageInfo,包含Package的所有信息,这些信息都是从AndroidManifest.xml文件中获取的。如果没有成功解析这个包,就返回null。

另外注意第二个参数flags,参考如下:

Use any combination of GET_ACTIVITIESGET_GIDSGET_CONFIGURATIONS,GET_INSTRUMENTATIONGET_PERMISSIONSGET_PROVIDERSGET_RECEIVERSGET_SERVICES,GET_SIGNATURES, to modify the data returned.

getPackageAchiveInfo方法源码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) { final PackageParser parser = new PackageParser(); final File apkFile = new File(archiveFilePath); try { PackageParser.Package pkg = parser.parseMonolithicPackage(apkFile, 0); if ((flags & GET_SIGNATURES) != 0) { parser.collectCertificates(pkg, 0); parser.collectManifestDigest(pkg); } PackageUserState state = new PackageUserState(); return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0, null, state); } catch (PackageParserException e) { return null; } }

getInstalledPackages(int flags)

public abstract List<PackageInfo> getInstalledPackages(int flags):获取安装到设备上的所有包集合,返回List<PackageInfo>对象。
参数flags可以是下面的任意组合, GET_ACTIVITIES GET_GIDS GET_CONFIGURATIONS , GET_INSTRUMENTATION GET_PERMISSIONS GET_PROVIDERS GET_RECEIVERS GET_SERVICES GET_SIGNATURES , GET_UNINSTALLED_PACKAGES。
如果flag设置了GET_UNINSTALLED_PACKAGES,则返回对象中包含删除时指定参数DONT_DELETE_DATA的应用。

getApplicationInfo(String packageName, int flags)

检索指定包名的所有信息的ApplicationInfo对象。flags参数可以是GET_META_DATA,GET_SHARED_LIBRARY_FILES,GET_UNINSTALLED_PACKAGES。
如果flags设定了GET_UNINSTALLED_PACKAGES,如果在已安装的应用列表中没有包含指定包,应用信息就从未安装应用(删除时保留数据目录的应用)列表中检索,
复制代码
1
2
3
4
5
6
7
8
9
10
11
try { //如果设置了GET_UNINSTALLED_PACKAGES这个flag,并且在已安装应用列表中没有找到这个包名,则从未安装的应用列表中检索。 //也就是说从已安装的应用程序中检索,以及删除时指定DONT_DELETE_DATA标记的应用程序(表示删除时不删除应用数据) ApplicationInfo info = context.getPackageManager() .getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES); if(null != info){ state = "Installed"; } } catch (NameNotFoundException e) { }

判断是否为系统应用

复制代码
1
2
3
4
5
6
7
8
9
public static boolean isSystemApp(ApplicationInfo appInfo) { boolean flag = false; if (appInfo != null && ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 || (appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)) { flag = true; } return flag; }

复制代码
1
2
3
4
5
6
7
8
public static boolean isSystemCoreApp(ApplicationInfo appInfo) { boolean flag = false; if (appInfo != null && (appInfo.uid < 10000)) { flag = true; } return flag; }

setComponentEnabledSetting禁用开启组件

我们先看一下源码中是怎么解释的,如下:

复制代码
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
/** * Set the enabled setting for a package component (activity, receiver, service, provider). * This setting will override any enabled state which may have been set by the component in its * manifest. * * @param componentName The component to enable * @param newState The new enabled state for the component. The legal values for this state * are: * {@link #COMPONENT_ENABLED_STATE_ENABLED}, * {@link #COMPONENT_ENABLED_STATE_DISABLED} * and * {@link #COMPONENT_ENABLED_STATE_DEFAULT} * The last one removes the setting, thereby restoring the component's state to * whatever was set in it's manifest (or enabled, by default). * @param flags Optional behavior flags: {@link #DONT_KILL_APP} or 0. */ public abstract void setComponentEnabledSetting(ComponentName componentName, int newState, int flags); /** * Return the enabled setting for a package component (activity, * receiver, service, provider). This returns the last value set by * {@link #setComponentEnabledSetting(ComponentName, int, int)}; in most * cases this value will be {@link #COMPONENT_ENABLED_STATE_DEFAULT} since * the value originally specified in the manifest has not been modified. * * @param componentName The component to retrieve. * @return Returns the current enabled state for the component. May * be one of {@link #COMPONENT_ENABLED_STATE_ENABLED}, * {@link #COMPONENT_ENABLED_STATE_DISABLED}, or * {@link #COMPONENT_ENABLED_STATE_DEFAULT}. The last one means the * component's enabled state is based on the original information in * the manifest as found in {@link ComponentInfo}. */ public abstract int getComponentEnabledSetting(ComponentName componentName);
为什么要关闭组件呢?

在用到组件时,有时候我们可能暂时性地不使用组件,但又不想把组件kill掉。比如创建了一个BroadcastReceiver广播接收器,用来想监听第一次开机启动后获得系统的许多相关信息,并保存在文件中,这样以后每次开机启动就不需要再去启动该服务了。也就是说如果不关闭这个BroadcastReceiver,就算不做数据处理,但程序还会一直在后台运行消耗电量和内存,这时候就需要把BroadcastReceiver关闭掉。

如何关闭组件呢?

关闭组件的方法正是上面说的setComponentEnabledSetting()方法。只要创建PackageManager对象和ComponentName对象,并调用PackageManager对象的setComponentEnableSetting方法就可以了。

public void setComponentEnableSetting(ComponentName componentName, int netState, int flags)

componentName:组件名称;

newState:组件新的状态,可以设置三个值,如下:

COMPONENT_ENABLE_STATE_DEFAULT:默认状态,采用在manifest中设置的值。

COMPONENT_ENABLE_STATE_ENABLED:可用状态。

COMPONENT_ENABLE_STATE_DISABLED:不可用状态。

flags:行为标签,值可以是DONT_KILL_APP或0,0表示杀死含有该组件的APP。

复制代码
1
2
3
4
5
6
7
/** * Flag parameter for * {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate * that you don't want to kill the app containing the component. Be careful when you set this * since changing component states can make the containing application's behavior unpredictable.不可预知的 */ public static final int DONT_KILL_APP = 0x00000001;
public int getCompinentEnabledSetting(ComponentName componentName)

获取组件的状态。

实例一:禁止开机启动BroadcastReceiver(可以是第三方Receiver)

复制代码
1
2
3
final ComponentName receiver = new ComponentName(context,需要禁止的receiver); final PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(receiver,PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP);

实例二:隐藏应用图标

如果设置一个app的MainActivity的状态为COMPONENT_ENABLE_STATE_DISABLED,则不会在Launcher的程序图标中发现该app。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
PackageManager packageManager = getPackageManager(); ComponentName componentName = new ComponentName(this, StartActivity.class); int res = packageManager.getComponentEnabledSetting(componentName); if (res == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT || res == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { // 隐藏应用图标 packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); } else { // 显示应用图标 packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP); }

setApplicationEnabledSetting()禁用组件

我们先看下在PackageManager中是如何描述的。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/** * Set the enabled setting for an application * This setting will override any enabled state which may have been set by the application in * its manifest. It also overrides the enabled state set in the manifest for any of the * application's components. It does not override any enabled state set by * {@link #setComponentEnabledSetting} for any of the application's components. * * @param packageName The package name of the application to enable * @param newState The new enabled state for the component. The legal values for this state * are: * {@link #COMPONENT_ENABLED_STATE_ENABLED}, * {@link #COMPONENT_ENABLED_STATE_DISABLED} * and * {@link #COMPONENT_ENABLED_STATE_DEFAULT} * The last one removes the setting, thereby restoring the applications's state to * whatever was set in its manifest (or enabled, by default). * @param flags Optional behavior flags: {@link #DONT_KILL_APP} or 0. */ public abstract void setApplicationEnabledSetting(String packageName, int newState, int flags);

setApplicationEnabledSetting()方法用来设置应用程序的enabled状态,可以停用应用程序中的所有组件(设置为disable状态)。注意与setComponentEnableSetting()方法的区别,后者是设置应用程序的某个组件。

跟踪一下源码,看看两者之间的关系。这里以调用setApplicationEnabledSetting(mContext, pkgname, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);为例进行说明,其中0表示flags。最终通过ApplicationPackageManager调用到PackageManagerService的setApplicationEnabledSetting()方法。

复制代码
1
2
3
4
5
6
7
8
9
@Override public void setApplicationEnabledSetting(String appPackageName, int newState, int flags, int userId, String callingPackage) { if (!sUserManager.exists(userId)) return; if (callingPackage == null) { callingPackage = Integer.toString(Binder.getCallingUid()); } setEnabledSetting(appPackageName, null, newState, flags, userId, callingPackage); }
接着调用到了setEnabledSetting()方法,如下。其实setComponentEnableSetting()方法内部也是调用的setEnabledSetting方法。

复制代码
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
private void setEnabledSetting(final String packageName, String className, int newState, final int flags, int userId, String callingPackage) { if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT || newState == COMPONENT_ENABLED_STATE_ENABLED || newState == COMPONENT_ENABLED_STATE_DISABLED || newState == COMPONENT_ENABLED_STATE_DISABLED_USER || newState == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) { throw new IllegalArgumentException("Invalid new component state: " + newState);//如果netState不是这几个状态,抛出IllegalArgumentException异常 } PackageSetting pkgSetting; final int uid = Binder.getCallingUid(); final int permission = mContext.checkCallingOrSelfPermission( android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);//是否申请了CHANGE_COMPONENT_ENABLED_STATED权限 enforceCrossUserPermission(uid, userId, false, true, "set enabled"); final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); boolean sendNow = false; boolean isApp = (className == null);//调用setApplicationEnabledSetting方法时,className为空,isApp为true。 String componentName = isApp ? packageName : className;//此处component为packageName int packageUid = -1; ArrayList<String> components; // writer synchronized (mPackages) { pkgSetting = mSettings.mPackages.get(packageName);//获取PackageSetting对象 if (pkgSetting == null) {//如果包名对应的PackageSetting对象不存在,则抛出非法参数异常 if (className == null) { throw new IllegalArgumentException( "Unknown package: " + packageName); } throw new IllegalArgumentException( "Unknown component: " + packageName + "/" + className); } // Allow root and verify that userId is not being specified by a different user if (!allowedByPermission && !UserHandle.isSameApp(uid, pkgSetting.appId)) {//异常处理 throw new SecurityException( "Permission Denial: attempt to change component state from pid=" + Binder.getCallingPid() + ", uid=" + uid + ", package uid=" + pkgSetting.appId); } if (className == null) {//setApplicationEnabledSetting()方法的className值为null // We're dealing with an application/package level state change处理应用程序的所有组件状态 if (pkgSetting.getEnabled(userId) == newState) {//返回PackageUserState类的enabled属性 // Nothing to do return;//如果属性没有改变,直接返回 } if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { // Don't care about who enables an app. callingPackage = null;//如果状态是default或enabled,不必关心是谁调用的 } pkgSetting.setEnabled(newState, userId, callingPackage);//设置PackageUserState的enabled和lastDisableAppCaller的属性值 // pkgSetting.pkg.mSetEnabled = newState; } else {//setComponentEnableSetting()方法执行这里 // We're dealing with a component level state change,设置组件级别的状态 // First, verify that this is a valid class name.首先,验证这是一个有效的类名 PackageParser.Package pkg = pkgSetting.pkg; if (pkg == null || !pkg.hasComponentClassName(className)) {//异常处理 if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) { throw new IllegalArgumentException("Component class " + className + " does not exist in " + packageName); } else { Slog.w(TAG, "Failed setComponentEnabledSetting: component class " + className + " does not exist in " + packageName); } } switch (newState) { case COMPONENT_ENABLED_STATE_ENABLED: if (!pkgSetting.enableComponentLPw(className, userId)) { return;//设置PackageUserState对象的disabledComponents和enabledComponents数组; } break; case COMPONENT_ENABLED_STATE_DISABLED: if (!pkgSetting.disableComponentLPw(className, userId)) { return;<span style="font-family: Arial, Helvetica, sans-serif;">//设置PackageUserState对象的disabledComponents和enabledComponents数组</span> } break; case COMPONENT_ENABLED_STATE_DEFAULT: if (!pkgSetting.restoreComponentLPw(className, userId)) { return; } break; default: Slog.e(TAG, "Invalid new component state: " + newState); return; } } mSettings.writePackageRestrictionsLPr(userId);//将/data/system/users/0/package-restrictions-backup.xml文件写入package-restrictions文件 components = mPendingBroadcasts.get(userId, packageName);//获取该包名下的所有组件(包括enabled、disabled状态的组件) final boolean newPackage = components == null; if (newPackage) { components = new ArrayList<String>(); } if (!components.contains(componentName)) { components.add(componentName); } if ((flags&PackageManager.DONT_KILL_APP) == 0) {//setApplicationEnabledSetting()方法中flags为0 sendNow = true; // Purge entry from pending broadcast list if another one exists already // since we are sending one right away. mPendingBroadcasts.remove(userId, packageName);//从预发送广播的组件列表中移除 } else { if (newPackage) { mPendingBroadcasts.put(userId, packageName, components); } if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) { // Schedule a message mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY); } } } long callingId = Binder.clearCallingIdentity(); try { if (sendNow) { packageUid = UserHandle.getUid(userId, pkgSetting.appId); sendPackageChangedBroadcast(packageName, (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid);//发送广播 } } finally { Binder.restoreCallingIdentity(callingId); } }

最后调用sendPackageChangedBroadcast()方法,发送广播。此时,killFlag为false。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void sendPackageChangedBroadcast(String packageName, boolean killFlag, ArrayList<String> componentNames, int packageUid) { if (DEBUG_INSTALL) Log.v(TAG, "Sending package changed: package=" + packageName + " components=" + componentNames); Bundle extras = new Bundle(4); extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0)); String nameList[] = new String[componentNames.size()]; componentNames.toArray(nameList); extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList); extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag);//false extras.putInt(Intent.EXTRA_UID, packageUid); sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null, null, new int[] {UserHandle.getUserId(packageUid)}); }

接下来看下sendPackageBroadcast()方法是如何调用的。此时,action=Intent.ACTION_PACKAGE_CHANGED,targetPkg和finishedReceiver都为null。

复制代码
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
static final void sendPackageBroadcast(String action, String pkg, Bundle extras, String targetPkg, IIntentReceiver finishedReceiver, int[] userIds) { IActivityManager am = ActivityManagerNative.getDefault(); if (am != null) { try { if (userIds == null) { userIds = am.getRunningUserIds(); } for (int id : userIds) { final Intent intent = new Intent(action, pkg != null ? Uri.fromParts("package", pkg, null) : null); if (extras != null) { intent.putExtras(extras); } if (targetPkg != null) { intent.setPackage(targetPkg); } // Modify the UID when posting to other users int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); if (uid > 0 && UserHandle.getUserId(uid) != id) { uid = UserHandle.getUid(id, UserHandle.getAppId(uid)); intent.putExtra(Intent.EXTRA_UID, uid); } intent.putExtra(Intent.EXTRA_USER_HANDLE, id); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); if (DEBUG_BROADCASTS) { RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); Slog.d(TAG, "Sending to user " + id + ": " + intent.toShortString(false, true, false, false) + " " + intent.getExtras(), here); } am.broadcastIntent(null, intent, null, finishedReceiver, 0, null, null, null, android.app.AppOpsManager.OP_NONE, finishedReceiver != null, false, id); } } catch (RemoteException ex) { } } }
调用ActivityManager发送广播。

复制代码
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
case Intent.ACTION_PACKAGE_CHANGED: Uri data = intent.getData(); String ssp; if (data != null && (ssp=data.getSchemeSpecificPart()) != null) { boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);//false boolean fullUninstall = removed && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);//false if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {//true forceStopPackageLocked(ssp, UserHandle.getAppId( intent.getIntExtra(Intent.EXTRA_UID, -1)), false, true, true, false, fullUninstall, userId, removed ? "pkg removed" : "pkg changed");调用forceStopPackaageLocked()方法 } if (removed) { sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED, new String[] {ssp}, userId); if (fullUninstall) { mAppOpsService.packageRemoved( intent.getIntExtra(Intent.EXTRA_UID, -1), ssp); // Remove all permissions granted from/to this package removeUriPermissionsForPackageLocked(ssp, userId, true); removeTasksByPackageNameLocked(ssp, userId); if (userId == UserHandle.USER_OWNER) { mTaskPersister.removeFromPackageCache(ssp); } } } else { removeTasksByRemovedPackageComponentsLocked(ssp, userId); if (userId == UserHandle.USER_OWNER) { mTaskPersister.addOtherDeviceTasksToRecentsLocked(ssp); } } } break; } break;
此时调用forceStopPackageLocked()方法用来停止组件运行。


最后

以上就是羞涩裙子最近收集整理的关于PackageManagerService的常用方法的全部内容,更多相关PackageManagerService内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(75)

评论列表共有 0 条评论

立即
投稿
返回
顶部