Intents and Intent Filters

An Intent is a messaging object you 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:

  • To start an activity:

    An Activity represents a single screen in an app. You can start a new instance of an Activity by passing an Intent tostartActivity(). The Intent describes the activity to start and carries any necessary data.

    If you want to receive a result from the activity when it finishes, call startActivityForResult(). Your activity receives the result as a separate Intent object in your activity'sonActivityResult() callback. For more information, see theActivities guide.

  • To start a service:

    Service is a component that performs operations in the background without a user interface. You can start a service to perform a one-time operation (such as download a file) by passing an Intent to startService(). The Intent describes the service to start and carries any necessary data.

    If the service is designed with a client-server interface, you can bind to the service from another component by passing an Intent to bindService(). For more information, see the Services guide.

  • To deliver a broadcast:

    A broadcast is a message that any app can receive. The system delivers various broadcasts for system events, such as when the system boots up or the device starts charging. You can deliver a broadcast to other apps by passing an Intent to sendBroadcast()sendOrderedBroadcast(), or sendStickyBroadcast().

Intent Types

There are two types of intents:

  • Explicit intents specify the component to start by name (the fully-qualified class name). You'll typically use an explicit intent to start a component in your own app, because you know the class name of the activity or service you want to start. For example, start a new activity in response to a user action or start a service to download a file in the background.
  • 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. For example, if you want to show the user a location on a map, you can use an implicit intent to request that another capable app show a specified location on a map.

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

Figure 1. Illustration of how an implicit intent is delivered through the system to start another activity: [1] Activity Acreates an Intent with an action description and passes it to startActivity()[2] The Android System searches all apps for an intent filter that matches the intent. When a match is found, [3] the system starts the matching activity (Activity B) by invoking its onCreate() method and passing it the Intent.

When you 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 matches an intent filter, the system starts that component and delivers it theIntent 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 file that specifies the type of intents that the component would like to receive. For instance, by declaring an intent filter for an activity, you make it possible for other apps to directly start your activity with a certain kind of intent. Likewise, if you do notdeclare any intent filters for an activity, then it can be started only with an explicit intent.

Caution: To ensure your app is secure, always use an explicit intent when starting a Service and do not declare intent filters for your services. Using an implicit intent to start a service is a security hazard because you cannot be certain what service will respond to the intent, and the user cannot see which service starts. Beginning with Android 5.0 (API level 21), the system throws an exception if you call bindService() with an implicit intent.

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:

Component name
The name of the component to start.

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. Without a component name, the intent is implicit and the system decides which component should receive the intent based on the other intent information (such as the action, data, and category—described below). So if you need to start a specific component in your app, you should specify the component name.

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

This field of the Intent is a ComponentName object, which you can specify using a fully qualified class name of the target component, including the package name of the app. For example,com.example.ExampleActivity. You can set the component name with setComponent()setClass(),setClassName(), or with the Intent constructor.

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

In the case of a 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.

You can specify your own actions for use by intents within your app (or for use by other apps to invoke components in your app), but you should usually use action constants defined by the Intent class or other framework classes. Here are some common actions for starting an activity:

ACTION_VIEW
Use this action in an intent with  startActivity() when you have some information that an activity can show to the user, such as a photo to view in a gallery app, or an address to view in a map app.
ACTION_SEND
Also known as the "share" intent, you should use this in an intent with  startActivity() when you have some data that the user can share through another app, such as an email app or social sharing app.

See the Intent class reference for more constants that define generic actions. Other actions are defined elsewhere in the Android framework, such as in Settings for actions that open specific screens in the system's Settings app.

You can specify the action for an intent with setAction() or with an Intent constructor.

If you define your own actions, be sure to include your app's package name as a prefix. For example:

static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
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. For example, if the action is ACTION_EDIT, the data should contain the URI of the document to edit.

When creating an intent, it's often important to specify the type of data (its MIME type) in addition to its URI. For example, an activity that's able to display images probably won't be able to play an audio file, even though the URI formats could be similar. So specifying the MIME type of your data helps the Android system find the best component to receive your intent. However, the MIME type can sometimes be inferred from 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, you can set both explicitly with setDataAndType().

Caution: If you want to set both the URI and MIME type, do not call setData() and setType()because they each nullify the value of the other. Always use setDataAndType() to set both URI and MIME type.

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:
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.
CATEGORY_LAUNCHER
The activity is the initial activity of a task and is listed in the system's application launcher.

See the Intent class description for the full list of categories.

You can specify a category with addCategory().

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:

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.

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

For example, when creating an intent to send an email with ACTION_SEND, you can specify the "to" recipient with the EXTRA_EMAIL key, and specify the "subject" with the EXTRA_SUBJECT key.

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

static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
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 (for example, which  task the activity should belong to) and how to treat it after it's launched (for example, whether it belongs in the list of recent activities).

For more information, see the setFlags() method.

Example explicit intent

