http://developer.android.com/guide/components/intents-filters.html
Intent是一个用来请求来自其它组件行为活动(action)的消息传送类。主要有三个基本用例
- 启动一个activity
通过向startActivity()传入一个Intent启动一个新的activity实例,这个Intent描述需要启动的activity并且携带必须的数据。使用startActivityForResult()来接收回传的结果,你可以接收到结果(一个单独的Intent类)在activity的onActivityResult()回调函数中。 - 启动一个Service
service为一个没有用户界面的在后台运行来执行操作的组件。通过向startService()中传入Intent来启动一个一次性操作的service(如下载操作),Intent描述需要启动的service并且携带必须的数据。你还可以向bindService()方法中传入一个Intent绑定service和其它组件。 - 分发一个广播
广播是一个任何app都可以接受的一个消息。通过向sendBroadcast(), sendOrderedBroadcast(), or sendStickyBroadcast()方法传入Intent来向其它app分发一个广播。
Intent类型
显式Intent
指定具体的名字(完全限定类名)启动一个组件。你可以使用显示intent来在你自己的app中启动一个组件,因为你知道他们的全名。
startActivity(new Intent(this,NextActivity.class));
隐式Intent
你不知道组件的类名,但是知道组件选不出来的一个action,可以启动一个其他app的组件来进行操作。
Intent intent = new Intent(Intent.ACTION_CALL, Uri
.parse("tel:" + phoneNumber));
startActivity(intent);
当你启动一个显式Intent时,系统会立即启动那个组件。
当你启动一个隐式Intent时,Intent会被交付给Android System,Android System会将intent与其他App的清单文件(manifest file)中声明的intent-filter比较,找出最合适的一个,当存在多个可以启动的组件时,会弹出一个对话框让用户选择。
intent-filter为在清单文件中声明,用来指定想要接收的intent。
注意:总是保证用显式Intent启动一个Service,不要使用隐式Intent启动一个Service因为你不能确认Service会响应你的启动,用户也不能看到Service是否被启动。
创建一个Intent
intent需要携带启动组件的信息和接收组件需要执行操作的信数据。
主要的信息包含如下:
- 组件名称
指定组件的完全限定类名来启动一个组件,隐式启动组件基于其他intent信息 (such as the action, data, and category—described below)。可以通过构造器,setComponent(), setClass(), setClassName()来指定组件名称。 Action
action是一个指定执行活动的字符串。
在发送广播的情况下,action产生并且被广播。action主要的决定了剩余的intent结构,特别的包含数据及其他。使用setAction(),或构造器指定它们,你应该使用Intent类或其他框架类定义的action常数,如:ACTION_VIEW:使用它当你有一些信息需要展示给用户看,以最合理的方式查看Intent数据,如网址,电话号码,map中的地址。
ACTION_SEND:使用它当你有一些数据要与其他app分享的时候,如社交app。
//自定义一个Action,保证包含app的包名
static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
Data
数据类型通常被intent action简单的表示出来,如action为ACTION_EDIT,data就应该包含需要编辑文件的URI。
通常需要设置data的MINE类型(表示用什么应用程序打开),例如,需要打开一个图片,但是其URI与音频文件类似,所有应该设置MINE类型帮助系统选出最好的执行组件。有时候,MINE类型可从URI中的到,如data为content:开头的URI,表示data为ContentProvider类型。
分别通过setData(),setType()设置数据URI和MINE类型,通过setDataAndType()设置两者,如果都要设置,使用setDataAndType()而不是分别设置,因为分开设置会使另一个设置无效。Category(分类)
一个包含关于处理intent组件的的额外信息,intent中可以放入任意数量Category,但通常 不需要去设置通过addCategory()设置。CATEGORY_BROWSABLE:表示目标activity可以被一个浏览器的图片,邮箱地址启动来显示一些数据。
CATEGORY_LAUNCHER:表示activity是最初的一个,在应用程序启动时。
这些属性定义了intent的特征,通过这些属性,系统可以找到该启动哪一个组件。除此之外,intent还要携带更多的附加信息
Extras
是一组包含请求需要处理的键值对。通过putExtra()加入数据,包含两个参数,键与值。你也可以声明一个Bundle对象包含所有的数据,将他传入Intent。Intent类声明很多的键值常量,你也可以声明自己的键值。
//记得包含app的包名
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
- Flags
指示系统如何启动一个activity,如这个activity属于哪个任务;启动之后如何运行,如他是否属于最近活动列表。通过setFlags()设置。
显示、隐式Intent例子
// 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);
// Create the text message with a string
//没有使用URI,因为data type已经在Extra中描述了
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType(HTTP.PLAIN_TEXT_TYPE); // "text/plain" MIME type
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(sendIntent);
}
通过使用createChooser()强制显示组件选择窗口,而不是通过默认选择组件。
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);
}
接受隐式Intent
在清单文件的对应组件中声明元素,通过action, data, category属性
一个app组件应该被分出多个filiters,每个表示一个独一无二的功能。如一个画廊app可以分出两个filiters,显示图片和编辑图片。启动这个activity时通过intent中的信息决定他的行为。
通过下列属性指定intent-filiter的类型:
- < action >
声明接收的intent action,指定name属性。 - < data >
声明接收的data,使用一个或多个属性来接收data URI(scheme, host, port, path, etc.)和MINE类型。 - < category >
声明接收的intent 种类,指定name属性。必须包含CATEGORY_DEFAULT,否则没有一个隐式意图会启动这个activity。
<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>
你可以在一个filiter中包含多个<action>, <data>, or <category>。你只需要确认这个组件可以处理任何这些属性和它的组合。当你只要某些特定组合时创建多个filiter。
设置exported属性false可以使一个个组件只被自己这个app打开。
<activity android:name="MainActivity">
<!-- 入口activity -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="ShareActivity">
<!-- 处理SEND action,data属性为文本 -->
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<!-- 也处理SEND action,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>
使用Pending Intent
PendingIntent是对Intent的一个包装,主要目的为赋予其他app权限来操作自己app,PandingIntent以为延迟Intent包含自己app的context。
使用pendingIntent的目的在于它所包含的Intent的操作的执行是需要满足某些条件的。
主要的用法为:
- 声明一个Intent对Notification进行操作时,系统的NotificationManager来执行这个Intent。
- 声明一个Intent对App Widget进行操作时,主屏幕应用来执行这个Intent。
- 声明一个Intent用来处理将来的操作时,系统的AlarmManager来执行这个Intent
//声明启动不同组件的intent
PendingIntent intent;
intent = PendingIntent.getActivity(...);
intent = PendingIntent.getService(...);
intent = PendingIntent.getBroadcast(...)