Detailed Android Intent object and Intent filter filter matching process _android

Source: Internet
Author: User

If you are not particularly knowledgeable about intent, see the "How to use intent in Android" for this article, the action, category, and data are described in detail. If you want to learn about the use of common intent in development, see "intent idioms in Android."

The content of this article is a bit long, I hope you can patiently read it out.

In this paper, the intent filter filter, which is used to describe the component in manifest, is uniformly represented by Intent-filter.

I. Overview

We know that intent is divided into two types: explicit intent and implicit intent. If a intent explicitly specifies the full class name of the component to be started, then this intent is an explicit intent, otherwise it is an implicit intent. When we start the component with an explicit intent, Android finds the component to be started directly according to the component name provided by the intent object, and when we start the component with an implicit intent, The Android system cannot directly know the name of the component to launch, and this article is about how the Android system matches the components to be started based on an implicit intent lookup.

When the Android system receives an implicit intent to start an activity (or other component), Android compares intent information with the Intent-filter of registered components based on the following three information, To select the most matching activity (or other component) for the intent:

    • Action in the intent
    • The category in the intent
    • Data in intent (contains the URI and MIME type of data)

That is, the implicit intent object satisfies the information in the <action/>, <category/>, <data/> Three tags in the intent-filter registered in the target component to be started. That means the action test, the category test, and the data test, respectively. Intent-filter information is described in the Android Manife file, as the name suggests, Intent-filter is intent filter, which is used to filter intent.

If an implicit intent object passes the Intent-filter action test, category test, and data test for a component at the same time, the component can be started by the intent object. If an implicit intent object does not pass the Intent-filter test of any component in the system, then no Android system will be able to find the component that the intent object is starting. Let's take a look at how we can pass these three Tests in turn.

Second, the action test

In order to specify the type of intent that can be received and processed, a component can declare in Intent-filter that it supports 0 or more action, for example:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <action android: Name= "com.ispring.action.ACTION_TEST2"/>
 <category android:name= "Android.intent.category.DEFAULT"/ >
</intent-filter>

The intent object can set a unique action value through the Setaction () method. For action testing, you need to do two things:

The intent object sets the action
If the intent object sets the value of the action by calling the Setaction () method, the action test does not pass unless the component's Intent-filter contains an action value in the intent object.
For example, suppose the intent-filter of our activity is as follows:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <action android: Name= "com.ispring.action.ACTION_TEST2"/>
 <category android:name= "Android.intent.category.DEFAULT"/ >
 <data android:scheme= "ispring" android:host= "blog.csdn.net"/>
</intent-filter>

The following intent objects can be tested by the action in the Intent-filter above:

Intent Intent = new Intent ();
Intent.setaction ("com.ispring.action.ACTION_TEST1");
Uri uri = uri.parse ("Ispring://blog.csdn.net/sunqunsunqun");
Intent.setdata (URI);

The intent is able to pass the action test because intent-filter contains the intent action value com.ispring.action.ACTION_TEST1.

The following intent object does not pass the action test above intent-filter:

Intent Intent = new Intent ();
Intent.setaction ("com.ispring.action.ACTION_TEST3");
Uri uri = uri.parse ("Ispring://blog.csdn.net/sunqunsunqun");
Intent.setdata (URI);

The intent is unable to pass the action test because Intent-filter does not contain the intent action value com.ispring.action.ACTION_TEST3.

Intent object does not set action
If the intent object does not call the Setaction () method to set the value of the action, then if Intent-filter has at least one arbitrary action value, the intent object can pass the Intent-filter action test. Conversely, if no action is defined in the Intent-filter, then the intent cannot pass the Intent-filter action test.
For example, suppose our intent object looks like this:

Intent Intent = new Intent ();
Do not set Action value
//intent.setaction ("com.ispring.action.ACTION_TEST1");
Uri uri = uri.parse ("Ispring://blog.csdn.net/sunqunsunqun");
Intent.setdata (URI);

The intent object above can be passed through the following intent-filter:

<intent-filter>
 <action android:name= "Com.csdn.action.ACTION_XXX"/>
 <category android: Name= "Android.intent.category.DEFAULT"/> <data android:scheme= "ispring" android:host= "blog.csdn.net"
 / >
</intent-filter>

The intent object above cannot be passed through the following intent-filter:

<intent-filter>
 <category android:name= "Android.intent.category.DEFAULT"/>
 <data android: Scheme= "ispring" android:host= "blog.csdn.net"/>
</intent-filter>

With a few examples above, presumably everyone has understood the rules of the action test, and the use of the category and data tags above will be described in detail below.

To sum up, there are two points of conclusion:
1. For the intent object to pass the action test, the action declared in Intent-filter cannot be empty and contains the action value in the intent object (if intent action value is not empty).
2. If Intent-filter does not declare any action, then all intent objects (that is, regardless of intent configuration) cannot pass the Intent-filter action test.