An explicit intent is one that you use to launch a specific app component, such as a particular activity or service in your app. To create an explicit intent, define the component name for the Intent object—all other intent properties are optional.

For example, if you built a service in your app, named DownloadService, designed to download a file from the web, you can start it with the following code:

// Executed in an Activity, so 'this' is the Context
// The fileUrl is a string URL, such as "http://www.example.com/image.png"
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);

The Intent(Context, Class) constructor supplies the app Context and the component a Class object. As such, this intent explicitly starts the DownloadService class in the app.

For more information about building and starting a service, see the Services guide.

Example implicit intent

An implicit intent specifies an action that can invoke any app on the device able to perform the action. Using an implicit intent is useful when your app cannot perform the action, but other apps probably can and you'd like the user to pick which app to use.

For example, if you have content you want the user to share with other people, create an intent with theACTION_SEND action and add extras that specify the content to share. When you call startActivity() with that intent, the user can pick an app through which to share the content.

Caution: It's possible that a user won't have any apps that handle the implicit intent you send tostartActivity(). If that happens, the call will fail and your app will crash. To verify that an activity will receive the intent, call resolveActivity() on your Intent object. If the result is non-null, then there is at least one app that can handle the intent and it's safe to call startActivity(). If the result is null, you should not use the intent and, if possible, you should disable the feature that issues the intent.

// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");

// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

Note: In this case, a URI is not used, but the intent's data type is declared to specify the content carried by the extras.

When startActivity() is called, the system examines all of the installed apps to determine which ones can handle this kind of intent (an intent with the ACTION_SEND action and that carries "text/plain" data). If there's only one app that can handle it, that app opens immediately and is given the intent. If multiple activities accept the intent, the system displays a dialog so the user can pick which app to use..

Figure 2. A chooser dialog.

Forcing an app chooser

When there is more than one app that responds to your 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, such as when opening a web page (users often prefer just one web browser) .

However, if multiple apps can respond to the intent and the user might want to use a different app each time, you 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). For example, when your app performs "share" with the ACTION_SEND action, users may want to share using a different app depending on their current situation, so you should always use the chooser dialog, as shown in figure 2.

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

Intent sendIntent = new Intent(Intent.ACTION_SEND);
...

// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show the chooser dialog
Intent chooser = Intent.createChooser(sendIntent, title);

// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}

This displays a dialog with a list of apps that respond to the intent passed to the createChooser() method and uses the supplied text as the dialog title.

Receiving an Implicit Intent

To advertise which implicit intents your app can receive, declare one or more intent filters for each of your app components with an <intent-filter> element in your 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 your app component only if the intent can pass through one of your intent filters.

Note: An explicit intent is always delivered to its target, regardless of any intent filters the component declares.

An app component should declare separate filters for each unique job it can do. For example, one activity in an image gallery app may have two filters: one filter to view an image, and another filter to edit an image. When the activity starts, it inspects the Intent and decides how to behave based on the information in the Intent (such as to show the editor controls or not).

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>, you can specify the type of intents to accept using one or more of these three elements:

<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.
<data>
Declares the type of data accepted, using one or more attributes that specify various aspects of the data URI ( schemehostportpath, etc.) and MIME type.
<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.

Note: In order to receive implicit intents, you 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 you do not declare this category in your intent filter, no implicit intents will resolve to your activity.

For example, here's an activity declaration with an intent filter to receive an ACTION_SEND intent when the data type is text:

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

It's okay to create a filter that includes more than one instance of <action><data>, or <category>. If you do, you simply need to be certain that the component can handle any and all combinations of those filter elements.

When you want to handle multiple kinds of intents, but only in specific combinations of action, data, and category type, then you need to create multiple intent filters.

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 through on another filter. More information about how the system resolves intents is provided in the section below about Intent Resolution.

Caution: To avoid inadvertently running a different app'sService, always use an explicit intent to start your own service and do not declare intent filters for your service.

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

Example filters

To better understand some of the intent filter behaviors, look at the following snippet from the manifest file of a social-sharing app.

<activity android:name="MainActivity">
    <!-- This activity is the main entry, should appear in app launcher -->
    <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="video/*"/>
    </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:

  • The ACTION_MAIN action indicates this is the main entry point and does not expect any intent data.
  • The CATEGORY_LAUNCHER category indicates 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.

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 from MainActivity, they can also enter ShareActivity directly from another app that issues an implicit intent matching one of the two intent filters.

Note: The MIME type, application/vnd.google.panorama360+jpg, is a special data type that specifies panoramic photos, which you can handle with the Google panorama APIs.

Using a Pending Intent

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

