About the Intent

An Intent is a messaging object that can be used to request actions from other application components. Basic use cases mainly include the following three:

  • Start the Activity
  • Start the Service
  • Transfer broadcasting

The type of Intent

  • Explicit Intent

Specify which application can handle the Intent by providing the package name of the target application or the fully qualified component class name.

  • An implicit Intent

Instead of specifying specific components, you declare general operations to be performed, allowing components in other applications to handle them. For example, you need to show the user the location on a map.

With implicit intents, the Android system finds the appropriate component to launch by comparing the content of an Intent to the Intent filter declared in the manifest file of other apps on the device. If there is only one, start directly. If there are more than one, a dialog box is displayed allowing the user to select the application to use.

An Intent filter is an expression in the application manifest that specifies the type of Intent to receive by the component. For example, by declaring an Intent filter for an Activity, you can enable other applications to launch the Activity directly with a specific type of Intent. If the Activity is not declared with any Intent filter, the Activity can only show that the Intent was started.

Note that:

When starting a Service, always display the Intent and do not declare an Intent filter for the Service. Starting services with an implicit Intent is a security risk because it is impossible to determine which services will respond to the Intent and users cannot see which services have been started. As of Android5.0, if you call bindService with an implicit Intent, the system will throw an exception.

Build the Intent

The Intent object carries information that the Android system uses to determine which component to launch, as well as information that the recipient component uses to perform the action correctly. That is to say, there are two main aspects:

  • Component name

The name of the component to start is optional. If not, it is an implicit Intent.

The corresponding field for this property is ComponentName, which can be set with the methods setComponent(), setClass(), setClassName(), or Intent constructor.

  • operation

A string specifying the generic operation to perform.

For broadcast intents, this is an action that has already occurred and is being reported. Actions largely determine what constitutes the rest of the IntEnts, especially what is contained in data and Extra.

You can specify your own operations for use in the application. You can also use predefined actions in the Intent such as:

ACTION_VIEW: Display specific information, such as photos or maps, through some Activity

ACTION_SEND: Also known as shared Intent. Some users can share data with other applications, such as email or social sharing apps.

You can specify actions using setAction() or the Intent constructor.

  • data

A URI that references the data to be manipulated and/or the MIME type of that data.

When creating an Intent, it is often important to specify the data type, or MIME type, in addition to the URI, to help the Android system find the best component to receive the Intent. When the URI type is Content: XXX, the data is stored on the device and controlled by ContentProvider. The system can obtain the data type through the URI.

Only setData through setData(), or setType () if you want to set MIME types. Note that you cannot call setData and setType at the same time, because the two methods will clear each other’s Settings. You should also use setDataAndType() when specifying this.

  • category

A string containing additional information about the type of Intent component that should be handled. You can put any number of category descriptions into an Intent, but most intents do not require categories.

Common categories:

CATEGORY_BROWSABLE: The target Activity allows itself to start through a web browser to display the data referenced by the connection.

CATEGORY_LAUNCHER: This Activity is the initial Activity of the task and is listed in the application launcher of the system.

Specify the category through the method addCategory().

  • Extra

A key-value pair that carries additional information needed to complete the requested action. Store key-value pair information through the Bundle.

Do not use Parcelable or Serializable data in an Intent received by another application. If an application attempts to access data in a Bundle object but does not have access to the package or serialization, RuntimeException will be raised.

The corresponding method is putExtra().

  • mark

You can tell the Android system how to start the Activity and what to do with it once it starts.

The corresponding method is setFlags().

Implicit Intent security verification

With an implicit Intent, you can send a specific action to a processable application to execute. However, it is also possible that no application on the user’s device can handle the Intent, or that the implicit Intent fails to execute due to configuration file limitations or administrator Settings. In this case, the invocation fails and the app that initiated the Intent crashes.

If the Intent returns a result, then at least one application can handle the Intent. In this case, it is safe to use an implicit Intent. If the result is empty, the implicit Intent is not available.

Intent.action_send putExtra(intent.extra_text, textMessage) = intent.action_send putExtra(intent.extra_text, textMessage)type = "text/plain"} // An implicit Intent is used after security verificationif(sendIntent.resolveActivity(packageManager) ! = null) { startActivity(sendIntent) }Copy the code

Enforce application selectors

When an implicit Intent is sent, multiple applications can handle the Intent. In this case, a dialog box is displayed asking the user to select an application to handle the Intent. By default, the user can also set an application as the default processing application for this behavior, so that the next time the trigger is triggered, the selection box will not be displayed, and the application selected by the user will be directly processed.

Of course, Android also provides specific apis that enable an implicit Intent to pop up the application selection box each time, so that the user cannot select the default application for that action.

val sendIntent = Intent(Intent.ACTION_SEND) ... Val title: String = resources.getString(r.string.chooser_title) // Create an implicit Intent to display the app selection box: Intent = intent.createchooser (sendIntent, title) // Initiate an action after security verificationif(sendIntent.resolveActivity(packageManager) ! = null) { startActivity(chooser) }Copy the code

Receive an implicit Intent

You can declare one or more intent filters for each application component by using the

element in the manifest file. Each Intent filter specifies the type of Intent it accepts based on the action, data, and category of the Intent. The system passes an implicit Intent to the application component only if the Intent can be delivered through one of the Intent filters.

Inside the

tag, you can specify the type of intent to accept using one or more of the following three elements:

  • <action>

In the name attribute, declare the accepted Intent action. The value must be the text string value of the operation, not a class constant.

  • <data>

Declare the accepted data type using one or more attributes that specify aspects of the data URI (Scheme, host, PROt, PATH) and the MIME type.

  • <category>

