与其他 Activity 交互
隐式 intent
隐式 intent 不声明要启动的组件的类名称,而是声明要执行的操作。
该操作指定您要执行的操作,比如查看、编辑、发送或 获取 某项。
intent 通常还包含与操作关联的数据,比如您要查看的地址或您要发送的电子邮件消息。
根据要创建的 intent ,数据可能是 Uri
、多种其他数据类型之一,或 intent 可能根本就不需要数据。
例如数据为Url:
拨号:
Uri number = Uri.parse("tel:5551234"); Intent callIntent = new Intent(Intent.ACTION_DIAL, number);
查看地图:
// 要指向的地址 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 level Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
查看网页:
Uri webpage = Uri.parse("http://www.android.com"); Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);
需要额外数据例:
发送带附件的电子邮件:
Intent emailIntent = new Intent(Intent.ACTION_SEND); // The intent does not have a URI, so declare the "text/plain" MIME type emailIntent.setType(HTTP.PLAIN_TEXT_TYPE); emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients emailIntent.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
创建日历事件:
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");
调用应用前应确认是否存在接收 intent 的应用
尽管 Android 平台保证某些意向可以分解为内置应用之一(比如,“电话”、“电子邮件”或“日历”应用),您应在调用意向之前始终包含确认步骤。
注意:如果您调用了意向,但设备上没有可用于处理意向的应用,您的应用将崩溃。
要确认是否存在可响应意向的可用Activity,请调用 queryIntentActivities()
来获取能够处理您的Intent
的Activity列表。
如果返回的 List
不为空,您可以安全地使用该意向。例如:
PackageManager packageManager = getPackageManager(); List activities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); boolean isIntentSafe = activities.size() > 0;
开始具有意向的Activity
根据之前构建好的 intent 启动
startActivity(intent);
显示应用选择器
注意,当您通过将您的 Intent
传递至 startActivity()
而开始Activity时,有多个应用响应意向,用户可以选择默认使用哪个应用(通过选中对话框底部的复选框。
当执行用户通常希望每次使用相同应用进行的操作时,比如当打开网页(用户可能只使用一个网页浏览器)或拍照(用户可能习惯使用一个照相机)时,这非常有用。
但是,如果要执行的操作可由多个应用处理并且用户可能习惯于每次选择不同的应用,—比如“共享”操作,用户有多个应用分享项目—,您应明确显示选择器对话框。 选择器对话框强制用户选择用于每次操作的应用(用户不能对此操作选择默认的应用)。
要显示选择器,使用 createChooser()
创建Intent
并将其传递至 startActivity()
。例如:
Intent intent = 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 chooser Intent chooser = Intent.createChooser(intent, title); // Verify the intent will resolve to at least one activity if (intent.resolveActivity(getPackageManager()) != null) { startActivity(chooser); }
获取Activity的结果
要想接收另一个 Activity 返回的结果,需使用startActivityForResult()
(而不是 startActivity()
)
在使用 starttActivityForResult() 时需要一个额外参数request code,用来标识是哪个 Activity 返回的结果
例如,启动选择联系人的Activity
static final int PICK_CONTACT_REQUEST = 1; // The request code ... private void pickContact() { Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts")); pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST); }
当启动的 Activity 返回时,系统会调用 onActivityResult()
的方法,在该方法中根据request code来处理指定返回。
此方法包括三个参数:
- 您向
startActivityForResult()
传递的请求代码。 - 第二个Activity指定的结果代码。如果操作成功,这是
RESULT_OK
;如果用户退出或操作出于某种原因失败,则是RESULT_CANCELED
。 - 传送结果数据的
Intent
。
例如,处理选择联系人后的返回结果:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // Check which request we're responding to if (requestCode == PICK_CONTACT_REQUEST) { // Make sure the request was successful if (resultCode == RESULT_OK) { // The user picked a contact. // The Intent's data Uri identifies which contact was selected. // Do something with the contact here (bigger example below) } } }
从返回结果中获取联系人电话号码完整示例,需掌握 Content Provider
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // Check which request it is that we're responding to if (requestCode == PICK_CONTACT_REQUEST) { // Make sure the request was successful if (resultCode == RESULT_OK) { // Get the URI that points to the selected contact Uri contactUri = data.getData(); // We only need the NUMBER column, because there will be only one row in the result String[] projection = {Phone.NUMBER}; // Perform the query on the contact to get the NUMBER column // We don't need a selection or sort order (there's only one result for the given URI) // CAUTION: The query() method should be called from a separate thread to avoid blocking // your app's UI thread. (For simplicity of the sample, this code doesn't do that.) // Consider using CursorLoader to perform the query. Cursor cursor = getContentResolver() .query(contactUri, projection, null, null, null); cursor.moveToFirst(); // Retrieve the phone number from the NUMBER column int column = cursor.getColumnIndex(Phone.NUMBER); String number = cursor.getString(column); // Do something with the phone number... } } }
允许其他应用启动您的Activity
要允许其他应用开始您的Activity,需要在 AndoirdManifest 文件中 为需要的<activity>添加 <intent-filter>
元素
添加 intent-filter
为了正确定义您的Activity可处理的意向,您添加的每个意向过滤器在操作类型和Activity接受的数据方面应尽可能具体。
如果Activity具有满足以下 Intent
对象条件的意向过滤器,系统可能向Activity发送给定的 Intent
:
操作 action
对要执行的操作命名的字符串。通常是平台定义的值之一,比如 ACTION_SEND
或 ACTION_VIEW
。
使用 <action>
元素在您的意向过滤器中指定此值。您在此元素中指定的值必须是操作的完整字符串名称,而不是 API 常数(请参阅以下示例)。
数据 data
与意向关联的数据描述。
用 <data>
元素在您的意向过滤器中指定此内容。使用此元素中的一个或多个属性,您可以只指定 MIME 类型、URI 前缀、URI 架构或这些的组合以及其他指示所接受数据类型的项。
注意:如果您无需声明关于数据的具体信息
Uri
(比如,您的Activity处理其他类型的“额外”数据而不是 URI 的时间),您应只指定android:mimeType
属性声明您的Activity处理的数据类型,比如text/plain
或image/jpeg
。
类别 category
提供另外一种表征处理意向的Activity的方法,通常与用户手势或Activity开始的位置有关。 系统支持多种不同的类别,但大多数都很少使用。
但是,所有隐含意向默认使用 CATEGORY_DEFAULT
进行定义。
用 <category>
元素在您的意向过滤器中指定此内容。
<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"/> <data android:mimeType="image/*"/> </intent-filter> </activity>
处理您的Activity中的 intent
为了决定在您的Activity执行哪种操作,您可读取用于开始Activity的 Intent
。
当您的Activity开始时,调用 getIntent()
检索开始Activity的 Intent
。您可以在Activity生命周期的任何时间执行此操作,但您通常应在早期回调时(比如, onCreate()
或 onStart()
)执行。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Get the intent that started this activity Intent intent = getIntent(); Uri data = intent.getData(); // Figure out what to do based on the intent type if (intent.getType().indexOf("image/") != -1) { // Handle intents with image data ... } else if (intent.getType().equals("text/plain")) { // Handle intents with text ... } }
返回结果
如果您想要向调用您的Activity的Activity返回结果,只需调用 setResult()
指定结果代码和结果 Intent
。当您的操作完成且用户应返回原始Activity时,调用 finish()
关闭(和销毁)您的Activity。 例如:
// Create intent to deliver some kind of result data Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri"); setResult(Activity.RESULT_OK, result); finish()
注意:结果默认设置为
RESULT_CANCELED
。因此,如果用户在完成操作动作或设置结果之前按了返回按钮,原始Activity会收到“已取消”的结果。
如果您只需返回指示若干结果选项之一的整数,您可以将结果代码设置为大于 0 的任何值。 如果您使用结果代码传递整数,并且您无需包含 Intent
,您可以调用 setResult()
并且仅传递结果代码。 例如:
setResult(RESULT_COLOR_RED);
finish();