Category Test

In order to specify the type of intent that can be received and processed, a component can declare in Intent-filter that it supports 0 or more category, for example:

<intent-filter>
 <category android:name= "Android.intent.category.DEFAULT"/>
 <category Android:name= "Android.intent.category.BROWSABLE"/> ...
</intent-filter>

The intent object has a addcategory () method, which means that a intent object can also associate multiple category. In order for the intent object to pass the Intent-filter category test, all category in the intent object will find the corresponding item in the Intent-filter.
Specifically, it is divided into the following two kinds of situations:

    • Intent object has at least one category

In this case, assuming that the intent object has n category (n >=1), then the intent-filter must include these n category,intent objects in order to pass the category test, otherwise the test cannot pass. If you start an activity with a intent object, there are other restrictions that are described later in detail.
For example, suppose our intent-filter looks like this:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <category Android:name= "Android.intent.category.DEFAULT"/>
 <category android:name= "com.ispring.category.TEST1"/ >
 <category android:name= "com.ispring.category.TEST2"/>
</intent-filter>

The following intent objects can be tested by category

Intent Intent = new Intent ();
Intent.setaction ("com.ispring.action.ACTION_TEST1");
Intent.addcategory ("com.ispring.category.TEST1");
Intent.addcategory ("com.ispring.category.TEST2");

The intent object can be tested by category because Intent-filter contains all category values in the intent pair: com.ispring.category.TEST1 " and com.ispring.category.TEST2.

The following intent objects cannot pass the category test

Intent Intent = new Intent ();
Intent.setaction ("com.ispring.action.ACTION_TEST1");
Intent.addcategory ("com.ispring.category.TEST1");
Intent.addcategory ("com.ispring.category.TEST3");

The intent was unable to pass the category test on the above Intent-filter because Intent-filter contains only intent with com.ispring.category.TEST1 in the category, and does not contain a value of Com.isp The category of the ring.category.TEST3 does not meet the full category of the intent.

    • The intent object does not contain any category

If the intent object does not invoke the Addcategory () method, then the intent object does not contain any category. In this case, if the intent is not used to initiate an activity, then regardless of how the Intent-filter is configured in category, the intent object can always pass Intent-filter test, Even if Intent-filter does not declare any category,intent can pass the category test. It is emphasized here that the intent is not a condition for initiating an activity, which is explained in detail below.

What needs to be specifically stated here is that in all of the examples above, we Have added a value of Android.intent.category.DEFAULT category to the intent-filter of the activity, because when we pass an implicit intent to startactivity () or Startactivityforresult () method, Android automatically adds the category of Android.intent.category.DEFAULT to the implicit intent, so in order for Intent-filter to contain all intent in category, we need to The category is added in the Ntent-filter and requires special attention when used.

Based on a few examples above, we summarize the following:

1. If the intent object does not contain any category and the intent is not used to initiate the activity, then the intent object is always able to pass through all intent-filter tests of category;
2. If the intent object contains category (at least one), then the intent test is passed only when the category declared in Intent-filter contains all category in the Category object.
3. If the activity is allowed to be initiated by an implicit intent, then we must declare the category of the value Android.intent.category.DEFAULT in the intent-filter of the activity.

Data test

To specify the data,intent-filter of the intent that can be received, you need to declare more than 0 <data/> tags, for example:

<intent-filter>
 <data android:mimetype= "video/mpeg" android:scheme= "http" .../> <data
 Android:mimetype= "audio/mpeg" android:scheme= "http" .../>
 ...
</intent-filter>

Each <data/> tag can specify a URI structure and the MIME type of data. A complete URI consists of scheme, host, port, and path, and the structure looks like this:

<scheme>://

Scheme can be either a common protocol in Android or a custom protocol. The common protocols in Android include content protocols, HTTP protocols, file protocols, and so on, and custom protocols can use custom strings.

    • The following is the URI of a content protocol:

Content://com.example.project:200/folder/subfolder/etc
In this URI, scheme is Content,host is Com.example.project,port is 200,path is folder/subfolder/etc.

    • The following is the URI of a custom protocol:

Ispring://blog.csdn.net/sunqunsunqun
In the URI, scheme is Ispring,host is blog.csdn.net, not explicitly set Port,path is Sunqunsunqun.

These attributes that make up the URI are optional in the <data/> tag, but the following dependencies exist:

    • If scheme is not specified, the host parameter is ignored
    • If host is not specified, the port parameter is ignored
    • If scheme and host are not specified, the path parameter is ignored

When we pair the URI parameters in the intent object with the URI format specified in the <data/> tag in intent-filter, we compare only the portions specified by Intent-filter's <data/> Tag, for example:

