多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
1. 客户端查询 客户端通过ApplicationPackageManager输出的queryIntentActivities函数向PKMS发起一次查询请求,代码如下: **ApplicationPackageManager.java::queryIntentActivities** ~~~ public List<ResolveInfo>queryIntentActivities(Intent intent, int flags) { try { return mPM.queryIntentActivities( intent,//下面这句话很重要 intent.resolveTypeIfNeeded(mContext.getContentResolver()), flags); }...... } ~~~ 如果Intent的Data包含一个URI,那么就需要查询该URI的提供者(即ContentProvider)以取得该数据的数据类型。读者可自行阅读resolveTypeIfNeeded函数的代码。 另外,flags参数目前有3个可选值,分别是MATCH_DEFAULT_ONLY、GET_INTENT_FILTERS和GET_RESOLVED_FILTER。详细信息读者可查询SDK相关文档。 下面来看PKMS对匹配查询的处理。 2. queryIntentActivities分析 该函数代码如下: **PacakgeManagerService.java::queryIntentActivities** ~~~ public List<ResolveInfo>queryIntentActivities(Intent intent, String resolvedType, int flags) { final ComponentName comp = intent.getComponent(); if(comp != null) { //Explicit的Intents,直接根据component得到对应的ActivityInfo final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1); final ActivityInfo ai = getActivityInfo(comp, flags); if (ai != null) { final ResolveInfo ri = new ResolveInfo(); //ResovlerInfo的activityInfo指向查询得到的ActivityInfo ri.activityInfo = ai; list.add(ri); } return list; } synchronized (mPackages) { final String pkgName = intent.getPackage(); if (pkgName == null) { //Implicit Intents,我们重点分析此中情况 return mActivities.queryIntent(intent, resolvedType, flags); } //Intent指明了PackageName,比Explicit Intents情况差一点 final PackageParser.Package pkg = mPackages.get(pkgName); if (pkg != null) { //其实是从该Package包含的Activities中进行匹配查询 return mActivities.queryIntentForPackage(intent, resolvedType, flags, pkg.activities); } return new ArrayList<ResolveInfo>(); } } ~~~ 上边代码分三种情况: - 如果Intent指明了Component,则直接查询该Component对应的ActivityInfo。 - 如果Intent指明了Package名,则根据Package名找到该Package,然后再从该Package包含的Activities中进行匹配查询。 - 如果上面条件都不满足,则需要在全系统范围内进行匹配查询,这就是queryIntent的工作。 queryIntent函数的代码如下: ~~~ public List<ResolveInfo> queryIntent(Intentintent, String resolvedType, intflags) { mFlags =flags; //调用基类的queryIntent函数 returnsuper.queryIntent(intent, resolvedType, (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0); } ~~~ **IntentResolver.java::queryIntent** ~~~ public List<R> queryIntent(Intent intent,String resolvedType, booleandefaultOnly) { Stringscheme = intent.getScheme(); ArrayList<R> finalList = new ArrayList<R>(); //最多有四轮匹配工作要做 ArrayList<F> firstTypeCut = null; ArrayList<F> secondTypeCut = null; ArrayList<F> thirdTypeCut = null; ArrayList<F> schemeCut = null; //下面将设置各轮校验者 if(resolvedType != null) { intslashpos = resolvedType.indexOf('/'); if(slashpos > 0) { final String baseType = resolvedType.substring(0, slashpos); if (!baseType.equals("*")) { if (resolvedType.length() != slashpos+2 || resolvedType.charAt(slashpos+1) != '*') { firstTypeCut =mTypeToFilter.get(resolvedType); secondTypeCut =mWildTypeToFilter.get(baseType); }......//略去一部分内容 } } if(scheme != null) { schemeCut = mSchemeToFilter.get(scheme); } if(resolvedType == null && scheme == null && intent.getAction()!= null) { //看来action的filter优先级最低 firstTypeCut = mActionToFilter.get(intent.getAction()); } //FastImmutableArraySet是一种特殊的数据结构,用于保存该Intent中携带的 //Category相关的信息。 FastImmutableArraySet<String>categories = getFastIntentCategories(intent); if(firstTypeCut != null) { //匹配查询,第一轮过关斩将 buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, firstTypeCut,finalList); } if(secondTypeCut != null) { buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, secondTypeCut, finalList); } if(thirdTypeCut != null) { buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, thirdTypeCut, finalList); } if(schemeCut != null) { //生成符合schemeCut条件的finalList buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, schemeCut, finalList); } //将匹配结果按Priority的大小排序 sortResults(finalList); returnfinalList; } ~~~ 在以上代码中设置了最多四轮匹配关卡,然后逐一执行匹配工作。具体的匹配代码由buildResolveList完成,无非是一项查找工作而已。此处就不再深究细节了,建议读者在研究代码时以目的为导向,不宜深究其中的数据结构。