本文译自:http://developer.android.com/training/basics/intents/filters.html
前面的两课一直关注了故事的一边:从你的应用程序中启动另一个应用程序的Activity。但是如果你的应用能够执行一个可能对另外的应用程序有用的操作,那么你的应用程序就应该准备响应来自其他应用程序的操作请求。例如,如果你创建了一个能够跟用户的朋友共享消息和照片的社区应用,那么你就应该支持ACTION_SEND类型的Intent,以便用户能够启动来自其他应用程序的共享操作,并加载你的应用程序来执行这个操作。
要允许其他的应用程序来启动你的Activity,你需要在你的清单文件的相应的<activity>元素中添加一个<intent-filter>元素。
当你的应用程序被安装到设备上时,系统会识别你的Intent过滤器,并把这个信息添加到一个由所有被安装应用程序所支持的内部的Intent目录中。当一个应用程序用隐含的Intent对象来调用startActivity()或startActivityForResult()方法时,系统就会在这个目录中查找那些Activity能够响应这个Intent的请求。
添加Intent过滤器
为了能够正确的定义你的Activity所能处理的Intent对象,Activity接收的操作和数据应该尽可能在每个被添加的Intent过滤器中进行具体的定义。
如果Activity有一个跟下列Intent对象条件完全匹配的Intent过滤器,系统就会把给定的Intent对象发送给这个Activity:
Action
定义要执行的操作名称(字符串)。通常是由平台定义的一个值,如ACTION_SEND或ACTION_VIEW。
使用过滤器中的<action>元素来指定操作。在这个元素中指定的值必须是该操作完整的字符串名称,而不是API常量。
Data
定义跟该Intent匹配的数据
使用过滤器中的<data>元素来指定数据。使用这个元素中的一个或多个属性,你能够只简单指定MIME类型、URI前缀、URI方案,或者是这些的组合,以及其他的能够接收的数据类型的指示。
注意:如果你不需要声明指定相关数据的Uri(如当你的Activity要处理其他类型的附加数据时,而不是URI),那么就应该只指定android:mimeType属性来声明你的Activity所能处理的数据类型,如text/plain或image/jpeg。
Category
提供两外一种Activity处理Intent对象的方法,通常与用户的手势或其他的位置有关。系统支持几种不同的分类,但是很少被使用。但是默认情况下,所有的隐含的Intent对象都要使用CATEGORY_DEFAULT来定义。
在Intent过滤器中使用<category>元素来指定这个分类信息。
在你的Intent过滤器中,你可以在<intent-filter>元素中嵌套上述对应XML元素来声明你的Activity所能接收的Intent对象的条件。
例如,以下Activity的Intent过滤器的声明,能够处理ACTION_SEND类型的Intent对象,并且数据类型可以是文本或图片:
<activityandroid: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>
每个输入的Intent对象只能指定一个操作和一种数据类型,但是在每个<intent-filter>元素中则可以声明多个<action>、<category>、<data>元素的实例。
如果任何两个操作和数据的行为是相互排斥的,那么你应该给它们建立独立的Intent过滤器,并在每个Intent过滤器中指定其可接收的操作和对应的数据类型。
例如,假设你的Activity可以使用ACTION_SEND和ACTION_SENDTO类型的Intent来处理文本和图片。这种情况下,你就必须给这两个操作分别定义独立的Intent过滤器,因为ACTION_SENDTO类型的Intent对象必须使用数据的Uri来指定收件人的地址,例如:
<activityandroid:name="ShareActivity">
<!-- filter for sending text; accepts SENDTO action with sms URI schemes -->
<intent-filter>
<action android:name="android.intent.action.SENDTO"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="sms" />
<data android:scheme="smsto" />
</intent-filter>
<!-- filter for sending text or images; accepts SEND action and text or image data -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="image/*"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
注意:为了接收隐式的Intent对象,在Intent过滤器中必须包含CATEGORY_DEFAULT分类。如果包含了CATEGORY_DEFAULT分类,startActivity()和startActivityForResult()方法启动的所有的Intent对象就会被处理,否则,隐式的Intent对象就不会被你的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 ...
}
}
返回结果
如果你想要把结果返回给调用者,只需简单的调用setResult()方法来指定具体的结果代码和结果Intent对象。当操作完成后,并要返回到最初的调用者,就要调用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_OK或RESULT_CANCELED。然后根据需要使用一个Intent对象来提供另外的数据。
注意:默认的结果会被设置为RESULT_CANCELED。因此,在操作完成和结果被设定之前,如果用户按下返回按钮,那么初始的Activity就会收到“被取消”的结果。
如果你只是简单的返回一个整数,来指明几个可选结果中的一个,那么你把结果代码设置为任何比0大的值。如果你使用结果代码来发送一个整数,并且不需要包含Intent对象,那么你就可以调用setResult()方法,并且只给它传递一个结果代码。例如:
setResult(RESULT_COLOR_RED);
finish();
在这种情况中,可能的结果很少,因此结果代码可以是本地定义的整数(比0大)。这样在把结果返回给你自己应用程序中的Activity时,就会很好的工作,因为接收结果的Activity可以引用公共的常量来判断结果代码的值。
注意:不需要检查你的Activity是使用startActivity()方法、还是使用startActivityForResult()方法来启动的。如果启动你的Activity期望要有返回结果,那么只需简单的调用setResult()方法就可以了。如果启动Activity调用的是startActivityForResult()方法,那么系统就会把你提供给setResult()方法的结果发送给它,否则,这个结果会被忽略。