If scheme is only specified in Intent-filter, then all URIs with that Sheme can match to that intent-filter.
If scheme and authority (authority include both host and port) are specified in Intent-filter and no path is specified, All URIs with the same scheme and authority can be matched to the intent-filter without considering the value of the path.
If scheme, authority, and path are specified in Intent-filter, only URIs with the same scheme, authority, and path can be matched to that intent-filter.
It should be noted that the Intent-filter <data/> Tag, when specifying the value of path, can use wildcard * inside to play a partial-match effect.

The data test needs to compare the URI, MIME type in the intent object with the URI and MIME type specified in the Intent-filter <data/> tag.
We know that a intent-filter can have multiple <data/> tags, intent objects do not need to pass all <data/> Tag tests, in general, our intent object simply through one of the <data/ The intent object passes the data test of the Intent-filter by testing the > tag and satisfying some conditions under certain circumstances.
The rules for contrasting are as follows:

    • Intent object does not contain URI and MIME type

In this case, the data test can only be passed if Intent-filter does not specify any URI and MIME type.
For example, we have the following intent objects:

Intent Intent = new Intent ();
Intent.setaction ("com.ispring.action.ACTION_TEST1");

The intent object above can be tested by the following Intent-filter data:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <category Android:name= "Android.intent.category.DEFAULT"/>
</intent-filter>

The intent object above cannot be tested through the following intent-filter:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <category Android:name= "Android.intent.category.DEFAULT"/>
 <data android:scheme= "ispring"/>
</ Intent-filter>

    • Intent object contains URI but does not contain MIME type

In this case, the data test can only be passed when the URI of the intent object is matched to the URI format in Intent-filter, and Intent-filter does not specify a MIME type. It is to be noted that the case where the intent-filter does not specify a MIME type means that all <data/> tags in intent-filter do not specify a MIME type. It is important to understand that there is no android:mimetype in the whole intent-filter, as you can see in the following few examples.
For example, there are the following intent objects:

Intent Intent = new Intent ();
Intent.setaction ("com.ispring.action.ACTION_TEST1");
Uri uri = uri.parse ("Ispring://blog.csdn.net/sunqunsunqun");
Intent.setdata (URI);

The above intent can pass the following intent-filter data test:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <category Android:name= "Android.intent.category.DEFAULT"/>
 <data android:scheme= "ispring" Blog.csdn.net "/>
</intent-filter>

The intent object above can be tested by the following Intent-filter data:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <category Android:name= "Android.intent.category.DEFAULT"/>
 <data android:scheme= "ispring" Blog.csdn.net "/> <data android:scheme= Sunqun" android:host= "8080"/>
</intent-filter>

The intent object cannot be tested with scheme-Sunqun <data/> Tag, but can be tested with scheme Ispring's data label, and two < in intent objects and Intent-filter The data/> tag does not specify MIME, so the intent object above can pass the Intent-filter test.

The intent object above cannot be tested through the <data/> tag of the following intent-filter:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <category Android:name= "Android.intent.category.DEFAULT"/>
 <data android:mimetype= "Text/plain" Ispring "android:host=" blog.csdn.net "/>
</intent-filter>

The intent object above cannot be tested by the only <data/> tag in Intent-filter because our intent object does not specify a MIME type, but the <data/> tag above is via Android: Mimetype= "Text/plain" sets the MIME type.

The intent object above cannot pass the following Intent-filter data test:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <category Android:name= "Android.intent.category.DEFAULT"/>
 <data android:scheme= "ispring" Blog.csdn.net "/>
 <data android:mimetype= text/plain"/>
</intent-filter>

The intent object above is unable to pass the data test in this intent-filter because the intent object does not have a MIME type set, but the second data label in Intent-filter passes through Android:mimetype= " Text/plain set the MIME type.

Intent object contains MIME type but does not contain URI
In this case, the data test is passed only if the MIME type in the intent is the same as the MIME type listed in Intent-filter, and Intent-filter does not specify any URI format. It is to be noted that here the Intent-filter does not specify any URI format, which means that all <data/> tags in intent-filter do not specify URIs. It is important to understand that there is no android:scheme, Android:host, Android:port, and android:path throughout the Intent-filter, as you can see in the following few examples.
For example, there are the following intent objects:

Intent Intent = new Intent ();
Intent.setaction ("com.ispring.action.ACTION_TEST1");
Intent.settype ("Text/plain");

The intent object above can be tested by the following Intent-filter data:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <category Android:name= "Android.intent.category.DEFAULT"/>
 <data android:mimetype= "Text/plain"/>
</ Intent-filter>

The intent object above can be tested by the following Intent-filter data:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <category Android:name= "Android.intent.category.DEFAULT"/>
 <data android:mimetype= "image/*"/>
 <data Android:mimetype= "Text/plain"/>