Major use cases for a pending intent include:

  • Declare an intent to be executed when the user performs an action with your Notification (the Android system's NotificationManager executes the Intent).
  • Declare an intent to be executed when the user performs an action with your App Widget (the Home screen app executes the Intent).
  • Declare an intent to be executed at a specified time in the future (the Android system's AlarmManagerexecutes the Intent).

Because each Intent object is designed to be handled by a specific type of app component (either anActivity, a Service, or a BroadcastReceiver), so too must a PendingIntent be created with the same consideration. When using a pending intent, your app will not execute the intent with a call such asstartActivity(). You must instead declare the intended component type when you create thePendingIntent by calling the respective creator method:

  • PendingIntent.getActivity() for an Intent that starts an Activity.
  • PendingIntent.getService() for an Intent that starts a Service.
  • PendingIntent.getBroadcast() for a Intent that starts an BroadcastReceiver.

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

Each method takes the current app Context, the Intent you 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).

More information about using pending intents is provided with the documentation for each of the respective use cases, such as in the Notifications and App Widgets API guides.

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 based on three aspects:

  • The intent action
  • The intent data (both URI and data type)
  • The intent category

The following sections describe how intents are matched to the appropriate component(s) in terms of how the intent filter is declared in an app's manifest file.

Action test

To specify accepted intent actions, an intent filter can declare zero or more <action> elements. For example:

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

To get through this filter, the action specified in the Intent must match one of the actions listed in the filter.

If the filter does not list any actions, there is nothing for an intent to match, so all intents fail the test. However, if an Intent does not specify an action, it will pass the test (as long as the filter contains at least one action).

Category test

To specify accepted intent categories, an intent filter can declare zero or more <category> elements. For example:

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

For an intent to pass the category test, every category in the Intent must match a category in the filter. The reverse is not necessary—the intent filter may declare more categories than are specified in the Intent and theIntent will still pass. Therefore, an intent with no categories should always pass this test, regardless of what categories are declared in the filter.

Note: Android automatically applies the the CATEGORY_DEFAULT category to all implicit intents passed tostartActivity() and startActivityForResult(). So if you want your activity to receive implicit intents, it must include a category for "android.intent.category.DEFAULT" in its intent filters (as shown in the previous <intent-filter> example.

Data test

To specify accepted intent data, an intent filter can declare zero or more <data> elements. For example:

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

Each <data> element can specify a URI structure and a data type (MIME media type). There are separate attributes — schemehostport, and path — for each part of the URI:

<scheme>://<host>:<port>/<path>

For example:

content://com.example.project:200/folder/subfolder/etc

In this URI, the scheme is content, the host is com.example.project, the port is 200, and the path isfolder/subfolder/etc.

Each of these attributes is optional in a <data> element, but there are linear dependencies:

  • If a scheme is not specified, the host is ignored.
  • If a host is not specified, the port is ignored.
  • If both the scheme and host are not specified, the path is ignored.

When the URI in an intent is compared to a URI specification in a filter, it's compared only to the parts of the URI included in the filter. For example:

  • If a filter specifies only a scheme, all URIs with that scheme match the filter.
  • If a filter specifies a scheme and an authority but no path, all URIs with the same scheme and authority pass the filter, regardless of their paths.
  • If a filter specifies a scheme, an authority, and a path, only URIs with the same scheme, authority, and path pass the filter.

Note: A path specification can contain a wildcard asterisk (*) to require only a partial match of the path name.

The data test compares both the URI and the MIME type in the intent to a URI and MIME type specified in the filter. The rules are as follows:

  1. An intent that contains neither a URI nor a MIME type passes the test only if the filter does not specify any URIs or MIME types.
  2. An intent that contains a URI but no MIME type (neither explicit nor inferable from the URI) passes the test only if its URI matches the filter's URI format and the filter likewise does not specify a MIME type.
  3. An intent that contains a MIME type but not a URI passes the test only if the filter lists the same MIME type and does not specify a URI format.
  4. An intent that contains both a URI and a MIME type (either explicit or inferable from the URI) passes the MIME type part of the test only if that type matches a type listed in the filter. It passes the URI part of the test either if its URI matches a URI in the filter or if it has a content: or file: URI and the filter does not specify a URI. In other words, a component is presumed to support content: and file: data if its filter lists only a MIME type.

This last rule, rule (d), reflects the expectation that components are able to get local data from a file or content provider. Therefore, their filters can list just a data type and do not need to explicitly name the content: andfile: schemes. This is a typical case. A <data> element like the following, for example, tells Android that the component can get image data from a content provider and display it:

<intent-filter>
    <data android:mimeType="image/*" />
    ...
</intent-filter>

Because most available data is dispensed by content providers, filters that specify a data type but not a URI are perhaps the most common.

Another common configuration is filters with a scheme and a data type. For example, a <data> element like the following tells Android that the component can retrieve video data from the network in order to perform the action:

<intent-filter>
    <data android:scheme="http" android:type="video/*" />
    ...
</intent-filter>

Intent matching

Intents are matched against intent filters not only to discover a target component to activate, but also to discover something about the set of components on the device. For example, the Home app populates the app launcher by finding all the activities with intent filters that specify the ACTION_MAIN action and CATEGORY_LAUNCHERcategory.

Your application can use intent matching in a similar way. The PackageManager has a set of query...()methods that return all components that can accept a particular intent, and a similar series of resolve...()methods that determine the best component to respond to an intent. For example, queryIntentActivities()returns a list of all activities that can perform the intent passed as an argument, and queryIntentServices()returns a similar list of services. Neither method activates the components; they just list the ones that can respond. There's a similar method, queryBroadcastReceivers(), for broadcast receivers.

一个意图是一个消息对象,你可以用它来 ​​请求另一个动作的应用程序组件。虽然意图促进在几个方面组件之间的通信中,有三个基本的用例:

  • 要启动一个活动:

    一个活动代表了一个应用程序的单一屏幕。您可以启动的新实例活动传递一个意图 到startActivity() 。的意图 描述了启动活动并进行任何必要的数据。

    如果你想从当它完成活动收到结果,调用startActivityForResult() 。您的活动得到的结果作为一个单独的意图在活动的对象的onActivityResult()回调。欲了解更多信息,请参见活动指南。

  • 要启动服务:

    一个服务是没有用户界面在后台执行操作的组件。您可以启动一个服务传递一个执行一次性操作(如下载文件),意图 给startService() 。该意向书 介绍启动该服务,并进行任何必要的数据。

    如果服务被设计与一个客户-服务器接口,可以通过使结合于来自另一组件的服务意图bindService() 欲了解更多信息,请参阅服务指南。

  • 为了提供广播:

    广播是,任何应用程序可以接收消息。该系统提供了系统事件的各种节目,比如当系统启动或设备开始充电的。你可以通过传递一个提供给其他应用广播意向 到sendBroadcast() , sendOrderedBroadcast(),或sendStickyBroadcast() 

意图类型

有两种类型的意图的:

  • 明确的意图指定的名字开始(完全合格的类名)的组件。您通常会使用一个明确的意图在自己的应用程序来启动一个组成部分,因为你知道你想要启动的活动或服务的类名。例如,响应于用户动作开始一个新的活动或启动服务下载文件中的背景。
  • 隐式意图不命名一个特定的组件,而是宣布执行一般的动作,这使得从其他应用程序的组件来处理它。例如,如果你想显示用户在地图上的位置,你可以用一个隐含的意图来请求另一个应用程序能够显示在地图上的指定位置。

当你创建一个明确的意图开始一项活动或服务时,系统立即开始在指定的应用程序组件意图对象。

图1.怎样一个隐含的意图是通过系统提供的启动另一个活动说明:[1] 活动A创建了一个 意图与动作的描述和它传递给startActivity() [2] Android系统搜索的所有应用程序意图过滤器的意图相匹配。当找到一个匹配,[3]系统启动配对活动(活动B通过调用它)的onCreate()方法,并传递给它的意图

当你创建一个隐含的意图,Android系统找到合适的组件通过意图的内容进行比较以启动意图过滤器在申报清单文件设备上的其他应用程序。如果意图相匹配的意图过滤器,系统将启动该组件,并提供它的意图对象。如果有多个意图过滤器是兼容的,系统会显示一个对话框,以便用户可以选择要使用的应用程序。

一个意图过滤器是在应用的清单文件,指定该组件希望收到意图的类型的表达式。例如,通过声明为活动的意图过滤器,你有可能使其他应用程序直接与某种意图开始您的活动。同样的,如果你不是为了游玩声明任何的意图过滤器,那么就只能用明确意图开始。

注意:为了确保您的应用程序是安全的,开始时请务必使用明确意图服务,不为你服务声明意图过滤器。使用一个隐含的意图是启动一个服务是一个安全隐患,因为你不能确定什么样的服务将向意图做出回应,并且用户无法看到哪些服务启动。采用Android 5.0(API级别21)开始,系统投如果你调用一个异常bindService() 有一个隐含的意图。

建立一个Intent

一个意图对象携带了Android系统用于确定要启动的组件(如确切的组件名称或应接收的意图组件类别),以及信息接收者组件,以便正确执行操作使用信息(如要采取的行动和数据要遵循)。

包含在主信息意图是以下内容:

组件名称
启动组件的名称。

这是可选的,但它的信息的关键部分,使得一个意图 明确,这意味着意图应仅递送到由组件名称中定义的应用程序组件。没有一个组件名称,目的是隐式,系统决定哪个组件应接收基于其它意图信息的意图(如动作,数据和下面类别描述的)。所以,如果你需要在你的应用程序来启动某个特定组件,您应该指定组件名称。

注意:当启动一个服务,你应该 始终指定组件名称。否则,你无法确定什么样的服务将向意图做出回应,并且用户无法看到哪些服务启动。

在这一领域的意图是一个 组件名对象,您可以指定使用目标组件的完全限定类名,其中包括应用程序的包名。例如, com.example.ExampleActivity。您可以设置与该组件名称setComponent() setClass() setClassName() ,或使用 意向构造。

行动
指定通用操作的字符串来执行(如 视图)。

在广播意图的情况下,这是发生的,并且所报告的动作。操作在很大程度上决定了意图的其余部分所采用的结构,尤其中包含的内容数据,并附加功能。

您可以通过意图您的应用程序(或其他应用使用来调用你的应用程序组件)中指定使用自己的行为,但你通常应该使用已定义的动作常量意图类或其他框架类。下面是启动活动的一些常规操作:

ACTION_VIEW
使用此行动与意图 startActivity()时,你有一些信息,一个活动可以显示给用户,如要查看的照片在画廊的应用程序,或查看在地图应用程序的地址。
ACTION_SEND
也被称为“共享”的意图,你应该有一个意图使用 startActivity() ,当你有一些数据,用户可以通过其他应用程序,共享,如电子邮件应用或社交共享应用程序。

意向的定义通用的行为更多的常量类引用。其他的动作在Android框架其他地方定义,比如在设置为打开系统中的设置应用特定画面的动作。

您可以指定与意图的动作的setAction()或与意向构造。

如果您定义自己的操作,一定要包括你的应用程序的包名作为前缀。例如:

静态 最终 字符串ACTION_TIMETRAVEL =  “com.example.action.TIMETRAVEL” ;
数据
的URI(一个 开放的引用的数据对象)可以作用于和/或MIME类型的数据。类型提供的数据通常由意图的动作决定的。例如,如果动作是 ACTION_EDIT,数据应包含编辑文档的URI。

当创建一个意图,它指定数据的除了它的URI的类型(它的MIME类型)往往重要。例如,这能够大概显示图像的活动将不能够播放音频文件,即使该URI格式可能是相似的。因此指定MIME类型的数据有助于Android系统发现收到你的意图的最佳组件。然而,MIME类型,有时可以从推断的URI的,特别是当数据是一个 内容: URI,其指示数据所在的设备上,并且通过受控 的ContentProvider,这使得数据的MIME类型的系统是可见的。

要设置只有数据的URI,调用使用setData() 。要设置只MIME类型,调用的setType() 。如果有必要,你可以同时设置明确setDataAndType() 

注意:如果你要同时设置URI和MIME类型, 不要调用使用setData()和 的setType() ,因为它们各自抵消对方的价值。始终使用setDataAndType()同时设置URI和MIME类型。

类别
包含的那种分量应该处理这个意图附加信息串。任何数量的类别描述可以放置在一个意图,但大多数意图不要求一个类别。下面是一些常见的类别:
CATEGORY_BROWSABLE
目标活动允许自身通过web浏览器来显示由链路诸如图像或电子邮件消息中引用的数据来启动。
CATEGORY_LAUNCHER
该活动是一个任务的初始活性和在该系统的应用程序启动被列出。

意向进行分类的完整列表类的描述。

您可以指定与类别addCategory() 

上述(组件名称,动作,数据,和类别)中列出这些性质表示意图的限定特征。通过阅读这些特性,Android系统能解决哪些应用组件它应该开始。

然而,意图可以携带不影响它是如何解析为应用程序组件的其他信息。一个意图还可以提供:

附加功能
携带完成所请求的操作所需的附加信息键 - 值对。正如一些行动使用特定类型的数据的URI,一些动作也用特别的演员。

可以使用各种添加额外的数据putExtra()方法,每个方法接受两个参数:键名和值。您还可以创建一个捆绑的所有额外的数据对象,然后将中的意图putExtras() 

例如,在创建意图时,与发送电子邮件 ACTION_SEND,您可以指定用的“到”收件人 EXTRA_EMAIL键,并指定“主体”与 EXTRA_SUBJECT键。

意图类指定许多EXTRA_ *常量标准化的数据类型。如果您需要声明自己的附加 ​​键(对于您的应用程序接收意图),一定要包括你的应用程序的包名作为前缀。例如:

静态 最终 字符串EXTRA_GIGAWATTS =  “com.example.EXTRA_GIGAWATTS” ;
在定义的标志 意图类作为意图元数据功能。这些标志可指示Android系统如何启动一个活动(例如,它  的任务活动应该属于)和它的发射后如何对待它(例如,它是否属于在最近的活动的列表)。

欲了解更多信息,请参见setFlags()方法。

例如明确意图

一个明确的意图是让你用来启动特定的应用程序组件,比如在你的应用程序特定的活动或服务之一。要创建一个明确的意图,对于定义组件名意向对象的所有其他意图属性都是可选的。

例如,如果你建你的应用程序服务,命名为下载服务,旨在从网络上下载一个文件,可以用下面的代码开始吧:

//在活动执行,因此“这”是上下文
 //该fileUrl是一个字符串的URL,如"http://www.example.com/image.png" 
Intent downloadIntent =  new  Intent ( this ,  DownloadService . class ); 
downloadIntent . setData ( Uri . parse ( fileUrl )); 
startService ( downloadIntent );

意向书(背景下,A类) 构造函数提供应用程序上下文和组件对象。因此,这种意图明确开始下载服务中的应用程序类。

有关构建和启动服务的详细信息,请参阅 服务指南。

例如隐含意图

隐式意图指定可以调用该设备能够执行行动的任何应用程序的操作。使用一个隐含的意图时,你的应用程序无法执行的操作,但其他应用程序也许可以和你想的用户选择使用哪个应用是非常有用的。

例如,如果你有内容,您希望用户与其他人共享,创建具有意图ACTION_SEND行动,并添加指定内容共享临时演员。当你调用 startActivity()与意图,用户可以选择通过共享的内容的应用程序。

注意:这是可能的,用户不会有任何 的处理您发送到隐含意图应用startActivity() 。如果发生这种情况,调用将失败,您的应用程序会崩溃。要验证活动将收到的意图,调用resolveActivity()您的意向对象。如果结果不为null,则至少有一个应用程序能够处理的意图和它的安全调用 startActivity() 。如果结果为空,你不应该使用的意图,可能的话,你应该禁用发出意图的功能。

//创建一个文本消息 
  




验证意图将解析为一个活动
,如果 sendIntent resolveActivity getPackageManager ()) !=   { 
    startActivity sendIntent ); 
}

