Android Intent source code learning

Source: Internet
Author: User

Android Intent source code learning
Preface this article mainly introduces Android Intent and analyzes the Intent query and matching process from the Android source code perspective.
Intent introduces the meaning of Intent in Chinese as "Intent", and Intent is a very abstract concept. So how to instantiate Intent in Android coding design? Therefore, the Android system explicitly specifies an Intent which can be measured by two attributes. Main attributes: including Action and Data. Action indicates the Action Intent expressed by the Intent, and Data indicates the Data operated by the Action. Secondary attributes: include Category, Type, Component, and Extras. Here, Category indicates the Category, Type indicates the MIME Type of the data, and Component can be used to specify the responder of a specific Intent (for example, specifying the intent as a class under a certain package ), extras is used to carry other information. Android has two types of Intent: Intent (Explicit Intent) and Implicit Intent (Implicit Intent ). Explicit Intent: This kind of Intent clearly specifies which Component to look. In the code, you can use setClassName or setComponent to lock the target object. Implicit Intent: This kind of Intent does not specify which Component to start, but sets Action, Data, and Category for the system to filter out the appropriate Component. Next, we will write two sample codes to introduce the 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 code, it is found that setClassName also implements the Explicit it Intent using ComponentName. The source code is as follows:
    public Intent setClassName(String packageName, String className) {        mComponent = new ComponentName(packageName, className);        return this;    }
Then, an Implict Intent sample code is provided. I use an Activity to mark some Intent filters as an example, and then write an Intent to start it.
                    
                                 
              
  
         
In AndroidManifest. xml of the current application, intent-filter is added to the SendIntentType class. The action name is "justtest" and the category name is "justcategory ". The code for starting this Activity is as follows:
private void startImplictIntent() {Intent intent = new Intent();intent.setAction(justaction);intent.addCategory(justcategory);startActivity(intent);}
When the system matches the Implict Intent, the three items listed in the Intent Filter are used as the reference standard. The specific steps are as follows: First, match the Action of the IntentFilter, if the action set by Intent does not meet the Action of IntentFilter, the match fails. If IntentFilter does not set Action or the set Action is the same, the match is successful. Check the Category of IntentFilter. The matching method is the same as that of Action. The only exception is that the Category is CATEGORY_DEFAULT. Finally, check Data.
The management of Activityi information can be seen from the above analysis that in the process of matching Intent, the system must first manage all Activity information in the current system. Activity information is collected and managed by PackageManagerService during APK scanning. The source code is as follows:
// Process the activity information of the package N = pkg. activities. size (); 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 );}
The above code has two important data structures, as shown in. Combined with the code and data structure, we can see that mAcitivitys is of the ActivityIntentResolver type and is a member variable of PKMS. It is used to save all Activity-related information in the system. This data structure also contains a mActivities variable, which uses ComponentName as the key to save the PackageParser. Activity object. All information related to Acitivity (including the IntentFilter tag declared in XML) parsed from APK is saved by PackageParser. Activity. In the previous code, the addActivity function is called to complete the public sector of private information. The code of the addActivity function is as follows:
Public final void addActivity (PackageParser. activity a, String type) {final boolean systemApp = isSystemApp (a.info. applicationInfo); mActivities. put (. getComponentName (), a); final int NI =. intents. size (); for (int j = 0; j <NI; j ++) {PackageParser. activityIntentInfo intent =. intents. get (j); if (! SystemApp & intent. getPriority ()> 0 & activity. equals (type) {// the priority of the non-system APK must be 0intent. setPriority (0) ;}addfilter (intent );}}
Next, let's take a look at the addFilter function. The function source code is as follows:
Public void addFilter (F f) {// mFilters stores 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 :);}}
Here there are several data structures, which are similar to ArrayMap. Where F is the template parameter. MSchemeToFilter: used to save the IntentFilter information related to scheme in the uri. MActionToFilter: used to save the IntentFilter information that only sets the Action condition. MTypedActionToFilter: used to save the IntentFilter information of the MIME type that both sets Action and Data. After learning about the approximate data structure, let's take a look at the register_intent_filter function implementation:
    private final int register_intent_filter(F filter, Iterator
  
    i,            ArrayMap
   
     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;    }
   
  
Then there is an addFilter function, which is obviously a function overload. Let's take a look at the implementation of this addFilter:
    private final void addFilter(ArrayMap
  
    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, it determines the capacity. If it is not enough, it will be resized. If it is enough, it will find the location to insert. If the F array does not exist, create an array with a capacity of 2 and assign element 0 to the filter.
The Intent match query and analysis client initiates a query request to PackageManagerService through the queryIntentActivities function output by ApplicationPackageManager. The Code is as follows:
    @Override    public List
  
    queryIntentActivities(Intent intent,                                                   int flags) {        return queryIntentActivitiesAsUser(intent, flags, mContext.getUserId());    }    /** @hide Same as above but for a specific user */    @Override    public List
   
     queryIntentActivitiesAsUser(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. The function code is as follows:
Public List
  
   
QueryIntentActivities (Intent intent, String resolvedType, int flags, int userId) {if (! SUserManager. exists (userId) return Collections. emptyList (); enforcecrosuserpermission (Binder. getCallingUid (), userId, false, query intent activities); ComponentName comp = intent. getComponent (); if (comp = null) {if (intent. getSelector ()! = Null) {intent = intent. getSelector (); comp = intent. getComponent () ;}} if (comp! = Null) {// the Intent of the Explicit, and obtain the corresponding ActivityInfofinal List based on the component.
   
    
List = new ArrayList
    
     
(1); final ActivityInfo ai = getActivityInfo (comp, flags, userId); if (ai! = Null) {final ResolveInfo ri = new ResolveInfo (); ri. activityInfo = ai; list. add (ri);} return list;} // readersynchronized (mPackages) {final String pkgName = intent. getPackage (); if (pkgName = null) {// Implicit Intentreturn mActivities. queryIntent (intent, resolvedType, flags, userId);} final PackageParser. package pkg = mPackages. get (pkgName); if (pkg! = Null) {// specifies the package name's Intentreturn mActivities. queryIntentForPackage (intent, resolvedType, flags, pkg. activities, userId);} return new ArrayList
     
      
();}}
     
    
   
  
As you can see, the implementation of Explicit Intent is relatively simple. Let's focus on the implementation of Implict Intent. Implicit Intent calls the queryIntent method. Let's take a look at the implementation code of queryIntent:
public List
  
    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 trace the queryIntent method of IntentResolver. java. The source code is as follows:
Public List
  
   
QueryIntent (Intent intent, String resolvedType, boolean defaultOnly, int userId) {String scheme = intent. getScheme (); ArrayList
   
    
FinalList = new ArrayList
    
     
(); // Up to four matching operations F [] firstTypeCut = null; F [] secondTypeCut = null; F [] thirdTypeCut = null; F [] schemeCut = null; // If the intent primary des 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); 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 only need to do this // if the intent type was not already */*. thirdTypeCut = mWildTypeToFilter. get (*);} 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 the intent identifier des 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 dire Ctly matching each resulting 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 will only be looking for matches against empty // data. if (resolvedType = null & scheme = null & intent. getAction ()! = Null) {firstTypeCut = mActionToFilter. get (intent. getAction ();} FastImmutableArraySet
     
      
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); return finalList ;}
     
    
   
  
The specific query matching process is completed by the buildResolveList function. I will not post the code for the matching Implementation of the query. You can just query it by yourself.

 

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.