</intent-filter>

The intent object above is not tested by the first data label of the MIME type image/*, but can be tested with the second data label, and intent objects and Intent-filter do not specify any URI format.

The above intent object cannot pass the data test in the following intent-filter:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <category Android:name= "Android.intent.category.DEFAULT"/>
 <data android:mimetype= "Text/plain" Ispring "/>
</intent-filter>

The URI information is not set in the intent object above, but the scheme value in the URI is set in the Intent-filter, so intent cannot pass the Intent-filter data test.

The intent object above cannot pass the data test in the following intent-filter:

<intent-filter>
 <action android:name= "com.ispring.action.ACTION_TEST1"/>
 <category Android:name= "Android.intent.category.DEFAULT"/>
 <data android:mimetype= "Text/plain"/>
 < Data android:scheme= "ispring"/>
</intent-filter>

The intent object above does not specify URI information, but the intent object cannot pass the Intent-filter's data test because the second <data/> tag in the intent-filter above sets the scheme information in the URI.

Intent object contains both URI and MIME types
In this case, to test the URI separately and whether the MIME type test passes, the data test passes only if the URI and the MIME test pass.

For MIME tests: If the MIME type of the intent can match the MIME type value in one of the <data/> tags listed in intent-filter, then the MIME type test is passed.
For the URI test:
There are two different cases, which can be tested by URI if either of the following conditions is true.
If the URI format of the intent can match the URI in one of the <data/> listed in Intent-filter, then the URI test is passed.
If the URI of the intent is a content: protocol or file: protocol, and the URI is not specified in all <data/> tags of the entire intent-filter, then the intent can also pass the URI test. In other words, if a intent-filter only lists MIME types and does not list any URI-related formats, then this intent-filter defaults to support content: protocol or file: protocol.
Here are a few examples of how you can experience yourself.

Assume that the following protocols are ispring for the custom protocol: intent objects:

Intent Intent = new Intent ();
Intent.setaction ("com.ispring.action.ACTION_TEST1");
Uri uri = uri.parse ("Ispring://blog.csdn.net/sunqunsunqun");
String type = "Text/plain";
Intent.setdataandtype (URI, type);

The intent object above can be tested by the following Intent-filter data:

<intent-filter>
  <action android:name= "com.ispring.action.ACTION_TEST1"/>
  <category Android:name= "Android.intent.category.DEFAULT"/>
  <data android:scheme= "ispring" Blog.csdn.net "/>
  <data android:mimetype= text/plain"/>
</intent-filter>

The above intent object is not able to pass the following Intent-filter data test:

<intent-filter>
  <action android:name= "com.ispring.action.ACTION_TEST1"/>
  <category Android:name= "Android.intent.category.DEFAULT"/>
  <data android:scheme= "ispring" Blog.csdn.net "android:port=" 8080 "/>
  <data android:mimetype=" Text/plain "/>
</intent-filter >

The port is not satisfied and the URI test does not pass, causing the data test to fail.

The above intent object is not able to pass the following Intent-filter data test:

<intent-filter>
  <action android:name= "com.ispring.action.ACTION_TEST1"/>
  <category Android:name= "Android.intent.category.DEFAULT"/>
  <data android:scheme= "ispring" Blog.csdn.net "/>
  <data android:mimetype= image/*"/>
</intent-filter>

Android:mimetype is not satisfied, the MIME type test does not pass, causing the data test to fail.

Assume that the following protocol is content: intent object:

Intent Intent = new Intent ();
Intent.setaction ("com.ispring.action.ACTION_TEST1");
Uri uri = uri.parse ("Content://com.ispring.test");
String type = "Text/plain";
Intent.setdataandtype (URI, type);

The above intent object is not able to pass the following Intent-filter data test:

<intent-filter>
  <action android:name= "com.ispring.action.ACTION_TEST1"/>
  <category Android:name= "Android.intent.category.DEFAULT"/>
  <data android:scheme= "ispring"/>
  <data Android:mimetype= "Text/plain"/>
</intent-filter>

The scheme mismatch in the URI caused the data test to fail because the URI test did not pass.

The intent object above can be tested by the following Intent-filter data:

<intent-filter>
  <action android:name= "com.ispring.action.ACTION_TEST1"/>
  <category Android:name= "Android.intent.category.DEFAULT"/>
  <data android:mimetype= "Text/plain"/>
</ Intent-filter>

The intent is used in the content: protocol, and the URI format is not defined throughout the Intent-filter, so the URI test can be passed and the MIME type can find a match, so you can pass the data test.

In summary, we have completed a detailed explanation of the action, category, and data tests in intent, and all of the sample code in this article has been validated in the Android Studio 1.0 Official edition. Thank you for your patience to read Ben Boven, I hope this article on the correct use of intent filter help.

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.