getPackageArchiveInfo得到APK包含的信息
1public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags)
参数archiveFilePath表示一个APK文件的绝对路径。注意返回值PackageInfo,包含Package的所有信息,这些信息都是从AndroidManifest.xml文件中获取的。如果没有成功解析这个包,就返回null。
另外注意第二个参数flags,参考如下:
Use any combination of GET_ACTIVITIES
, GET_GIDS
, GET_CONFIGURATIONS
,GET_INSTRUMENTATION
, GET_PERMISSIONS
, GET_PROVIDERS
, GET_RECEIVERS
, GET_SERVICES
,GET_SIGNATURES
, to modify the data returned.
getPackageAchiveInfo方法源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public 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)
GET_ACTIVITIES
,
GET_GIDS
,
GET_CONFIGURATIONS
,
GET_INSTRUMENTATION
,
GET_PERMISSIONS
,
GET_PROVIDERS
,
GET_RECEIVERS
,
GET_SERVICES
,
GET_SIGNATURES
,
GET_UNINSTALLED_PACKAGES。
getApplicationInfo(String packageName, int flags)
1
2
3
4
5
6
7
8
9
10
11try { //如果设置了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
9public 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
8public 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;
获取组件的状态。
实例一:禁止开机启动BroadcastReceiver(可以是第三方Receiver)
1
2
3final 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
13PackageManager 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); }
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
125private 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
15private 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
41static 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) { } } }
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
38case 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;
最后
以上就是羞涩裙子最近收集整理的关于PackageManagerService的常用方法的全部内容,更多相关PackageManagerService内容请搜索靠谱客的其他文章。
发表评论 取消回复