> 文档中心 > Android源码分析-PackageManagerService(PMS)源码分析(三)- queryIntentActivities函数来查找activity

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的解析