Android源码分析-PackageManagerService(PMS)源码分析(三)- queryIntentActivities函数来查找activity
嘿,各位Android开发的小伙伴们,今天咱们来聊聊queryIntentActivities这个函数!你要是用过startActivity,肯定知道它需要个Intent来指定要打开的组件。那系统是怎么匹配这个Intent的呢?这就是queryIntentActivities的活儿了。
首先,问题来了:queryIntentActivities到底干了啥?简单说,它就是个“媒婆”,负责在茫茫应用海中,帮你找到那个最适合的Activity。这个过程就像你去相亲,Intent是你的择偶标准,queryIntentActivities就是婚介所,专门帮你筛选出符合你条件的对象。
那么,它具体是怎么筛选的呢?源码告诉我们,它会先看看Intent里有没有明确指定的组件(ComponentName)。如果有,那就直接锁定目标,毕竟“指名道姓”是最省事的。如果没有,它就得去所有已安装的应用中,挨个排查,看看哪个Activity能满足你的需求。
这里有个有趣的点:queryIntentActivities还会调用getActivityInfo来获取Activity的详细信息。这就像你在相亲前,先得拿到对方的“简历”,看看对方的背景、性格、爱好是不是你的菜。
最后,咱们思考一下:为啥要搞得这么复杂?其实,这正是Android系统的灵活之处。它允许你通过Intent打开任何应用中的Activity,而不需要你知道它在哪个包、叫什么名字。这种“松散耦合”的设计,让应用的集成和扩展变得无比轻松。
所以,下次你用startActivity时,别忘了背后默默工作的queryIntentActivities,它可是你打开新世界的“金钥匙”啊!
queryIntentActivities函数的作用:
在Android应用程序开发中,用startActivity可以开启另外一个Activity或应用。startActivity函数必须包含Intent参数,这个参数用来指定具体要打开的组件。
例如,
startActivity(new Intent(this,MyActivity.class));
那么,Android系统是如何进行Intent的匹配的呢?答案主要在PackageManagerService(PMS)的queryIntentActivities函数中。本节来分析queryIntentActivities相关源代码。
queryIntentActivities源码分析:
在启动一个activity时,会通过调用queryIntentActivities来获取activity,例如:
List 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 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 list = new ArrayList(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(); } }
分析:
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的解析