注意:在这种情况下,一个URI是不使用,但意图的数据类型声明来指定由额外携带的内容。

startActivity()被调用时,系统会检查所有已安装的应用程序,以确定哪些可以处理这种意图(与意图ACTION_SEND行动,并携带“text / plain的”数据)。如果只有一个应用程序可以处理它,该应用程序会立即打开,并给出意图。如果有多个活动接受的意图时,系统会显示一个对话框,以便用户可以选择要使用的应用程序..

图2.一个选择器对话框。

强制应用程序选择器

当有多个应用程序,响应你的意图隐含的,用户可以选择哪些应用程序来使用,让该应用程序的操作的默认选择。为执行该用户可能希望使用相同的应用程序从现在起,一个动作时,这是很好的,例如打开一个网页时,如(用户往往更喜欢只是一个网络浏览器)。

但是,如果多个应用程序可以向意向作出回应,用户可能希望每次都使用不同的应用程序,你应该明确地显示一个选择对话框。在选择对话框要求用户选择哪些应用每次使用的操作(用户不能选择为操作的默认应用)。例如,当您的应用程序进行“共享”与ACTION_SEND动作,用户可能想利用这取决于他们目前的状况不同的应用分享,所以你应该始终使用选择对话框,如图2。

要显示选择器,创建一个意图使用createChooser()并将它传递给startActivity() 。例如:

