Intent
Intent有三种基本的使用场景。
- 启动一个Activity。
- startActivity(),无法从新Activity获取结果。
- startActivityForResut() ,然后重写 onActivityResult() 获取结果。
- 启动一个Service
- startService() ,启动一个服务执行一项操作,比如下载一个文件。
- bindService()
- 发送broadcast
- sendBroadcast()
- sendOrderedBroadcast()
- sendStickBroadcast()
Intent 类型
有两种Intent
- 显式Intent(Explicit Intent)
在Intent中指定组件名称(class的完全限定名),通常用来启动app内部的组件。比如启动一个Activity响应用户的action,或者启动一个Service在后台下载一个文件。 - 隐式Intent (Implicit Intent)
不指定组件名称,而是声明一个通用的动作(action),允许另一个应用中的组件来处理这个动作。比如可使用另一个应用来在地图上显示用户位置。
如果创建了一个显式Intent来启动Activity或Service。系统会立即启动Intent中指定的组件。
如果创建了一个隐式Intent,系统通过将所有应用的清单文件(manifest file)中声明的intent filter和制定的Intent作比较,从而找到合适的组件,如果有个多个匹配结果,会弹出一个对话框让用户选择要执行的组件。
注意: 为了安全,启动Service时应该使用显式Intent,并且不要为自己的Service声明intent filter。从Android 5.0 (API Level 21)开始,如果bindService()中使用了隐式Intent,会抛出异常。
构建Intent
Intent 包括如下信息:
- 组件名称(component name)
指定了要启动的组件。指定组件名称就是显式Intent,否则是隐式Intent。 动作(action),String类型
指定了要执行的动作(如view或pick)。 Intent类中包含了一些常量定义了通用的Action。其他类中也定义了一些Action,比如Settings类。
如果想自定义Action。需要定义一个常量定义,并且这个常量值应该以包名作前缀。如:static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";数据(Data)
setData() ,指向要执行动作的数据的URI
setType() ,指定数据的MIME Type
setDataAndType() ,同时指定URI和MIME Type,不能通过两次setData()和setType()来代替本方法。- 类别(Category),String类型,指定了要处理该Intent的组件的种类。一个Intent可包含多个category,但是大多少Intent不需要Category。
可调用addCategory()指定Category。
常见的Category有CATEGORY_BROWSABLE,CATEGORY_LAUNCHER - 额外数据(Extras)
可putExtra()添加额外数据,也可创建一个包括所有额外数据的Bundle对象,然后调用putExtras()。 - 标识(Flag)
指定了Android System如何运行一个Activity。
显示Intent示例
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);
隐式Intent示例
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);
}
强制选择App
系统自带的Chooser可设置默认值,如果不需要这种行为。当有多个Activity匹配时,可强制弹出Chooser。
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
<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>