Android Intent Source Learning

Source: Internet
Author: User

This article mainly introduces the Android Intent, and analyzes the Intent query matching process from the angle of Android source code.
Intent introduction Intent's Chinese is "intention" meaning, and intention is a very abstract concept, then in the Android coding design, how to instantiate the intention? So the Android system explicitly specifies that a intent can be measured by two attributes.
    • Main attributes: include action and data. Where action is used to represent the intent of the action expressed by the intent, and data is used to represent what the action is doing.
    • Secondary properties: Includes category, Type, component, and extras. Where category represents a class, type represents the MIME type of the data, component can be used to specify the responder of a particular intent (for example, to specify intent as a class in a package), extras to host other information.
There are two main types of Intent in the Android system, showing Intent (Explicit Intent) and implicit Intent (implicit Intent).
    • Explicit Intent: This type of Intent clearly indicates which component to look for. The target object can be locked in code by setclassname or SetComponent.
    • Implicit Intent: This type of Intent does not explicitly indicate which component to start, but instead sets the action, Data, category to allow the system to filter out the appropriate component.
Next, write two code examples to introduce explicit intent and implict inent. The first is explicit Intent:
private void Startexplicitintentwithcomponent () {Intent Intent = new Intent (); ComponentName component = new ComponentName ("Com.example.photocrop", "com.example.photocrop.MainActivity"); Intent.setcomponent (component); startactivity (intent);} private void Startexplicitintentwithclassname () {Intent Intent = new Intent (); Intent.setclassname (" Com.example.photocrop "," com.example.photocrop.MainActivity "); StartActivity (intent);}
However, from the source to see, found Setclassname is also with the help of ComponentName realized explicit Intent. The source code is as follows:
    Public Intent Setclassname (string packagename, String className) {        mcomponent = new ComponentName (PackageName, ClassName);        return this;    }
Then, give a code example of Implict intent. Here I use an activity to label some intent filter as an example, and then write a intent to start it.
        <activity             android:name= ". Sendintenttype ">            <intent-filter >                <action android:name=" justtest "/>                <category Android:name= "Justcategory"/>            </intent-filter>        </activity>
In the current application of the Androidmanifest.xml, to the Sendintenttype class added intent-filter,action name "Justtest", category named "Justcategory". The code to start the activity is as follows:
private void Startimplictintent () {Intent Intent = new Intent (); Intent.setaction ("justaction"); Intent.addcategory (" Justcategory "); StartActivity (intent);}
In the process of matching implict intent, the system will take the 3 items listed in intent Filter as the reference standard, the following steps are as follows:
    1. Match the action of Intentfilter first, and if the action set by intent does not satisfy the action of Intentfilter, the match fails. If the Intentfilter action is not set or the action set is the same, the match succeeds.
    2. Then check the category of the Intentfilter, the matching method matches the action of the same, the only exception is when the category is Category_default case.
    3. Finally, check data.

Activityi information Management from the above analysis can be seen, the system of matching intent process, the first need to manage the current system of all activity information. The activity information is collected and managed by Packagemanagerservice while scanning the apk. The relevant source code is as follows:
Activity information for processing the package N = Pkg.activities.size (); r = null;for (i = 0; i < N; i++) {Packageparser.activity a = Pkg.acti Vities.get (i); a.info.processname = Fixprocessname (Pkg.applicationInfo.processName, A.info.processname, PKG.APPLICATIONINFO.UID); Mactivities.addactivity (A, "activity");}
In the above code, there are two more important data structures, as shown in. In combination with the code and the data structure, you know:
    • Macitivitys is a activityintentresolver type and is a member variable of pkms that holds all activity-related information in the system. There is also a mactivities variable inside this data structure that holds the Packageparser.activity object with ComponentName as key.
    • All acitivity-related information that is parsed from the APK, including the intentfilter tag declared in the XML, is saved by packageparser.activity.
