1.3 Intent 和 Intent 过滤器 - TomeOkin/Learning-Notes GitHub Wiki
Intent 由 data、action、category、component name(可选)、extra(可选)、flags 等组成,每一部分都可以自定义。
-
data:由 mimeType 和 URI 组成,mimeType 指明媒体类型,比如
text/*
、image/jpeg
。URI 由 scheme、host、port 和 path 属性构成,路径可以使用正则表达式:
<scheme>://<host>:<port>[<path>|<pathPrefix>|<pathPattern>]
比如:https://www.google.com:443
或者content://com.example.project:200/folder/subfolder/etc
小技巧:
android.resource://包名/资源Id
可以访问 resource 文件夹里的内容
-
action:指定要执行的操作类型,比如
ACTION_VIEW
、ACTION_EDIT
、ACTION_SEND
,也可以自定义。 -
category:指定要操作的类别,比如要在启动器显示的意图类别就会设置为
android.intent.category.LAUNCHER
(如果要支持多窗口,还会加上android.intent.category.MULTIWINDOW_LAUNCHER
)。如果要默认匹配,则会加上android.intent.category.DEFAULT
。 -
component name:用在显式意图中,指明处理该意图的 Activity、Service 或 BroadcastReceiver。
-
extra:可以通过
putExtra()
方法往 Intent 里添加内容,或者先添加到Bundle
里,再添加到 Intent 中。 -
flags:对应与启动模式里的 flags。
意图的书写方式有两种,一种是写在 AndroidManifest.xml
的意图过滤器中,表示的是支持处理或想要处理该意图;另一种是直接在代码里使用,以隐式意图的方式启动支持处理该意图的 Activity、Service 或 BroadcastReceiver 或显式指定处理该意图的 Activity、Service 或 BroadcastReceiver。
<activity android:name="MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER"/>
</intent-filter>
</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>
<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>
在代码里使用时,如果要同时设置 Uri 和 mimeType,要使用的是 setDataAndType()
;setData()
会设置 Uri 并清除 mimeType,同样,setType()
会设置 mimeType 并清除 Uri。
// 隐式意图
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_SUBJECT, R.string.share_subject);
i.putExtra(Intent.EXTRA_TEXT, theMessage);
// 显示意图
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);
匹配过程中,如果存在多个过滤器,只需通过其中一个过滤器即可。匹配过滤器时,action 必须至少匹配一项才能通过,category 必须全部都匹配才能通过,data 也只需匹配通过其中一项即可。
系统默认在启动隐式意图时,会自动为 category 加上 CATEGORY_DEFAULT
,故一般情况下,定义 category 时,为了保证能匹配通过,一般 category 都会含有 android.intent.category.DEFAULT
,或者再多一项用于准确匹配。
如果找不到匹配的组件,那么执行 start 操作时,会抛出异常。所以,一般情况下,会先判断是否有支持的组件。
PackageManager
中提供了一系列 query 方法用于查询是否支持的组件,还有 resolve 系列方法用于查询最合适的意图(也可以使用 Intent 的 resolve 系列方法)。如果查询到的意图很多,那么还可以使用启动选择器供用户选择合适的组件。
Intent startupIntent = new Intent(Intent.ACTION_MAIN);
startupIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PackageManager pm = getActivity().getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(startupIntent, 0);
Collections.sort(activities, new Comparator<ResolveInfo>() {
public int compare(ResolveInfo a, ResolveInfo b) {
PackageManager pm = getActivity().getPackageManager();
return String.CASE_INSENSITIVE_ORDER.compare(
a.loadLabel(pm).toString(),
b.loadLabel(pm).toString());
}
});
final Intent pickContact = new Intent(Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI);
PackageManager packageManager = getActivity().getPackageManager();
if (packageManager.resolveActivity(pickContact,
PackageManager.MATCH_DEFAULT_ONLY) == null) {
// do something
}
特别地,resolveActivity
的第二个参数 flags 设置为 PackageManager.MATCH_DEFAULT_ONLY
,指明只检索那些有设置 android.intent.category.DEFAULT
的应用,至于 queryIntentActivities
为什么第二个参数 flags 为什么使用的是 0,原因是作为应用启动 Activity,只需要具备 action 为 android.intent.action.MAIN
且 category 为 android.intent.category.LAUNCHER"
即可启动。
一个封装的 Intent,主要提供给外部应用执行应用自身意图时使用:
- 当用户操作通知时,
NotificationManager
执行该意图。 - 用户操作 App Widget 时,桌面启动器执行该意图。
- 定时任务,AlarmManager 在对应的时间执行该意图。
Intents and Intent Filters 官方文档
《Android 开发艺术探索》
《The Busy Coders Guide to Android Development》
《Android Programming:The Big Nerd Ranch Guide》 最下方两个小 demo