欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

深入分析Intent匹配查詢 - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開發(fā)/軟件開發(fā)

知識

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運(yùn)營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!

您當(dāng)前位置>首頁 » 新聞資訊 » 技術(shù)分享 >

深入分析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


回念3NscanPackageLI中,經(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)案例查看更多