意图sendIntent =   意图意图ACTION_SEND ); 
... 

//总是使用字符串资源的UI文本
//这是说像“分享这张照片。” 
字符串标题= getResources ()。的getString ř 字符串chooser_title ); 
//创建意图显示选择对话框
意图选择器=  意图createChooser sendIntent 标题); 

//验证原意将解决至少一个活动
,如果 sendIntent resolveActivity getPackageManager ()) !=   { 
    startActivity 选配); 
}

这将显示与传递给意图响应的应用程序列表的对话框createChooser()方法,并使用所提供的文本作为对话框的标题。

接收隐式意图

为了宣传其隐含的意图您的应用程序可以接收,与申报为每个应用程序组件的一个或多个意图过滤器<意图过滤器> 在你的元素清单文件。每一个意图过滤指定它接受基于意图的动作,数据和类别意图的类型。该系统将提供一个隐含的意图,你的应用程序组件只有意图可以通过你的意图过滤器之一。

注:一个明确意图总是传递到其目标,无论任何意图过滤组件声明。

一个应用程序组件应为每一个独特的工作可以做单独声明过滤器。例如,在一个图片库应用一个活动可能有两个过滤器:一个过滤器来查看图像,另一个过滤器来编辑图像。当活动启动时,它检查该意图,并决定基于在所述信息如何表现意图(例如,以显示编辑控件或不是)。

