This lesson teaches you to
- 构建隐式意图
- 验证是否有个可以接收Intent的应用程序
- 使用Intent启动Activity
- 显示一个应用程序选择器
You should also read
- 共享内容
One of Android's most important features is an app's ability to send the user to another app based on an "action" it would like to perform. For example, if your app has the address of a business that you'd like to show on a map, you don't have to build an activity in your app that shows a map. Instead, you can create a request to view the address using an . The Android system then starts an app that's able to show the address on a map.
As explained in the first class, , you must use intents to navigate between activities in your own app. You generally do so with an explicit intent, which defines the exact class name of the component you want to start. However, when you want to have a separate app perform an action, such as "view a map," you must use an implicit intent.
正如在第一课,构建你的第一个应用程序中所解释的,你必须使用intent在你程序中的activity之间导航。你一般使用显式Intent来这么做,其定义了你想要启动组件的确切类名。然而,当你想要一个单独的应用执行一个动作,例如"查看地图",你必须使用一个隐式意图。
This lesson shows you how to create an implicit intent for a particular action, and how to use it to start an activity that performs the action in another app.
这节向你展示如何为一个特别的动作创建隐式意图,以及如何使用它启动一个activity,以在另一个应用程序中执行这个动作。
Build an Implicit Intent 构建一个隐式意图
Implicit intents do not declare the class name of the component to start, but instead declare an action to perform. The action specifies the thing you want to do, such as view,edit, send, or get something. Intents often also include data associated with the action, such as the address you want to view, or the email message you want to send. Depending on the intent you want to create, the data might be a , one of several other data types, or the intent might not need data at all.
If your data is a , there's a simple
constructor you can use define the action and data.
For example, here's how to create an intent to initiate a phone call using the data to specify the telephone number:
Uri number = Uri.parse("tel:5551234");Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
When your app invokes this intent by calling , the Phone app initiates a call to the given phone number.
Here are a couple other intents and their action and data pairs:
- View a map: 查看地图:
// Map point based on address// 地图点基于地址Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");// Or map point based on latitude/longitude // 或者地图点基于经纬度// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom leve//l z参数是缩放级别Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
- View a web page: 查看网页
Uri webpage = Uri.parse("http://www.android.com");Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
Other kinds of implicit intents require "extra" data that provide different data types, such as a string. You can add one or more pieces of extra data using the various methods.
By default, the system determines the appropriate MIME type required by an intent based on the data that's included. If you don't include a
in the intent, you should usually use
to specify the type of data associated with the intent. Setting the MIME type further specifies which kinds of activities should receive the intent.
Here are some more intents that add extra data to specify the desired action:
下面是更多的意图,它们添加了额外的数据指定所需的动作。- Send an email with an attachment: 发送带有附件的电子邮件:
Intent emailIntent = new Intent(Intent.ACTION_SEND);// The intent does not have a URI, so declare the "text/plain" MIME type // 意图没有URI,因此声明"text/plain" MIME类型emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipientsemailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));// You can also attach multiple items by passing an ArrayList of Uris // 通过Uri的ArrayList,你可以添加多个附件
- Create a calendar event: 创建日历事件:
Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30);calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());calendarIntent.putExtra(Events.TITLE, "Ninja class");calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");
Note: This intent for a calendar event is supported only with API level 14 and higher.
注:这个日历事件的Intent 仅在API 级别 14或更高的版本上支持
Note: It's important that you define your to be as specific as possible. For example, if you want to display an image using the
intent, you should specify a MIME type of
image/*
. This prevents apps that can "view" other types of data (like a map app) from being triggered by the intent.
注:这点很重要,定义你的Intent应尽可能明确。例如,如果你想要用ACTION_VIEW意图显示一张图片,你应当指定MIME类型为image/* 。这可以防止被该意图触发应用程序“窥视”其它类型的数据(例如地图程序)。
Verify There is an App to Receive the Intent 验证是否有个可以接收意图的应用程序
Although the Android platform guarantees that certain intents will resolve to one of the built-in apps (such as the Phone, Email, or Calendar app), you should always include a verification step before invoking an intent.
尽管Android平台保证某些意图将会分配到一个内置的应用程序(像电话,电子邮件或日历应用),你也应当总是在调用意图前包含一个验证的步骤。
Caution: If you invoke an intent and there is no app available on the device that can handle the intent, your app will crash.
注意:如果你调用了一个意图,但是设备上却没有任何可处理该意图的应用程序,你的应用将会崩溃。
To verify there is an activity available that can respond to the intent, call to get a list of activities capable of handling your
. If the returned
is not empty, you can safely use the intent. For example:
PackageManager packageManager = getPackageManager();Listactivities = packageManager.queryIntentActivities(intent, 0);boolean isIntentSafe = activities.size() > 0;
If isIntentSafe
is true
, then at least one app will respond to the intent. If it is false
, then there aren't any apps to handle the intent.
Note: You should perform this check when your activity first starts in case you need to disable the feature that uses the intent before the user attempts to use it. If you know of a specific app that can handle the intent, you can also provide a link for the user to download the app (see how to ).
注:你应该在你的activity第一次启动时执行这项检查,以防你需要禁用"在用户尝试前使用该意图"的选项。如果你知道某个应用程序可以处理该意图,你仍然可以提供一个用户下载该程序的链接(见如何链接你的产品到Google Play)
Start an Activity with the Intent 使用Intent启动Activity
Figure 1. Example of the selection dialog that appears when more than one app can handle an intent.
图1. 一个Intent可以被多个应用程序处理时将出现一个选择对话框。
Once you have created your and set the extra info, call
to send it to the system. If the system identifies more than one activity that can handle the intent, it displays a dialog for the user to select which app to use, as shown in figure 1. If there is only one activity that handles the intent, the system immediately starts it.
startActivity(intent);
Here's a complete example that shows how to create an intent to view a map, verify that an app exists to handle the intent, then start it:
下面是个完整的示例,它展示了如何创建一个意图来查看地图,验证是否存在一个应用程序可以处理这个意图。// Build the intent // 创建意图Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);// Verify it resolves // 验证它的解决方案PackageManager packageManager = getPackageManager();Listactivities = packageManager.queryIntentActivities(mapIntent, 0);boolean isIntentSafe = activities.size() > 0;// Start an activity if it's safe // 如果安全则启动一个activityif (isIntentSafe) { startActivity(mapIntent);}
Show an App Chooser 显示应用程序选择器
Figure 2. Example of the chooser dialog that appears when you use to ensure that the user is always shown a list of apps that respond to your intent.
图2. 当你调用 createChooser() 时显示选择对话框,以确保总是向用户显示响应你意图的程序列表。
Notice that when you start an activity by passing your to
and there is more than one app that responds to the intent, the user can select which app to use by default (by selecting a checkbox at the bottom of the dialog; see figure 1). This is nice when performing an action for which the user generally wants to use the same app every time, such as when opening a web page (users likely use just one web browser) or taking a photo (users likely prefer one camera). However, if the action to be performed could be handled by multiple apps and the user might prefer a different app each time—such as a "share" action, for which users might have several apps through which they might share an item—you should explicitly show a chooser dialog, which forces 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 using
and pass it to
. For example:
Intent intent = new Intent(Intent.ACTION_SEND); // Always use string resources for UI text. This says something like "Share this photo with"// 总是为UI文本使用字符串资源,这里要显示的文本是“分享照片” String title = getResources().getText(R.string.chooser_title); // Create and start the chooser // 创建并启用选择器 Intent chooser = Intent.createChooser(intent, title); startActivity(chooser);
This displays a dialog with a list of apps that respond to the intent passed to the method and uses the supplied text as the dialog title.