In the Name attribute, declare the class of Intent accepted. The value must be the text string value of the operation, not a class constant.

One important point to note is that if you want to accept an implicit Intent, you must include the CATEGORY_DEFAULT category in the filter. The methods startActivity() and startActivityForResult() will handle all intents as they declare CATEGORY_DEFAULT. If the category is not declared in an Intent filter, the Activity is not resolved by an implicit Intent.

The Intent filter for the Activity component must be declared in the manifest file, but broadcast filters can be registered dynamically by calling registerReceiver(). A Service should always be started with an explicit Intent.

Use the PendingIntent

The PendingIntent object is a wrapper around an Intent object. The main purpose is to authorize external applications to use the included Intent as if it were executed from within the application’s own process.

PendingIntent Main purpose:

  • Declares the Intent (an Intent executed by NotificationManager) that the user wants to execute when performing an action using the application notification.
  • Declares the Intent to perform when the user performs an action with the application widget (the Intent performed by the home screen application).
  • Declares an Intent to be executed at a specific time in the future (an Intent executed by AlarmManager).

Since each Intent object is designed to be handled by a specific type of application component (Activity, Service, or BroadcastReceiver), the same considerations must be used to create PendingIntent:

  • PendingIntent. GetActivity (), applicable to the Intent of the Activity.
  • Pendingintent.getservice (), for an Intent that starts a Service.
  • PendingIntent. GetBroadcast (), is applicable to start BroadcastReceiver Intent.

PendingIntent calls each of the three intent methods with a flag parameter of type int that is defined within a set of specific values, including constants from the intent:

  • PendingIntent.FLAG_ONE_SHOT

Indicates that this PendingIntent can only be used once.

  • PendingIntent.FLAG_NO_CREATE

Returns NULL if the Intent described does not exist.

  • PendingIntent.FLAG_CANCEL_CURRENT

If the described PendingIntent already exists, the current Intent is cancelled before using the new Intent.

  • PendingIntent.FLAG_UPDATE_CURRENT

If the PendingIntent described already exists, keep the flag, but replace its additional data with the contents of the new Intent.

  • PendingIntent.FLAG_IMMUTABLE

Flags indicating that the created PendingIntent should be immutable.

Intent parsing

When an implicit Intent is received to start an Activity, the system compares the Intent with an Intent filter based on three aspects to find the best Activity for that Intent. The three aspects are action, Data, and category.

The Action match

<intent-filter>
    <action android:name="android.intent.action.EDIT" />
    <action android:name="android.intent.action.VIEW" />
    ...
</intent-filter>
Copy the code

In

, you can declare no

or more than one

. However, if one or more of these actions are declared, then the action must match one of the actions listed in the filter if the Intent is implicit. That’s 1 in N.


If no action is specified in the Activity filter, then all implicit intents fail.

However, if an implicit Intent does not specify an action, the Intent can be matched if there is at least one action in the Activity filter. That’s 0 in N.

The Category matching

<intent-filter>
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    ...
</intent-filter>
Copy the code

Like action, you can declare none or more than one at a time in a filter.

If an implicit Intent contains categories, all of them must match the category in the filter. That is, N in N or N in M (N < M, but each is in M).

If there is no category in an implicit Intent, you can match it. That’s 0 in N.

Note that Android automatically applies the CATEGORY_DEFAULT category to all implicit intents passed to startActivity() and startActivityForResult().

Data matching

<intent-filter>
    <data android:mimeType="video/mpeg" android:scheme="http". /> <data android:mimeType="audio/mpeg" android:scheme="http". / >... </intent-filter>Copy the code

Like action, you can declare none or more than one at a time in a filter.

Each element can specify a URI structure and a data type (MIME media type). Each part of the URI is a separate property: Scheme, host, port, and PATH.

Each attribute of the URI is optional, but there is a linear dependency:

  • If scheme is not specified, host is ignored.

  • If host is not specified, port is ignored.

  • If scheme and host are not specified, path is ignored.

Uris in intEnts match urIs in filters:

  • If the filter specifies only Scheme, all URIs with this scheme match.

  • If the scheme and permission are specified but path is not specified, all URIs with the same scheme and permission are matched, ignoring path.

  • If scheme, permission, and PATH are specified, you need to match them.

The URI and MIME type in the Intent match the URI and MIME type specified in the filter:

  • If the filter does not specify anything, then an Intent that does not contain a URI and MIME will only match.

  • If an implicit Intent contains a URI but does not contain A MIME (and cannot be recognized by the URI), it matches only if its URI matches the filter URI and the filter also does not specify a MIME.

  • If the filter specifies a MIME but does not specify a URI, then an implicit Intent that contains the specified MIME but does not contain a URI matches.

  • If an implicit Intent has both a URI and a MIME, or if only a URI but the MIME type can be inferred from the URI, then the Intent must match the MIME specified by the filter. If the URI in an implicit Intent matches the URI in the filter, or if the filter does not specify a URI, and the URI of an implicit Intent is Content: or File:, then the Intent can be matched by URI. That is, if the filter lists only the MIME type, Then assume that the component supports content: and File: data.

Since most of the data is distributed with contentProviders, filters that specify data types rather than URIs are probably the most common.

The Intent to match

The PackageManager method queryIntentActivities() returns all the activities listed in the Intent that can be executed as an argument. QueryIntentServices () returns a similar set of services. And queryIntentContentProviders () returns a similar series of ContentProvider, these two methods are not activated components, just listed.

There are also methods resolveActivity(), resolveService(), and resolveContentProvider(), which return the best handler of the current implicit Intent.