Intents and Intent Filters

来源:互联网 发布:c语言 n阶幻方 编辑:程序博客网 时间:2024/05/16 17:45

Intents and Intent Filters

An Intent is a messaging object we can use to request an action from another app component. Although intents facilitate communication between components in several ways, there are three fundamental use-cases: 

a) To start an activity:

An Activity represents a single screen in an app. We can start a new instance of an Activity by passing an Intent to startActivity().

If we want to receive a result from the Activity when it finishes, call startActivityForResult(). Our activity receives the result as a separate Intent object in our activity's onActivityResult() callback.

b) To start an service:

A service is a component that performs operations in the background without a user interface. We can start a service to perform a one-time operation by passing an Intent to startService().

If the service is designed with a client-server interface, we can bind to the service from another component by passing an Intent to bindService().

c) To deliver a broadcast:

A broadcast is a message that any app can receive. The system delivers various broadcasts for system events. We can deliver a broadcast to other apps by passing an Intent to sendBroadcast(), sendOrderedBroadcast(), or sendStickyBroadcast().

Intent types

There are two types of intents:

a> Explicit intents specify the component to start  by name (the fully-qualified class name). We'll typically use an explicit intent to start a component in our own app, because we know the class name of the Activity or service we want to start.

b> Implicit intents do not name a specific component, but instead declare a general action to perform, which allows a component from another app to handle it.

When we create an explicit intent to start an activity or service, the system immediately starts the app component specified in the Intent object.

When we create an implicit intent, the Android system finds the appropriate component to start by comparing the contents of the intent to the intent filters declared in the manifest file of other apps on the device. If the intent matched an intent filter, the system starts that component and delivers it the Intent object. If multiple intent filters are compatible, the system displays a dialog so the user can pick which app to use.

An intent filter is an expression in an app's manifest that the component would like to receive. For instance, by declaring an intent filter for an activity, we make it possible for other apps to directly start our activity with a certain kind of intent. Likewise, if we do not declare any intent filters for an activity, then it can be started only with an explicit intent.

To ensure our app is secure, always use an explicit intent when starting a Service and do not declare intent filters for our services.

Building an Intent

An Intent object carries information that the Android system uses to determine which component to start (such as the exact component name or component category that should receive the intent), plus information that the recipient component uses in order to properly perform the action (such as the action to take and the data to act upon). The primary information contained in an Intent is the following:

a> Component name

The name of the component to start. This field of the Intent is a ComponentName object, which we can specify using a fully qualified class name of the target component, including the package name of the app.

This is optional, but it's the critical piece of information that makes an intent explicit, meaning that the intent should be delivered only to the app component defined by the component name. So if we need to start a specific component in our app, we should specify the component name.

When starting a Service, we should always specify the component name. OtherWise, we cannot be certain what service will respond to the intent, and the user cannot see which service starts.

b> Action

A string that specifies the generic action to perform (such as view or pick).

In the case of broadcast intent, this is the action that took place and is being reported. The action largely determines how the rest of the intent is structured-particularly what is contained in the data and extras.

We can specify our won actions for use by intents within our app (or for use by other apps to invoke components in our app), but we should usually use action constants defined by the Intent class or other framework classes. Here are some common actions for starting an Activity:

1> ACTION_VIEW

Use this action in an intent with startActivity() when we have some information that an activity can show to the user.

2> ACTION_SEND

Also known as the "share" intent, we should use this in an intent with startActivity() when we have some data that the user can share through another app.

If we define our own actions,be sure to include our app's package name as a prefix.

c> Data

The URI(a Uri object) that references the data to be acted on and/or the MIME type of that data. The type of data supplied is generally dictated by the intent's action.

When creating an intent, it's often important to specify the type of data (its MIME type) in addition to its URI. As URI formats could be similar, specifying the MIME type of our data helps the Android system find the best component to receive our intent. However, the MIME type can sometimes be inferred form the URI---particularly when the data is a content: URI, which indicates the data is located on the device and controlled by a ContentProvider, which makes the data MIME type visible to the system.

To set only the data URI, call setData(). To set only the MIME type, call setType(). If necessary, we can set both explicitly with setDataAndType().

d> Category

A string containing additional information about the kind of component that should handle the intent. Any number of category descriptions can be placed in an intent, but most intents do not require a category. Here are some common categories:

1> CATEGORY_BROWSABLE

The target activity allows itself to be started by a web browser to display data referenced by a link---such as an image or an e-mail message.

2> CATEGORY_LAUNCHER

The activity is the initial activity of a task and is listed in the system's application launcher.

These properties listed above(component name, action, data and category) represent the defining characteristics of  an intent.By reading these properties, the Android system is able to resolve which app component it should start.

However, an intent can carry additional information that does not affect how it is resolved to an app component. An intent can also supply:

a> Extras

Key-value pairs that carry additional information required to accomplish the requested action. Just as some actions use particular kinds of data URIs, some actions also use particular extras.

We can add extra data with various putExtra() methods, each accepting two parameters: the key name and the value. We can also create a Bundle object with all the extra data, then insert the Bundle in the Intent with putExtras().

The Intent class specifies many EXTRA_* constants for standardized data types. If we need to declare our own extra keys (for intents that our app receives), be sure to include our app's package name as a prefix.

b> Flags