每一个意图过滤器是由一个定义的<意向过滤器> 在应用程序的清单文件中的元素,嵌套在相应的应用程序组件(如<活动> 元素)。里面的<意向过滤器>,您可以指定意图的方式,通过这三个要素中的一个或多个接受:

<动作>
接受声明的意图行动,在 名称属性。该值必须是一个行动的文本字符串值,而不是类常量。
<资料>
声明数据的接受,使用该指定数据的URI(各个方面的一个或多个属性的类型 方案主机端口,  路径等)和MIME类型。
<category>中
声明接受意向类别,在 名称属性。该值必须是一个行动的文本字符串值,而不是类常量。

注:为了获得隐含的意图,你 必须包括在 CATEGORY_DEFAULT的意图过滤类别。方法startActivity()和 startActivityForResult()把所有的意图,如果他们宣布CATEGORY_DEFAULT类别。如果没有这一类的意图过滤器声明,没有隐含意图将解析为您的活动。

例如,这里是与意图过滤器来接收活动的声明 ACTION_SEND意图时,数据类型为文本:

<activity  android:name = "ShareActivity" > 
    <intent-filter> 
        <action  android:name = "android.intent.action.SEND" /> 
        <category  android:name = "android.intent.category.DEFAULT" /> 
        <data  android:mimeType = "text/plain" /> 
    </intent-filter> 