Calling the Addactivity function in the preceding code completes the public ownership of the private information. The code for the Addactivity function is as follows:
Public final void Addactivity (packageparser.activity A, String type) {Final Boolean Systemapp = Issystemapp (a.info.applic Ationinfo); Mactivities.put (A.getcomponentname (), a), final int NI = A.intents.size (); for (int j = 0; J < NI; J + +) {Packa Geparser.activityintentinfo Intent = A.intents.get (j); if (!systemapp && intent.getpriority () > 0 && " Activity ". Equals (Type)) {///non-system apk must have a priority of 0intent.setpriority (0);} AddFilter (intent);}}
Next look at the addfilter function. The function source code is as follows:
    public void addfilter (f f) {    //Mfilters Save all Intentfilter information        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:" );        }    }
Several data structures appear here, similar to arraymap<string, f[]&gt, where F is the template parameter.
    • Mschemetofilter: Used to hold intentfilter information related to scheme in the URI.
    • Mactiontofilter: Used to save intentfilter information that only sets the action condition.
    • Mtypedactiontofilter: Used to hold intentfilter information that has both the action and data MIME types set.
After understanding the approximate data structure, let's take a look at the function implementation of Register_intent_filter:
    Private final int Register_intent_filter (F filter, iterator<string> I,            arraymap<string, f[]> dest, String prefix) {        if (i = = null) {            return 0;        }        int num = 0;        while (I.hasnext ()) {            String name = I.next ();            num++;            AddFilter (dest, name, filter);        }        return num;    }
And then another addfilter function, obviously a function overload, let's take a look at this addfilter implementation:
    Private final void AddFilter (arraymap<string, f[]> map, String name, F filter) {        f[] array = map.get (name);        if (array = = NULL) {            array = NewArray (2);            Map.put (name,  array);            Array[0] = filter;        } else {            final int N = Array.Length;            int i = N;            while (i > 0 && array[i-1] = = null) {                i--;            }            if (I < N) {                Array[i] = filter;            } else {                f[] Newa = NewArray ((n*3)/2);                System.arraycopy (array, 0, Newa, 0, N);                Newa[n] = filter;                Map.put (name, Newa);}}}    
In fact, the code is still very simple, if the F array exists, then determine the capacity, not enough to expand, enough words to find the location to insert. If the F array does not exist, create an array with a capacity of 2 and assign the number No. 0 element to the filter.
Intent matching query Analysis     Client initiates a query request to packagemanagerservice through the queryintentactivities function of the Applicationpackagemanager output , the code is as follows:
    @Override public    list<resolveinfo> queryintentactivities (Intent Intent,                                                   int flags) {        return Queryintentactivitiesasuser (Intent, Flags, Mcontext.getuserid ());    }    /** @hide same as above but a specific user */    @Override public    list<resolveinfo> Queryintentactivitiesa Suser (Intent Intent,                                                   int flags, int userId) {        try {            return mpm.queryintentactivities (                Intent,                Intent.resolvetypeifneeded (Mcontext.getcontentresolver ()),                flags,                userId),        catch ( RemoteException e) {            throw new RuntimeException ("Package manager has died", e);        }    }
As you can see, the real implementation of Queryintentactivities is in Packagemanagerservice.java, where the function code is as follows:
Public list<resolveinfo> queryintentactivities (Intent Intent, String resolvedtype, int flags, int userId) {if (!sus Ermanager.exists (userId)) return collections.emptylist (); Enforcecrossuserpermission (Binder.getcallinguid (), UserId, False, "query intent Activities"); ComponentName comp = intent.getcomponent (); if (comp = null) {if (intent.getselector () = null) {intent = Intent.getselect or (); comp = Intent.getcomponent ();}} if (comp = null) {//explicit intent, directly according to component get corresponding activityinfofinal list<resolveinfo> List = new arraylist& Lt Resolveinfo> (1); final Activityinfo ai = getactivityinfo (comp, flags, userId); if (ai! = null) {final ResolveInfo ri = NE W ResolveInfo (); ri.activityinfo = Ai;list.add (RI);} return list;} Readersynchronized (mpackages) {final String pkgname = Intent.getpackage (); if (pkgname = = null) {//implicit Intentretu RN Mactivities.queryintent (Intent, Resolvedtype, flags, userId);} Final Packageparser.package pkg = Mpackages.get (pkgname); if (pkg! = null) {// Intentreturn Mactivities.queryintentforpackage (Intent, Resolvedtype, flags, pkg.activities, USERID) specifying the package name;} return new arraylist<resolveinfo> ();}}
As you can see, the implementation of Explicit intent is relatively simple, and we focus on implict intent implementation. Implicit intent called the Queryintent method, let's take a look at the implementation code of Queryintent:
Public list<resolveinfo> queryintent (Intent Intent, String resolvedtype, int flags, int userId) {if (!susermanager. Exists (USERID)) return null;mflags = Flags;return super.queryintent (Intent, Resolvedtype, (Flags & packagemanager.match_default_only)! = 0, userId);}
Continue to follow the Intentresolver.java queryintent method, the source code is as follows:
    Public list<r> queryintent (Intent Intent, String resolvedtype, boolean defaultonly, int userId) {        String scheme = Intent.getscheme ();        arraylist<r> finallist = new arraylist<r> ();        Up to 4 rounds of matching operations f[] firsttypecut = null;        f[] secondtypecut = null;        f[] thirdtypecut = null;        f[] schemecut = null;        If The intent includes a MIME type, then we want to collect all of//the filters this 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 | | reso                        Lvedtype.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);                    Secondtypecut = Mwildtypetofilter.get (BaseType);                        } else {//We can match anything with our base type.                        Firsttypecut = Mbasetypetofilter.get (BaseType);                    Secondtypecut = Mwildtypetofilter.get (BaseType); }//Any */* types always apply, but we are only need to does this/if the intent type W                    As not already */*.                Thirdtypecut = Mwildtypetofilter.get ("*");  } else if (intent.getaction () = null) {//The intent specified any type ({@literal *}/*). This//can is a whole heck of a lot of things, so as a first//cut let's use the A                    Ction instead.                Firsttypecut = Mtypedactiontofilter.get (Intent.getaction ());}}}//If The intent includes a data URI, then we want to collect all of//the filters That match it scheme (we'll further refine matches//on the authority and path by directly matching each result        ing filter).        if (scheme! = null) {Schemecut = Mschemetofilter.get (scheme); }//If The intent does not specify any data--either a MIME type or//a URI--then we'll only be Looki        ng for matches against empty//data. if (Resolvedtype = = NULL && scheme = = null && intent.getaction ()! = null) {Firsttypecut = MAct        Iontofilter.get (Intent.getaction ());        } fastimmutablearrayset<string> categories = Getfastintentcategories (intent); if (firsttypecut! = null) {Buildresolvelist (Intent, Categories, debug, defaultonly, resolve        DType, 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, R        Esolvedtype, Scheme, Schemecut, Finallist, userId);        } sortresults (Finallist);    return finallist; }
The specific query matching process is done by the Buildresolvelist function. The matching implementation of the query I will not post code, we have to check their own to see just fine.

References [1] deep understanding of Android: Volume Two

Android Intent Source Learning

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.