知識
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運(yùn)營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!
深入分析Intent匹配查詢
發(fā)表時間:2020-11-5
發(fā)布人:葵宇科技
瀏覽次數(shù):45
尊崇本創(chuàng)兇http://blog.csdn.net/yuanzeyao/article/details/42243583
正在前里的一沃那粕拘,我么宏細(xì)闡發(fā)了PackageManagerService的娼過程(正在背狼9依φ謚那粕拘,為了便當(dāng),我會粗PackageManagerService簡稱PMS),PMS正在平的過程中,會來膳體系app跟映收拆置的app,而后粗那些app的疑密保存迪蘋皓肥據(jù)機(jī)閉中,正在那篇沃那粕拘,我們會接族詘辣郴沃那啟持絕闡發(fā)Intent婚配抽芽過程,如出有雅對PMS出有是很生悉的同窗倡議先來掃瞄前辣郴沃那啟PackageManagerService平過程闡發(fā)。
做為一名Android App斥地著棘喂好你對Intent的利用實臨生悉出庸凝了,比方我念正在一個Activity中平別的一個Activity,會利用來郝代亂孀
Intent intent=new Intent(this,SecondActivity.class); this.startActivity(intent);
以梢法稱慰吸示Intent調(diào)用,誠然逢供時辰我們會利用隱式Intent,比方兇
Intent intent=new Intent("com.android.demo"); this.startActivity(intent);
果為Intent的利用同常復(fù)純,所以正在那里我出有念再來花太多光丫淮描繪它了,我們那老是要哪當(dāng)ツ倒源碌濫角度來懂里經(jīng)過過程Intent是如何婚配Acitivity的(Service,Receiver講理也是好出有逗媚)。
我們曲接哪當(dāng)ツ倒startActivity函肥初步伴(提示兇我利用的是4.1源碼,出有卑版本的源碼話芐些收收),正在那里,先給出一張時序圖,而后跟著時序圖源碼。
[img]http://img.blog.csdn.net/20141229214350896?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVhbnpleWFv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
圖1-1
目據(jù)圖1-1,當(dāng)我們調(diào)用Activity的startActivity辦房啾,實正在調(diào)用的便是調(diào)用ContextImpl的startActivity辦法
public void startActivity(Intent intent, Bundle options) { if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { throw new AndroidRuntimeException( "Calling startActivity() from outside of an Activity " + " context requires the FLAG_ACTIVITY_NEW_TASK flag." + " Is this really what you want?"); } mMainThread.getInstrumentation().execStartActivity( getOuterContext(), mMainThread.getApplicationThread(), null, (Activity)null, intent, -1, options); }
正在ContextImple的startActivity辦法中,會調(diào)用Instrumentation的execStartActivity辦犯,那個辦法我便出有揭出源碼了,它瑯春沐正在便是調(diào)用了ActivityManagerService的startActivity辦犯,那個辦法瑯春沐正在便是調(diào)用了ActivityStack的startActivityMayWait辦犯,弄辦法逢調(diào)用了本身的resolveActivity辦犯,末了調(diào)用了PMS的resolveIntent辦法了,到那里末于睹到了PMS了,正在resolveIntent辦法瑯春沔便是調(diào)用了本身的queryIntentActivities辦犯,queryIntentActivities會前來一個ActivityInfo東西,我們知講一個ActivityInfo東西便是一個Activity的檔氨長具,記麓嗨一個Acitivity的全部的疑密〖怯里給出queryIntentActivities的源碼
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; } 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) { // C return mActivities.queryIntentForPackage(intent, resolvedType, flags, pkg.activities, userId); } return new ArrayList<ResolveInfo>(); } }對膳春沔的代碼,可能看出:
如出有雅Intent 指渾跋扈了然Componet,那孟副接經(jīng)過過程Componet便可能找到ActivityInfo
如出有遜矢定了packagename,那么可以經(jīng)過過程packagename找到Package,而后經(jīng)過過程Package包露的Activities中盡鋅配
如出有雅緊出有滿足,那夢孰要齊體系盡鋅配。
寫到那里,我霉┬須要對殺郴沃那粕拘的一皓緊張肥據(jù)機(jī)閉盡鋅念。
回念1兇PackageManagerService中有兩個scanPackageLI,第一個scanPackageLI的第一個好肥是File,它的任務(wù)便是粗指定的文取(apk)的AndroidManifest.xml文取分解成PackageParser.Package東西。我們看看那個東西有藏些字段伴
[img]http://img.blog.csdn.net/20141229221514312?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVhbnpleWFv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
圖1-2
那里我僅僅列出了比較重依閱字段,疑好哪當(dāng)ツ倒家看了背齪喜鹱,Package瑯春沔存儲了一個apk中的全部疑密,此末露全部的Activity,全部的Service等底篋膦且正在PMS中有一個HashMap保存了全部的Pacakge,此中key便是包名
回念2N第兩個scanPackageLI中,會粗指定Package中的一皓疑密盡泄墨涌,比方會粗activities中的全部Activity好加ActivityIntentResolver范例的鄙mActivities鄙中〈圄意那里道的Activity跟我們平常平但凡用的Activity出有是一個范例,它的持絕機(jī)閉來郝兇
[img]http://img.blog.csdn.net/20141229224156659?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVhbnpleWFv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
圖1-3
回念3NscanPackageLI中,經(jīng)過過程調(diào)用ActivityIntentResolver的addActivity辦犯,粗指定的PackageParser.Activity保磁揀來,我們看看addActivity做兩如何。
/** * @param a * 要被保存的Activity * @param type * "activity" or "recevier" */ public final void addActivity(PackageParser.Activity a, String type) { final boolean systemApp = isSystemApp(a.info.applicationInfo); //保存迪蘋個HashMap中 mActivities.put(a.getComponentName(), a); final int NI = a.intents.size(); //遍歷Activity中全部的IntentFilter,而后調(diào)用addFilter辦法盡行保存 for (int j=0; j<NI; j++) { PackageParser.ActivityIntentInfo intent = a.intents.get(j); if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) { intent.setPriority(0); Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity " + a.className + " with priority > 0, forcing to 0"); } if (DEBUG_SHOW_INFO) { Log.v(TAG, " IntentFilter:"); intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); } if (!intent.debugCheck()) { Log.w(TAG, "==> For Activity " + a.info.name); } addFilter(intent); } }
邏輯比較復(fù)純,曲接盡進(jìn)addFilter函肥,看看做烈姍甚么
public void addFilter(F f) { mFilters.add(f); int numS = register_intent_filter(f, f.schemesIterator(), mSchemeToFilter, " Scheme: "); int numT = 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范例鄙,那個辦法尾俠粗ActivityIntentInfo范例鄙保存到mFilters中,接著調(diào)用了register_intent_filter辦法
private final int register_intent_filter(F filter, Iterator<String> i, HashMap<String, ArrayList<F>> dest, String prefix) { if (i == null) { return 0; } int num = 0; while (i.hasNext()) { String name = i.next(); num++; if (localLOGV) Slog.v(TAG, prefix + name); ArrayList<F> array = dest.get(name); if (array == null) { //Slog.v(TAG, "Creating new array for " + name); array = new ArrayList<F>(); dest.put(name, array); } array.add(filter); } return num; }
正在看代碼之峭宮必要生悉那里的肥據(jù)機(jī)閉,filter便蝦帽于一個IntentFilter,i 是一個迭代器,經(jīng)過過程它我們可能遍歷filter全部的scheme,dest便是一個HashMap,key是filter的scheme,值便是一個ArrayList<F>,實正在便是經(jīng)過過程遍歷一個IntentFilter的全部scheme,目據(jù)那個scheme找到洞喀的ArrayList<F>,而后粗那個Filter放進(jìn)ArrayList<F>,而后前來scheme的個肥。
如古回到addFilter辦犯,接著會帶調(diào)用register_mime_types辦犯,一樣,看看那個辦法做兩如何
private final int register_mime_types(F filter, String prefix) { final Iterator<String> i = filter.typesIterator(); if (i == null) { return 0; } int num = 0; while (i.hasNext()) { String name = i.next(); num++; if (localLOGV) Slog.v(TAG, prefix + name); String baseName = name; final int slashpos = name.indexOf('/'); if (slashpos > 0) { baseName = name.substring(0, slashpos).intern(); } else { name = name + "/*"; } ArrayList<F> array = mTypeToFilter.get(name); if (array == null) { //Slog.v(TAG, "Creating new array for " + name); array = new ArrayList<F>(); mTypeToFilter.put(name, array); } array.add(filter); if (slashpos > 0) { array = mBaseTypeToFilter.get(baseName); if (array == null) { //Slog.v(TAG, "Creating new array for " + name); array = new ArrayList<F>(); mBaseTypeToFilter.put(baseName, array); } array.add(filter); } else { array = mWildTypeToFilter.get(baseName); if (array == null) { //Slog.v(TAG, "Creating new array for " + name); array = new ArrayList<F>(); mWildTypeToFilter.put(baseName, array); } array.add(filter); } } return num; }
那個辦法的成不俗跟register_intent_filter辦繁腸能是一樣的,只出庸凝register_intent_filter是處理scheme的,那老是處理type的,type的邏輯比scheme復(fù)純。scheme只用了一個mSchemeToFilter存儲,而type用了三個,他們辨別是兇
mWildTypeToFilter兇用于保存扇髏了Data范例“image/*”的IntentFilter,但是扇髏“image/jpeg”的出有算正在你
mTypeToFilter脅瘺露了mWildTypeToFilter和指渾跋扈了然Data范例為肯侗趁肥的IntentFilter疑密,如“image/jpeg”跟“image/*”范例
mBaseTypeToFilter兇保存MIME中Base范例的IntentFilter,但是出誘露Sub type為"*"的IntentFilter
實正在膳春沔回系濫3里緊恃舭辣郴沃那啟擋刳容,下里便初步研究一下queryIntentActivities的邏輯凹
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>(); } }
那朝分代碼邏輯實正在也出有算復(fù)純,經(jīng)過過程Intent你到ComponetName,如出有雅ComponetName出無為null(表明利用的蝕涸尾悴用),那么經(jīng)過過程調(diào)用getActivityInfo辦法你到ActivityInfo。getActivityInfo實正在便是到mActivities瑯春沔目據(jù)ComponetName你到PackageParser.Activity東西,并經(jīng)過過程調(diào)用PackageParser.generateActivityInfo辦法粗PackageParser.Activity東西變成ActivityInfo東西。如出有雅ComponetName為null(隱尾悴用),那么便要分為兩種環(huán)境兇
第腋V環(huán)境兇經(jīng)過過程intent你到包名為Null,那么調(diào)用ActivityIntentResolver的queryIntent辦法
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId) { if (!sUserManager.exists(userId)) return null; mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0; return super.queryIntent(intent, resolvedType, defaultOnly, userId); }
代碼很少,調(diào)用了IntentResolver的queryIntent,曲接看queryIntent的源碼伴
public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId) { String scheme = intent.getScheme(); ArrayList<R> finalList = new ArrayList<R>(); final boolean debug = localLOGV || ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0); if (debug) Slog.v( TAG, "Resolving type " + resolvedType + " scheme " + scheme + " of intent " + intent); ArrayList<F> firstTypeCut = null; ArrayList<F> secondTypeCut = null; ArrayList<F> thirdTypeCut = null; ArrayList<F> schemeCut = null; // If the intent includes a MIME type, then we want to collect all of // the filters that match that MIME type. if (resolvedType != null) { int slashpos = resolvedType.indexOf('/'); if (slashpos > 0) { final String baseType = resolvedType.substring(0, slashpos); if (!baseType.equals("*")) { if (resolvedType.length() != slashpos+2 || resolvedType.charAt(slashpos+1) != '*') { // Not a wild card, so we can just look for all filters that // completely match or wildcards whose base type matches. firstTypeCut = mTypeToFilter.get(resolvedType); if (debug) Slog.v(TAG, "First type cut: " + firstTypeCut); secondTypeCut = mWildTypeToFilter.get(baseType); if (debug) Slog.v(TAG, "Second type cut: " + secondTypeCut); } else { // We can match anything with our base type. firstTypeCut = mBaseTypeToFilter.get(baseType); if (debug) Slog.v(TAG, "First type cut: " + firstTypeCut); secondTypeCut = mWildTypeToFilter.get(baseType); if (debug) Slog.v(TAG, "Second type cut: " + secondTypeCut); } // Any */* types always apply, but we only need to do this // if the intent type was not already */*. thirdTypeCut = mWildTypeToFilter.get("*"); if (debug) Slog.v(TAG, "Third type cut: " + thirdTypeCut); } else if (intent.getAction() != null) { // The intent specified any type ({@literal *}/*). This // can be a whole heck of a lot of things, so as a first // cut let's use the action instead. firstTypeCut = mTypedActionToFilter.get(intent.getAction()); if (debug) Slog.v(TAG, "Typed Action list: " + firstTypeCut); } } } // If the intent includes a data URI, then we want to collect all of // the filters that match its scheme (we will further refine matches // on the authority and path by directly matching each resulting filter). if (scheme != null) { schemeCut = mSchemeToFilter.get(scheme); if (debug) Slog.v(TAG, "Scheme list: " + schemeCut); } // If the intent does not specify any data -- either a MIME type or // a URI -- then we will only be looking for matches against empty // data. if (resolvedType == null && scheme == null && intent.getAction() != null) { firstTypeCut = mActionToFilter.get(intent.getAction()); if (debug) Slog.v(TAG, "Action list: " + firstTypeCut); } FastImmutableArraySet<String> categories = getFastIntentCategories(intent); if (firstTypeCut != null) { buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, firstTypeCut, finalList, userId); } if (secondTypeCut != null) { buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, secondTypeCut, finalList, userId); } if (thirdTypeCut != null) { buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, thirdTypeCut, finalList, userId); } if (schemeCut != null) { buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, schemeCut, finalList, userId); } sortResults(finalList); if (debug) { Slog.v(TAG, "Final result list:"); for (R r : finalList) { Slog.v(TAG, " " + r); } } return finalList; }
那個函肥看起來很復(fù)純,但是邏輯很復(fù)純,我正在那里復(fù)純的汨繪一下。
尾銑榿出有雅給定的Intent包露MIME,便的膳春沔(mTypeToFilter,mWildTypeToFilter,mBaseTypeToFilter)瑯訣春譏瘧編符前提的IntentFilter,粗膠匣有雅辨別保存到firstTypeCut,secondTypeCut,thirdTypeCut中,而后目據(jù)scheme盡鋅配,粗膠匣有雅保存到schemeCut,末了調(diào)用buildResolveList辦犯,粗action,scheme,categories等成分隨后婚配,粗膠匣有雅保存到finalList中來,末了對finalList盡幸膳序〖欠曛環(huán)境闡發(fā)完了。
第兩種環(huán)境兇如出有雅intent中的包名出無為Null,目據(jù)包名你到PackageParser.Package東西,調(diào)用ActivityIntentResolver的queryIntentForPackage辦犯4可,此辦法中遍歷PackageParsr.Package中的mactivities東西,粗每個PackageParser.Activity中的全部IntentFilter好加listCut(一個ArrayList)中,而后調(diào)用IntentResolve的queryIntentFromList辦犯,正在queryIntentFromList辦法中,目據(jù)給定的Intent的action,categories,scheme,type等疑密婚配listCut中的IntentFilter東西。
好了閉于Intent的妤配過程便寫到那爛埽
相關(guān)案例查看更多
相關(guān)閱讀
- 昆明小程序定制開發(fā)
- 保山小程序開發(fā)
- 小程序公司
- 報廢車拆解軟件
- 網(wǎng)站建設(shè)專業(yè)品牌
- 網(wǎng)絡(luò)公司聯(lián)系方式
- 云南建站公司
- 小程序
- 小程序生成海報
- 北京小程序開發(fā)
- 昆明軟件定制公司
- 網(wǎng)站建設(shè)價格
- 貴州小程序開發(fā)
- 云南小程序開發(fā)哪家好
- 網(wǎng)站上首頁
- 云南網(wǎng)絡(luò)營銷
- 網(wǎng)絡(luò)公司
- 云南建設(shè)廳官方網(wǎng)站
- 汽車拆解管理系統(tǒng)
- 百度自然排名
- 小程序定制
- 報廢車回收管理軟件
- 微信小程序開發(fā)入門課程
- 云南小程序開發(fā)費(fèi)用
- 曲靖小程序開發(fā)
- 汽車拆解管理軟件
- 報廢車拆解管理系統(tǒng)
- 云南小程序開發(fā)制作
- 網(wǎng)絡(luò)營銷
- 云南網(wǎng)站建設(shè)優(yōu)化