</activity>

没关系创建一个过滤器,包括多个实例 的<action> , <数据>或 <category>中。如果你这样做,你只是需要确定该组件可以处理任何与这些过滤元件的所有组合。

当你要处理多个种类的意图,但只有在行动中,数据和类别类型的特定组合,那么你需要创建多个意图过滤器。

隐式意图由意图比较每三要素的对一个过滤器进行测试。被传递到该组件,意图必须通过所有三个测试。如果失败,甚至其中的一个匹配,Android系统将无法实现意图的组件。但是,由于组件可以具有多个意图过滤器,即不通过的部件的过滤器之一的意图可能使其通过另一个过滤器。下面对部分提供了有关该系统如何解决意图的更多信息意向分辨率。

注意:为避免意外运行不同的应用程序的 服务,始终使用明确意图开始自己的服务,并没有为您服务声明意图过滤器。

注意: 对于所有的活动,您必须在清单文件中声明你的意图过滤器。然而,对于广播接收机滤波器可以动态地由调用注册 registerReceiver() 。然后,您可以注销与接收机unregisterReceiver() 。这样做使您的应用程序到你的应用程序正在运行,而只在指定的时间段监听特定广播。

例如过滤器

为了更好地理解一些意图过滤器的行为,看看从共享的社会应用程序的清单文件中的片断。

<活动 安卓:名称= “MainActivity” > 
    <! -这个活动是主入口,应该出现在应用程序启动 
    
          
          
    


 
    本次活动以处理文本数据的“发送”行动 
    
         
         
         
    
    本次活动还处理“发送”和“SEND_MULTIPLE”与媒体数据
    
         
         
         
         
         
         
    

第一项活动,MainActivity,是应用程序的主入口点活动,当用户最初启动的启动器图标应用程序打开:

  • ACTION_MAIN行动表明这是主要的入口点,并且不期待任何意图的数据。
  • CATEGORY_LAUNCHER类别表示,本次活动的图标应放置在系统的应用启动。如果<活动>元素没有指定一个图标图标,则系统将使用该图标<应用程序> 元素。

这两个必须一起才能配对的活动出现在应用程序启动器。

第二活动,ShareActivity,是为了便于共用的文本和媒体内容。虽然用户可以通过导航到它进入这个活动MainActivity,他们也可以进入ShareActivity直接从其他应用程序,发出一个隐含的意图匹配两个意图过滤器中的一个。

注: MIME类型, 应用程序/ vnd.google.panorama360 + JPG,是指定的全景照片,您可以在处理特殊的数据类型谷歌全景的API。

使用意向之前

一个的PendingIntent对象是周围的包装意图对象。一个最主要的目的的PendingIntent 是将权限授予外国申请使用包含的意图,就好像它是从你的应用程序自身的进程中执行。

主要用例挂起的意图包括:

  • 声明的意图,当用户执行与你的一个动作要执行的通知 (Android系统的NotificationManager 执行意图)。
  • 声明的意图,当用户执行与你的一个动作要执行 应用程序的Widget (在主页屏幕上的应用程序执行意向)。
  • 声明的意图在未来(Android系统的指定时间执行AlarmManager执行意图)。

因为每个意图对象旨在由特定类型的应用程序组件(无论是一个的处理活动,一个服务,或广播接收器),因此,也必须一的PendingIntent用相同的考虑创建。当使用挂起的意图,你的应用程序将无法执行与诸如呼叫的意图startActivity() 。当您创建您必须声明,而不是预期的组件类型 的PendingIntent致电各创作者的方法:

  • PendingIntent.getActivity()一个 意向启动的活动
  • PendingIntent.getService()一个 意向启动一个服务
  • PendingIntent.getBroadcast()的 意图启动的广播接收器

除非你的应用程序是接收从其他应用程序挂起的意图,上面的方法来创建的PendingIntent是唯一 的PendingIntent你可能永远需要的方法。

每个方法对当前应用背景中, 意图要包裹指定如何意图应被使用,并且一个或多个标记(例如是否意图可以使用一次以上)。

关于使用未决意图详细信息设有用于每个各自的使用情况下,如在该文档的通知 和应用的窗口小部件的API指南。

分辨率意向

当系统收到一个隐含的意图开始活动,它将搜索通过比较意图基于以下三个方面的意图过滤器意图的最佳活动:

  • 这样做的目的行动
  • 这样做的目的数据(URI和数据类型)
  • 这样做的目的类别

以下各节描述意图是如何的意图过滤器是如何在一个应用程序的清单文件中声明的条款匹配到合适的组件(S)。

操作测试

要指定接受的意图行动,意图过滤器可以声明零个或更多 的<action>元素。例如:

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

打通这个过滤器,在指定的操作意图 必须匹配过滤器中列出的操作之一。

