企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
前面在介绍PKMS扫描APK时提到,PKMS将解析得到的Package私有的Activity信息加入到自己的数据结构mActivities中保存。先来回顾一下代码: **PacakgeManagerService.java::scanPackageLI函数** ~~~ ......//此时APK文件已经解析完成 N =pkg.activities.size();//取出该APK中包含的Activities信息 r =null; for (i=0; i<N; i++) { PackageParser.Activity a = pkg.activities.get(i); a.info.processName = fixProcessName(pkg.applicationInfo.processName, a.info.processName,pkg.applicationInfo.uid); mActivities.addActivity(a,"activity");//①加到mActivities中保存 } ~~~ 上面的代码中有两个比较重要的数据结构,如图4-11所示。 :-: ![](http://img.blog.csdn.net/20150803111124499?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 图4-11 相关数据结构示意图 结合代码,由图4-11可知: - mActivities为ActivityIntentResolver类型,是PKMS的成员变量,用于保存系统中所有与Activity相关的信息。此数据结构内部有一个mActivities变量,它以ComponetName为Key,保存PackageParser.Activity对象 - 从APK中解析得到的所有和Activity相关的信息(包括在XML中声明的IntentFilter标签)都由PacakgeParser.Activity来保存。 前面代码中调用addActivity函数完成了私有信息的公有化。addActivity函数的代码如下: **PacakgeManagerService.java::ActivityIntentResolver.addActivity** ~~~ public final voidaddActivity(PackageParser.Activity a, String type) { finalboolean systemApp = isSystemApp(a.info.applicationInfo); //将Component和Activity保存到mActivities中 mActivities.put(a.getComponentName(), a); finalint NI = a.intents.size(); for(int j=0; j<NI; j++) { //ActivityIntentInfo存储的就是XML中声明的IntentFilter信息 PackageParser.ActivityIntentInfo intent = a.intents.get(j); if(!systemApp && intent.getPriority() > 0 &&"activity".equals(type)) { //非系统APK的priority必须为0。后续分析中将介绍priority的作用 intent.setPriority(0); } addFilter(intent);//接下来将分析这个函数 } } ~~~ 下面来分析addFilter函数,这里涉及较多的复杂数据结构,代码如下: **IntentResolver.java::IntentResolver.addFilter** ~~~ public void addFilter(F f) { ...... mFilters.add(f);//mFilters保存所有IntentFilter信息 //除此之外,为了加快匹配工作的速度,还需要分类保存IntentFilter信息 //下边register_xxx函数的最后一个参数用于打印信息 intnumS = register_intent_filter(f, f.schemesIterator(), mSchemeToFilter," Scheme: "); intnumT = register_mime_types(f, " Type: "); if(numS == 0 && numT == 0) { register_intent_filter(f, f.actionsIterator(), mActionToFilter," Action: "); } if(numT != 0) { register_intent_filter(f, f.actionsIterator(), mTypedActionToFilter, " TypedAction: "); } } ~~~ 正如代码注释中所说,为了加快匹配工作的速度,这里使用了泛型编程并定义了较多的成员变量。下面总结一下这些变量的作用(注意,除mFilters为HashSet<F>类型外,其他成员变量的类型都是`HashMap<String, ArrayList<F>>`,其中F为模板参数)。 - mSchemeToFilter:用于保存URI中与schema相关的IntentFilter信息。 - mActionToFilter:用于保存仅设置Action条件的IntentFilter信息。 - TypedActionToFilter:用于保存既设置了Action又设置了Data的MIME类型的IntentFilter信息。 - mFilters:用于保存所有IntentFilter信息 - mWildTypeToFilter:用于保存设置了Data类型类似“image/*”的IntentFilter,但是设置MIME类型类似“Image/jpeg”的不算在此类。 - mTypeToFilter:除了包含mWildTypeToFilter外,还包含那些指明了Data类型为确定参数的IntentFilter信息,例如“image/*”和”image/jpeg“等都包含在mTypeToFilter中。 - mBaseTypeToFilter:包含MIME中Base 类型的IntentFilter信息,但不包括Sub type为“*”的IntentFilter。 不妨举个例子来说明这些变量的用法。 假设,在XML中声明一个IntentFilter,代码如下: ~~~ <intent-filter android:label="test"> <actionandroid:name="android.intent.action.VIEW" /> dataandroid:mimeType="audio/*" android:scheme="http" </intent-filter> ~~~ 那么: - 在mTypedActionToFilter中能够以“android.intent.action.VIEW”为key找到该IntentFilter。 - 在mWildTypeToFilter和mTypeToFilter中能够以“audio”为key找到该IntentFilter。 - 在mSchemeToFilter中能够以”http“为key找到该IntentFilter。 下面来分析Intent匹配查询工作。