queryIntentActivities函数的作用:
在Android应用程序开发中,用startActivity可以开启另外一个Activity或应用。startActivity函数必须包含Intent参数,这个参数用来指定具体要打开的组件。
例如,
startActivity(new Intent(this,MyActivity.class));
那么,Android系统是如何进行Intent的匹配的呢?答案主要在PackageManagerService(PMS)的queryIntentActivities函数中。本节来分析queryIntentActivities相关源代码。
queryIntentActivities源码分析:
在启动一个activity时,会通过调用queryIntentActivities来获取activity,例如:
List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags
| PackageManager.GET_RESOLVED_FILTER, userId);
相关的数据结构:
ActivityInfo mResolveActivity: 保存Activity相关的信息。例如启动模式,权限......等; ApplicationInfo mAndroidApplication: 应用程序信息; final ResolveInfo mResolveInfo = new ResolveInfo(); ComponentName mResolveComponentName: Component组件 PackageParser.Package mPlatformPackage; package
queryIntentActivities函数的源代码:
queryIntentActivities函数的代码位置:
frameworks/base/services/java/com/android/server/pm/
源代码:
@Override
public List<ResolveInfo> queryIntentActivities(Intent intent,
String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
intent = intent.getSelector();
comp = intent.getComponent();
}
}
if (comp != null) {
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
final ActivityInfo ai = getActivityInfo(comp, flags, userId);
if (ai != null) {
final ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
list.add(ri);
}
return list;
}
// reader
synchronized (mPackages) {
final String pkgName = intent.getPackage();
if (pkgName == null) {
return mActivities.queryIntent(intent, resolvedType, flags, userId);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
return mActivities.queryIntentForPackage(intent, resolvedType, flags,
pkg.activities, userId);
}
return new ArrayList<ResolveInfo>();
}
}
分析:
1. 获取Component组件实例;
2. comp!=null: 即intent精确匹配,这种情况下,会跳转到具体的activity;
3. 通过调用getActivityInfo来获取ActivityInfo实例;
在getActivityInfo中,再通过调用mActivitys数据成员来获取component对应的activity,代码如下:
@Override public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) { if (!sUserManager.exists(userId)) return null; synchronized (mPackages) { PackageParser.Activity a = mActivities.mActivities.get(component); if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a); if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) { PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); if (ps == null) return null; return PackageParser.generateActivityInfo(a, flags, ps.getStopped(userId), ps.getEnabled(userId), userId); } if (mResolveComponentName.equals(component)) { return mResolveActivity; } } return null; }
另外,还可以参考如下博文:
Android源码分析-PackageManagerService(PMS)源码分析(一)PMS的初始化以及PackageManager的使用
Android源码分析-PackageManagerService(PMS)源码分析(二)- 利用PackageParser进行package的解析