如果过滤器没有列出任何动作,没有任何一个意图匹配,所以所有的意图失败的考验。但是,如果意图 不指定一个动作,它将通过测试(只要该过滤器包含至少一个动作)。

分类测试

要指定接受意向类别,一个意图过滤器可以声明零个或更多 的<category>元素。例如:

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

对于意图传递类试验中,对每一个类别意图 必须在过滤器的类别相匹配。相反的是没有必要的,意图过滤器可以宣告多个类别比指定意图和 意图仍然会通过。因此,没有类别的意图应该总是通过这个测试,无论在过滤器中声明哪些类别。

注: Android的自动的应用CATEGORY_DEFAULT类别传递给所有的隐含意图startActivity()startActivityForResult() 。所以如果你想你的活动接受隐含意图,它必须包括一个类别“android.intent.category.DEFAULT”其意图过滤器(如在以前<意图过滤器>的例子。

数据测试

要指定接受意图数据,一个意图过滤器可以声明零个或多个 <数据>元素。例如:

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

每个<数据> 元素可以指定一个URI结构和数据类型(MIME媒体类型)。有单独的属性- 模式主机端口路径 -为URI的各个部分:

<方案>:// <主机>:<端口> / <路径>

例如:

内容://com.example.project:200 /文件夹/子文件夹中的/ etc

在此URI,该方案的内容,主机是com.example.project,端口是200,和路径是文件夹/子/等

每个属性是一个可选的<数据>元素,但也有线性的依赖关系:

  • 如果没有指定一个方案,主机将被忽略。
  • 如果没有指定主机,端口会被忽略。
  • 如果未指定两个方案和主机,路径被忽略。

当在意图的URI被相比,在过滤器中的URI规范,它相比仅包括在过滤器URI的部分。例如:

  • 如果过滤器仅指定一个方案,与该计划所有URI匹配滤波器。
  • 如果过滤器指定了一个方案,一个权威,但没有路径,用同样的方案和权威的URI通过过滤器,不管他们的路径。
  • 如果过滤器指定了一个方案,一个权威,和路径,只能用相同方案,授权和路径的URI通过过滤器。

注:路径规范可以包含通配符星号(*),以只需要路径名的一个部分匹配。

数据测试比较两者的URI和在意图在滤波器中指定的URI和MIME类型的MIME类型。的规则如下:

  1. 既不包含URI也不是MIME类型的意图传递仅当过滤器不指定任何的URI或MIME类型的测试。
  2. 包含URI的意图,但没有MIME类型(既不明确也不能推理从URI)通过测试仅当它的URI相匹配的滤波器的URI格式和过滤器同样未指定MIME类型。
  3. 包含MIME类型,但不是一个URI通过了测试仅在过滤器中列出了相同的MIME类型,不指定一个URI格式的意图。
  4. 同时包含URI和MIME类型(无论是明确的还是能推理从URI)意图通过测试的MIME类型部分仅当该类型的过滤器中列出的类型相匹配。它通过测试的URI的一部分或者如果它的URI的过滤器匹配的URI,或者如果它有一个内容: 或文件: URI和过滤器没有指定一个URI。换句话说,组件被假定为支持内容:文件:数据如果其过滤列表一个MIME类型。

这最后一条规则,规则(四),反映了期望组件能够从文件或内容提供商获取本地数据。因此,他们的过滤器可以列出只是一个数据类型,并不需要显式地命名内容:文件:方案。这是一个典型的案例。一个<数据>像下面这样的元素,例如,告诉Android组件可以从内容提供商获取图像数据并显示它:

<意图过滤器> 
    <数据 的android:mime类型= “图像/ *”  /> 
    ... 
</意图过滤器>

由于大多数可用的数据是由内容提供者,过滤器,用于指定一个数据类型而不是一个URI也许是最常用的分配。

另一种常见的配置是一个方案和一个数据类型的过滤器。例如,<数据> 像下面的元素告诉Android组件可以从网络检索视频数据以执行的操作:

<意图过滤器> 
    <数据 的android:计划= “HTTP”  机器人:类型= “视频/ *”  /> 
    ... 
</意图过滤器>

意向匹配

意图是针对意图过滤器匹配,不仅发现一个目标组件激活,同时也发现一些关于设备上的组件集合。例如,家庭应用填充通过查找所有与指定意向过滤器的活动应用启动 ACTION_MAIN行动和 CATEGORY_LAUNCHER类别。

应用程序可以以类似的方式使用意图匹配。该软件包管理系统具有一组查询...() 返回,可以接受的特定意图的所有组件的方法,以及类似的一系列解决...()确定对意图响应最佳组分的方法。例如,queryIntentActivities()返回一个可以执行作为参数传递的意图所有活动的列表,以及queryIntentServices()返回一个类似的服务列表。无论方法激活的组件; 他们只是列出了可以响应的人。有一个类似的方法, queryBroadcastReceivers() ,对于广播接收机。


你可能感兴趣的:(android)