Flags defined in the Intent class that function as metadata for the intent. The flags may instruct the Android system how to launch an activity and how to treat it after it's launched.

Forcing an app chooser

When there is more than one app that responds to our implicit intent, the user can select which app to use and make that app the default choice for the action. This is nice when performing an action for which the user probably wants to use the same app from now on.

However, if multiple apps can respond to the intent and the user might want to use a different app each time, we should explicitly show a chooser dialog. The chooser dialog asks the user to select which app to use for the action every time (the user cannot select a default app for the action).

To show the chooser, create an Intent using createChooser() and pass it to startActivity().

Receiving an implicit intent

To advertise which implicit intents our app can receive,declare one or more intent filters for each of our app components with an <intent-filter> element in our manifest file. Each intent filter specifies the type of intents it accepts based on the intent's action, data and category. The system will deliver an implicit intent to our app component only if the intent can pass through one of our intent filters.

An app component should declare separate filters for each unique it can do. Each intent filter is defined by an <intent-filter> element in the app's manifest file, nested in the corresponding app component (such as an <activity> element). Inside the <intent-filter>, we can specify the type of intents to accept using one or more of these three elements:

a> <action>

Declares the intent action accepted, in the name attribute. The value must be the literal string value of an action, not the class constant.

b> <data>

Declares the type of data accepted, using one or more attributes that specify various aspects of the data URI (scheme, host, port, path, etc.) and MIME type.

c> <category>

Declares the intent category accepted, in the name attribute. The value must be the literal string value of an action, not the class constant.

In order to receive implicit intents, we must include the CATEGORY_DEFAULT category in the intent filter. The methods startActivity() and StartActivityForResult() treat all intents as if they declared the CATEGORY_DEFAULT category. If we do not declare this category in our intent filter, no implicit intents will resolve to our activity.

An implicit intent is tested against a filter by comparing the intent to each of the three elements. To be delivered to the component, the intent must pass all three tests. If it fails to match even one of them, the Android system won't deliver the intent to the component. However, because a component may have multiple intent filters, an intent that does not pass through one of a component's filters might make it trough on another filter.

 For all activities, we must declare our intent filters in the manifest file. However, filters for broadcast receivers can be registered dynamically by calling registerReceiver(). We can then unregister the receiver with unregisterReceiver(). Doing so allows our app to listen for specific broadcasts during only a specified period of time while our app is running.

Example filters

<activity android:name=".MainActivity" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <activity android:name=".ShareActivity" >            <!-- This activity handles "SEND" actions with text data -->            <intent-filter>                <action android:name="android.intent.action.SEND" />                <category android:name="android.intent.category.DEFAULT" />                <data android:mimeType="text/plain" />            </intent-filter>            <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->            <intent-filter>                <action android:name="android.intent.action.SEND" />                <action android:name="android.intent.action.SEND_MULTIPLE" />                <category android:name="android.intent.category.DEFAULT" />                <data android:mimeType="application/vnd.google.panorama360+jpg" />                <data android:mimeType="image/*" />                <data android:mimeType="videp/*" />            </intent-filter>        </activity>

The first activity, MainActivity, is the app's main entry point---the activity that opens when the user initially launches the app with the launcher icon:

a> The ACTION_MAIN action indicates this is the main entry point and does not expect an intent data.

b> The CATEGORY_LAUNCHER category indicated that this activity's icon should be placed in the system's app launcher. If the <activity> element does not specify an icon with icon, then the system uses the icon from the <application> element.

c> These two must be paired together in order for the activity to appear in the app launcher.

The second activity, ShareActivity, is intended to facilitate sharing text and media content. Although users might enter this activity by navigating to it form MainActivity, they can also enter ShareActivity directly from another app that issues an implicit intent matching one of the two intent filters.

Using a Pending Intent

A Pending Intent object is a wrapper around an Intent object. The primary purpose of a pending intent is to grant permission to a foreign application to use the contained intent as if it were executed from our app's own process.

Major use cases for a pending intent include:

a> Declare an intent to be executed when the user performs an action with our notification.(the Android system's notification manager execute the intent)

b> Declare an intent to be executed when the user performs an action with our app widget.(the Home screen app executes the intent)

c> Declare an intent to bel executed at a specified time in the future.(the Android system's alarm manager executes the intent)

When using a pending intent, our app will not execute the intent with a call such as startActivity(). We must instead declare the intended component type when we create the PendingIntent by calling the respective creator method:

a> PendingIntent.getActivity() for an Intent that starts an Activity.

b> PendingIntent.getService() for an Intent that starts a Service.

c> PendingIntent.getBroadCast() for an Intent that starts an BroadcastReceiver.

Unless our app is receiving pending intents from other apps, the above methods to create a PendingIntent are the only PendingIntent methods we'll probably ever need.

Each method takes the current app Context, the Intent we want to wrap, and one or more flags that specify how the intent should be used (such as whether the intent can be used more than once).

Intent Resolution

When the system receives an implicit intent to start an activity, it searches for the best activity for the intent by comparing the intent to intent filters bases on three aspects: the intent action, the intent data (both URI and data type), and the intent category.

Each <data> element can specify a URI structure and a data type (MIME media type). There are separate attributes --- scheme, host, port, and path --- for each part of the URI: <schema>://<host>:<port>/<path>


0 0
原创粉丝点击