文章转载禁止用于商业用途,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处莫高雷草原以及作者@JiongBull。
访问Android API指南目录索引查看全部翻译
常用intent
intent可以让你启动其他应用的activity,你只需在Intent对象里描述你想要执行的操作就可以了(比如“查看地图”或“拍照“)。这种类型的intent被称为隐式intent,因为它不是指定要启动的应用组件,而是指定action和提供执行action处理的一些数据。
当你调用startActivity()
或startActivityForResult()
并传参隐式intent时,系统会解析该intent(resolves the intent)给能处理该intent的应用,启动相关的Activity
。如果不止一个应用可以处理该intent,系统会给用户显示一个对话框,让用户来选择使用哪个应用。
这篇文档描述了一些隐式intent,你可以使用它们来执行常用操作,按照处理intent的应用类型进行归类。每个章节还介绍了如何通过创建intent filter来告诉系统你的应用有处理相同操作的能力。
注意:如果当前设备上没有可以接收某个隐式intent的应用,那么你的应用在调用startActivity()时就会崩溃掉。为了验证是否存在能接收该intent的应用,请对你的Intent对象调用resolveActivity()。如果结果是非null的,说明至少有一个应用可以处理该intent,调用startActivity()是安全的。如果结果是null,那么你不应该使用该intent,并且如果可能的话,你应该关闭那些会调用该intent的功能。
如果你还不熟悉如何创建intent和intent filter,你应该先阅读Intents and Intent Filters。
要了解如何从开发主机上使用这篇文档中列举的intent,请参阅Verify Intents with the Android Debug Bridge。
Google Now
Google Now使用这篇文档中列举的一些intent来响应语音命令。更多信息,请参阅Intents Fired by Google Now。
要创建一个新的闹钟,请使用ACTION_SET_ALARM
action并使用下面的extra设置诸如时间和信息等闹钟的详细信息。
注意:小时、分钟和信息extra只有在Android 2.3(API级别9)或更高的平台上可用。其他的extra是在后续版本的平台上引入的。
ACTION_SET_ALARM
EXTRA_HOUR
EXTRA_MINUTES
EXTRA_MESSAGE
EXTRA_DAYS
ArrayList
。每天都必须使用 Calendar类中定义的整型值来表示,例如
MONDAY
。
如果是一次性闹钟,请不要指定该extra。
EXTRA_RINGTONE
content:
类型的URI,用来指定闹钟使用的铃声,如果不需要铃声的话,使用 VALUE_RINGTONE_SILENT。
如果要使用默认铃声,请不要指定该extra。
EXTRA_VIBRATE
EXTRA_SKIP_UI
intent事例:
public void createAlarm(String message, int hour, int minutes) {
Intent intent = new Intent(AlarmClock.ACTION_SET_ALARM)
.putExtra(AlarmClock.EXTRA_MESSAGE, message)
.putExtra(AlarmClock.EXTRA_HOUR, hour)
.putExtra(AlarmClock.EXTRA_MINUTES, minutes);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
为了调用ACTION_SET_ALARM
intent,你的应用必须拥有SET_ALARM
权限:
android:name="com.android.alarm.permission.SET_ALARM" />
intent filter事例:
...>
android:name="android.intent.action.SET_ALARM" />
android:name="android.intent.category.DEFAULT" />
要创建一个倒计时计时器,请使用ACTION_SET_TIMER
action并使用下面的extra设置诸如持续时长等计时器详细信息。
注意:该intent时从Android 4.4(API级别19)开始引入的。
ACTION_SET_TIMER
EXTRA_LENGTH
EXTRA_MESSAGE
EXTRA_SKIP_UI
intent事例:
public void startTimer(String message, int seconds) {
Intent intent = new Intent(AlarmClock.ACTION_SET_TIMER)
.putExtra(AlarmClock.EXTRA_MESSAGE, message)
.putExtra(AlarmClock.EXTRA_LENGTH, seconds)
.putExtra(AlarmClock.EXTRA_SKIP_UI, true);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
为了调用ACTION_SET_TIMER
intent,你的应用必须拥有SET_ALARM
权限:
android:name="com.android.alarm.permission.SET_ALARM" />
intent filter事例:
...>
android:name="android.intent.action.SET_TIMER" />
android:name="android.intent.category.DEFAULT" />
要显示闹钟列表,请使用ACTION_SHOW_ALARMS
action。
虽然会调用该intent的应用不会很多(它主要是给系统应用使用的),任何有闹钟功能的应用都应该实现该intent filter,以便能显示当前所有的闹钟列表。
注意:该intent是从Android 4.4(API级别19)开始引入的。
ACTION_SHOW_ALARMS
intent filter事例:
...>
android:name="android.intent.action.SHOW_ALARMS" />
android:name="android.intent.category.DEFAULT" />
为了在用户的日历中添加一个新的时间,请使用ACTION_INSERT
action并用Events.CONTENT_URI来指定data URI。你可以使用下面定义的extra来指定多种事件的详情。
ACTION_INSERT
Events.CONTENT_URI
"vnd.android.cursor.dir/event"
EXTRA_EVENT_ALL_DAY
EXTRA_EVENT_BEGIN_TIME
EXTRA_EVENT_END_TIME
TITLE
DESCRIPTION
EVENT_LOCATION
EXTRA_EMAIL
可以使用在CalendarContract.EventsColumns类中定义的常量来指定更多的事件细节。
intent事例:
public void addEvent(String title, String location, Calendar begin, Calendar end) {
Intent intent = new Intent(Intent.ACTION_INSERT)
.setData(Events.CONTENT_URI)
.putExtra(Events.TITLE, title)
.putExtra(Events.EVENT_LOCATION, location)
.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, begin)
.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, end);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="android.intent.action.INSERT" />
android:mimeType="vnd.android.cursor.dir/event" />
android:name="android.intent.category.DEFAULT" />
为了打开相机应用并接收到返回的照片或视频,请使用ACTION_IMAGE_CAPTURE
或ACTION_VIDEO_CAPTURE
action。记得在EXTRA_OUTPUT extra中指定你想要相机保存照片或视频的位置。
ACTION_IMAGE_CAPTURE
或ACTION_VIDEO_CAPTURE
EXTRA_OUTPUT
当焦点重新从相机应用返回到你的activity时(你的应用会接收到onActivityResult()回调),你可以从你在EXTRA_OUTPUT值里指定的URI位置访问那些照片和视频。
注意:当你使用ACTION_IMAGE_CAPTURE
来拍照时,相机可能会在结果Intent里返回照片的一个缩小尺寸的拷贝(缩略图),存储在名为”data”的extra中的Bitmap里。
intent事例:
static final int REQUEST_IMAGE_CAPTURE = 1;
static final Uri mLocationForPhotos;
public void capturePhoto(String targetFilename) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.withAppendedPath(mLocationForPhotos, targetFilename);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bitmap thumbnail = data.getParcelable("data");
// 处理保存在mLocationForPhotos中的全尺寸照片
...
}
}
更多关于如何使用intent拍照的信息,包括如何为输出路径创建合适的Uri
,请阅读Taking Photos Simply or Taking Videos Simply。
intent filter事例:
...>
android:name="android.media.action.IMAGE_CAPTURE" />
android:name="android.intent.category.DEFAULT" />
在处理该intent时,你的activity应该检查传入Intent中的EXTRA_OUTPUT
extra,然后把捕获的图片或视频保存在extra指定的路径中,最后调用setResult(),并传入那个在”data” extra中包含压缩缩略图的Intent。
要打开只有拍照模式的相机应用,请使用INTENT_ACTION_STILL_IMAGE_CAMERA
action。
INTENT_ACTION_STILL_IMAGE_CAMERA
intent事例:
public void capturePhoto() {
Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent);
}
}
intent filter事例:
...>
android:name="android.media.action.STILL_IMAGE_CAMERA" />
android:name="android.intent.category.DEFAULT" />
要打开只有录制模式的相机应用,请使用INTENT_ACTION_VIDEO_CAMERA
action。
INTENT_ACTION_VIDEO_CAMERA
intent事例:
public void capturePhoto() {
Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent);
}
}
intent filter事例:
...>
android:name="android.media.action.VIDEO_CAMERA" />
android:name="android.intent.category.DEFAULT" />
要让用户选择联系人并让你的应用访问所有的联系人信息,请使用ACTION_PICK
action并把MIME类型指定为Contacts.CONTENT_TYPE
。
在回传给你的onActivityResult()
回调中的结果Intent
中,包含了指向被选择联系人的content:
URI。响应的应用还会给你的应用授予使用Contacts Provider读取联系人信息的临时权限,尽管你的应用没有包含READ_CONTACTS
权限。
提示:如果你只需要访问联系人的部分信息,比如电话号码和电子邮件地址,请参阅下一章节select specific contact data。
ACTION_PICK
Contacts.CONTENT_TYPE
intent事例:
static final int REQUEST_SELECT_CONTACT = 1;
public void selectContact() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_SELECT_CONTACT);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_SELECT_CONTACT && resultCode == RESULT_OK) {
Uri contactUri = data.getData();
// 处理存储在contactUri中被选中的联系人信息
...
}
}
更过关于在拥有联系人URI的情况下如何获取联系人详细内容的信息,请参阅Retrieving Details for a Contact。请牢记, 当你使用上面的intent从联系人URI中抽取信息时,你不需要READ_CONTACTS
权限就能读取那个联系人的详细信息了。
要想使用户选择联系人的特定信息,比如电话号码、电子邮件地址或其他数据类型,请使用ACTION_PICK
action并使用下面列举的某个content type来指定MIME类型, 比如CommonDataKinds.Phone.CONTENT_TYPE
来获取联系人的电话号码。
如果你只需要从通讯录中获取某种类型的数据,使用ContactsContract.CommonDataKinds类来指定CONTENT_TYPE
比使用Contacts.CONTENT_TYPE(就像前一章节展示的那样)更高效,因为返回的结果可以让你直接访问目标数据,而不需要对Contacts Provider执行更多复杂的查询。
在回传给你的onActivityResult()回调中的结果Intent
中,包含了指向被选中联系人数据的content:
URI。响应的应用还会给你的应用授予读取联系人数据的临时权限,尽管你的应用没有包含READ_CONTACTS
权限。
ACTION_PICK
CommonDataKinds.Phone.CONTENT_TYPE
CommonDataKinds.Email.CONTENT_TYPE
CommonDataKinds.StructuredPostal.CONTENT_TYPE
或者是ContactsContract里的其他CONTENT_TYPE
值。
intent事例:
static final int REQUEST_SELECT_PHONE_NUMBER = 1;
public void selectContact() {
// 启动一个activity供用户从通讯录中选取一个电话号码
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType(CommonDataKinds.Phone.CONTENT_TYPE);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_SELECT_PHONE_NUMBER);
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_SELECT_PHONE_NUMBER && resultCode == RESULT_OK) {
// 获取URI并在content provider中查询该电话号码
Uri contactUri = data.getData();
String[] projection = new String[]{CommonDataKinds.Phone.NUMBER};
Cursor cursor = getContentResolver().query(contactUri, projection,
null, null, null);
// 如果返回的游标有效,获取电话号码
if (cursor != null && cursor.moveToFirst()) {
int numberIndex = cursor.getColumnIndex(CommonDataKinds.Phone.NUMBER);
String number = cursor.getString(numberIndex);
// 处理电话号码
...
}
}
}
要显示一个已知联系人的相信信息,请使用ACTION_VIEW
action并在intent data中使用content:
URI指定联系人。
获取联系人URI的方法主要有两种:
ACTION_VIEW
content:
intent事例:
public void viewContact(Uri contactUri) {
Intent intent = new Intent(Intent.ACTION_VIEW, contactUri);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
要编辑一个已有的联系人,请使用ACTION_EDIT
action,在intent data中使用content:
URI来指定联系人,并且使用ContactsContract.Intents.Insert里的常量在extra中指定所有已知的联系人信息。
获取联系人URI的方法主要有两种:
ACTION_EDIT
content:
ContactsContract.Intents.Insert
中还定义了其他extra,你可以用来填充联系人的详细信息。
intent事例:
public void editContact(Uri contactUri, String email) {
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setData(contactUri);
intent.putExtra(Intents.Insert.EMAIL, email);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
更多关于如何编辑联系人的信息,请参阅Modifying Contacts Using Intents。
要添加一个新的联系人,请使用ACTION_INSERT
action,用Contacts.CONTENT_TYPE
指定MIME类型,并且使用ContactsContract.Intents.Insert里的常量在extra中指定所有已知的联系人信息。
ACTION_INSERT
Contacts.CONTENT_TYPE
ContactsContract.Intents.Insert
中定义了许多extra。
intent事例:
public void insertContact(String name, String email) {
Intent intent = new Intent(Intent.ACTION_INSERT);
intent.setType(Contacts.CONTENT_TYPE);
intent.putExtra(Intents.Insert.NAME, name);
intent.putExtra(Intents.Insert.EMAIL, email);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
更多关于如何新建一个联系人的信息,请参阅Modifying Contacts Using Intents。
要编写一封电子邮件,请根据是否包含附件选择下面的action,并且在intent中使用下面列举的extra键指定电子邮件的详细信息,例如收件人和主题等。
ACTION_SENDTO
(针对不带附件)或ACTION_SEND
(针对带一个附件)或ACTION_SEND_MULTIPLE
(针对带多个附件)
PLAIN_TEXT_TYPE
("text/plain")
"*/*"
Intent.EXTRA_EMAIL
Intent.EXTRA_CC
Intent.EXTRA_BCC
Intent.EXTRA_SUBJECT
Intent.EXTRA_TEXT
Intent.EXTRA_STREAM
Uri
。如果使用的是
ACTION_SEND_MULTIPLE
action,那么这里应该使用包含多个 Uri对象的 ArrayList替代。
intent事例:
public void composeEmail(String[] addresses, String subject, Uri attachment) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_EMAIL, addresses);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
intent.putExtra(Intent.EXTRA_STREAM, attachment);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
如果你想确保你的intent只会被电子邮件应用处理(而不是其他文本消息应用或社交应用),那么请使用ACTION_SENDTO
action并且把data scheme设置为"mailto:”
。例如:
public void composeEmail(String[] addresses, String subject) {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:")); // 只有电子邮件应用可以处理
intent.putExtra(Intent.EXTRA_EMAIL, addresses);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="android.intent.action.SEND" />
android:type="*/*" />
android:name="android.intent.category.DEFAULT" />
android:name="android.intent.action.SENDTO" />
android:scheme="mailto" />
android:name="android.intent.category.DEFAULT" />
要请求用户选择某个文件,例如文档或图片,然后把引用返回给你的应用,请使用ACTION_GET_CONTENT
action并指定你期望的MIME类型。返回给你应用的文件引用对你activity当前的生命周期来说是瞬时的,所以如果你想要晚点再访问的话,你必须把它复制一个拷贝文件中以供晚点访问。这个intent也允许用户在当前进程中创建新的文件(例如,用户可以不选取已存在的照片,而是使用相机拍照)。
在回传给你的onActivityResult()
方法中的结果Intent
中,包含指向文件的URI数据。该URI可能是任何类型的,例如http:
URI,file:
URI或content:
URI。然而,如果你想把可选文件限制为只能通过content provider(一种content:
URI)访问并且可以作为文件流给openFileDescriptor()使用,那么你应该把CATEGORY_OPENABLE添加到你的intent中。
在Android 4.3(API级别18)和更高版本的平台上,你还可以通过把EXTRA_ALLOW_MULTIPLE添加到intent并设置为true来让用户可以选择多个文件。然后你可以在getClipData()方法返回的ClipData对象中访问每个被选中的文件。
ACTION_GET_CONTENT
EXTRA_ALLOW_MULTIPLE
EXTRA_LOCAL_ONLY
CATEGORY_OPENABLE
获取照片的intent事例:
static final int REQUEST_IMAGE_GET = 1;
public void selectImage() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_IMAGE_GET);
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_GET && resultCode == RESULT_OK) {
Bitmap thumbnail = data.getParcelable("data");
Uri fullPhotoUri = data.getData();
// 处理保存在ullPhotoUri中的图片信息
...
}
}
返回照片的intent filter事例:
...>
android:name="android.intent.action.GET_CONTENT" />
android:type="image/*" />
android:name="android.intent.category.DEFAULT" />
android:name="android.intent.category.OPENABLE" />
当运行在Android 4.4或更高版本的平台上时,可以不像前面打开文件那样必须在应用中复制一份文件拷贝(通过使用ACTION_GET_CONTENT action),而是可以请求打开其他应用管理的文件,只要使用ACTION_OPEN_DOCUMENT
action并指定MIME类型即可。同样可以使用ACTION_CREATE_DOCUMENT action来让用户创建一个你的应用可编写的新的文档。例如,ACTION_CREATE_DOCUMENT intent不是从已存在的PDF文档中选取,而是让用户选择他们想在哪里创建新的文档(在其他管理文档存储的应用中),然后你的应用就会接收到URI位置,它描述了你可以编写的新文档的位置。
然而通过ACTION_GET_CONTENT action在回传给你的onActivityResult()方法的intent中,可能返回一个是任何类型的URI,但是通过ACTION_OPEN_DOCUMENT
和ACTION_CREATE_DOCUMENT
返回的结果intent却总是指定了被选中的文件的格式,content:
URI,可以通过DocumentsProvider来回溯。你可以使用openFileDescriptor()打开文件,使用DocumentsContract.Document里的列查询它的详细信息。
返回的URI给你的应用授予了长时间读取该文件的权限(也可能是编写权限)。所以当你想读取一个已存在的文件并且不想在你的应用中复制一份拷贝,或者你想在某个地方打开并编辑一个文件时,ACTION_OPEN_DOCUMENT
action更有用(而不是使用ACTION_GET_CONTENT)。
通过在intent中添加EXTRA_ALLOW_MULTIPLE并赋值true,你就能让用户选择多个文件了。如果用户只选择了一项,那么你可以直接从getData()获取该项目。如果用户选中了多项,那么getData()会返回null,你必须通过getClipData()来获取ClipData对象,然后从中获取每个项目。
注意:你的intent必须制定MIME类型,必须声明CATEGORY_OPENABLE
category。如果合适的话,你可以通过把MIME类型数组指定给EXTRA_MIME_TYPES
extra来添加多个MIME类型,如果你要这么做的话,必须在setType()中设置主要的MIME类型为"*/*”
。
ACTION_OPEN_DOCUMENT
或ACTION_CREATE_DOCUMENT
EXTRA_MIME_TYPES
"*/*”
。
EXTRA_ALLOW_MULTIPLE
EXTRA_TITLE
ACTION_CREATE_DOCUMENT
时来指定初始化的文件名称。
EXTRA_LOCAL_ONLY
CATEGORY_OPENABLE
获取照片的intent事例:
static final int REQUEST_IMAGE_OPEN = 1;
public void selectImage() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("image/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
// 只有系统能接收到这个ACTION_OPEN_DOCUMENT,所以不需要测试了。
startActivityForResult(intent, REQUEST_IMAGE_OPEN);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_OPEN && resultCode == RESULT_OK) {
Uri fullPhotoUri = data.getData();
// 处理保存在fullPhotoUri中的未压缩照片。
...
}
}
第三方应用实际上时不能响应使用ACTION_OPEN_DOCUMENT
action的intent。系统会接收到这个intent,然后在一个统一的用户界面上显示来自各种应用的可用文件。
要在这个UI中显示你应用的文件并用户其他应用可以打开它们,你必须实现一个DocumentsProvider
,然后包含一个名为PROVIDER_INTERFACE
("android.content.action.DOCUMENTS_PROVIDER"
)的intent filter。例如:
...
android:grantUriPermissions="true"
android:exported="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
android:name="android.content.action.DOCUMENTS_PROVIDER" />
更多关于如何使你的应用管理的文件可以从其他应用中打开的信息,请参阅theStorage Access Framework指南。
要追踪骑单车,请使用ACTION_TRACK
action和"vnd.google.fitness.activity/biking"
MIME类型,并且在开始时把EXTRA_STATUS
extra设置为STATUS_ACTIVE
,在结束时设置为STATUS_COMPLETED。
ACTION_TRACK
"vnd.google.fitness.activity/biking"
EXTRA_STATUS
STATUS_ACTIVE
,结束时设置为
STATUS_COMPLETED
。
intent事例:
public void startBikeRide() {
Intent intent = new Intent(FitnessIntents.ACTION_TRACK)
.setType("vnd.google.fitness.activity/biking")
.putExtra(FitnessIntents.EXTRA_STATUS, FitnessIntents.STATUS_ACTIVE);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="vnd.google.fitness.TRACK" />
android:mimeType="vnd.google.fitness.activity/biking" />
android:name="android.intent.category.DEFAULT" />
要追踪跑步,请使用ACTION_TRACK
action和"vnd.google.fitness.activity/running"
MIME类型,并且在开始时把EXTRA_STATUS
extra设置为STATUS_ACTIVE
,在结束时设置为STATUS_COMPLETED
。
ACTION_TRACK
"vnd.google.fitness.activity/running"
EXTRA_STATUS
STATUS_ACTIVE
,结束时设置为
STATUS_COMPLETED
。
intent事例:
public void startRun() {
Intent intent = new Intent(FitnessIntents.ACTION_TRACK)
.setType("vnd.google.fitness.activity/running")
.putExtra(FitnessIntents.EXTRA_STATUS, FitnessIntents.STATUS_ACTIVE);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="vnd.google.fitness.TRACK" />
android:mimeType="vnd.google.fitness.activity/running" />
android:name="android.intent.category.DEFAULT" />
要追踪锻炼,请使用ACTION_TRACK
action和"vnd.google.fitness.activity/other"
MIME类型,并且在开始时把STATUS_ACTIVE
设置为STATUS_ACTIVE
,在结束时设置为STATUS_COMPLETED
。
ACTION_TRACK
"vnd.google.fitness.activity/other"
EXTRA_STATUS
STATUS_ACTIVE
,结束时设置为
STATUS_COMPLETED。
intent事例:
public void startWorkout() {
Intent intent = new Intent(FitnessIntents.ACTION_TRACK)
.setType("vnd.google.fitness.activity/other")
.putExtra(FitnessIntents.EXTRA_STATUS, FitnessIntents.STATUS_ACTIVE);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="vnd.google.fitness.TRACK" />
android:mimeType="vnd.google.fitness.activity/other" />
android:name="android.intent.category.DEFAULT" />
要显示用户的心率,请使用ACTION_VIEW
action和"vnd.google.fitness.data_type/com.google.heart_rate.bpm"
MIME 类型。
ACTION_VIEW
"vnd.google.fitness.data_type/com.google.heart_rate.bpm"
intent事例:
public void showHeartRate() {
Intent intent = new Intent(FitnessIntents.ACTION_VIEW)
.setType("vnd.google.fitness.data_type/com.google.heart_rate.bpm");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="vnd.google.fitness.VIEW" />
android:mimeType="vnd.google.fitness.data_type/com.google.heart_rate.bpm" />
android:name="android.intent.category.DEFAULT" />
要显示用户的步数,请使用ACTION_VIEW
action和"vnd.google.fitness.data_type/com.google.step_count.cumulative"
MIME类型。
ACTION_VIEW
"vnd.google.fitness.data_type/com.google.step_count.cumulative"
intent事例:
public void showStepCount() {
Intent intent = new Intent(FitnessIntents.ACTION_VIEW)
.setType("vnd.google.fitness.data_type/com.google.step_count.cumulative");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="vnd.google.fitness.VIEW" />
android:mimeType="vnd.google.fitness.data_type/com.google.step_count.cumulative" />
android:name="android.intent.category.DEFAULT" />
需要叫车,请使用ACTION_RESERVE_TAXI_RESERVATION
action。
注意:在完成action前,应用必须要询问用户得到确定才行。
ACTION_RESERVE_TAXI_RESERVATION
intent事例:
public void callCar() {
Intent intent = new Intent(ReserveIntents.ACTION_RESERVE_TAXI_RESERVATION);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="com.google.android.gms.actions.RESERVE_TAXI_RESERVATION" />
android:name="android.intent.category.DEFAULT" />
要打开地图,请使用ACTION_VIEW
action并使用下面定义的一种scheme在intent data中指定位置信息。
ACTION_VIEW
geo:latitude,longitude
事例:"geo:47.6,-122.3"
geo:latitude,longitude?z=zoom
事例:"geo:47.6,-122.3?z=11"
geo:0,0?q=lat,lng(label)
事例:"geo:0,0?q=34.99,-106.61(Treasure)"
geo:0,0?q=my+street+address
事例:"geo:0,0?q=1600+Amphitheatre+Parkway%2C+CA"
注意:所有传入geo
URI中的字符串都必须进行编码。例如,字符串1st & Pike, Seattle
应该变成1st%20%26%20Pike%2C%20Seattle
。字符串中的空格可以用%20编码,也可以用加号(+)来替代。
intent事例:
public void showMap(Uri geoLocation) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(geoLocation);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="android.intent.action.VIEW" />
android:scheme="geo" />
android:name="android.intent.category.DEFAULT" />
要播放音乐文件,请使用ACTION_VIEW
action并在intent data中指定文件的URI位置。
ACTION_VIEW
file:
content:
http:
"audio/*"
"application/ogg"
"application/x-ogg"
"application/itunes"
intent事例:
public void playMedia(Uri file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(file);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="android.intent.action.VIEW" />
android:type="audio/*" />
android:type="application/ogg" />
android:name="android.intent.category.DEFAULT" />
要根据搜索请求播放音乐,请使用INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH
intent。应用在响应用户播放音乐的语音命令时可能会触发这个intent。接收该intent的应用会在它的播放清单中检索该曲目,在匹配到指定查询的内容时就会播放。
这个intent应该包含EXTRA_MEDIA_FOCUS
字符串extra,它制定了检索模式。例如,检索模式可以指定是搜索艺术家姓名还是歌曲名。
INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH
MediaStore.EXTRA_MEDIA_FOCUS
(必须)
用来指定检索模式(用来指定用户想要查询指定的艺术家、专辑、歌曲或播放列表)。大部分检索模式都需要附加的extra。例如,如果用户感兴趣听某首指定的歌,那么这个intent可能需要三个附加extra:歌曲标题、艺术家和专辑。针对的EXTRA_MEDIA_FOCUS里的值,该intent支持下列检索模式:
"vnd.android.cursor.item/*"
播放任何音乐。接收的应用应该基于智能选测来播放一些音乐,比如用户最近听过的播放列表。
附加extra:
QUERY
(必须) - 空字符串。这个extra是为了向后兼容, 所以需要提供该字段:那些不了解检索模式的已有的应用可以把该intent当做非结构化检索。"vnd.android.cursor.item/*"
根据某个非结构化的检索查询播放指定的歌曲、专辑或类型。如果应用无法辨识用户想听的音乐类型,那就可以使用这种检索模式创建intent。应用应该尽可能的使用更多指定的检索模式。
附加extra:
QUERY
(必须) - 字符串,包含了艺术家、专辑、歌曲名称或风格的组合。Audio.Genres.ENTRY_CONTENT_TYPE
播放指定风格的音乐。
附加extra:
"android.intent.extra.genre
” (必须) - 风格。QUERY
(必须) - 风格。这个extra是为了向后兼容, 所以需要提供该字段:那些不了解检索模式的已有的应用可以把该intent当做非结构化检索。Audio.Artists.ENTRY_CONTENT_TYPE
播放指定艺术家的音乐。
附加extras:
EXTRA_MEDIA_ARTIST
(必须) - 艺术家。"android.intent.extra.genre"
- 风格。QUERY
(必须) - 字符串,包含了艺术家、专辑、歌曲名称或风格的组合。这个extra是为了向后兼容, 所以需要提供该字段:那些不了解检索模式的已有的应用可以把该intent当做非结构化检索。Audio.Albums.ENTRY_CONTENT_TYPE
播放指定专辑的音乐。
附加extra:
EXTRA_MEDIA_ALBUM
(必须) - 专辑。EXTRA_MEDIA_ARTIST
- 艺术家。"android.intent.extra.genre"
- 风格。QUERY
(required) - 字符串,包含了艺术家、专辑、歌曲名称或风格的组合。这个extra是为了向后兼容, 所以需要提供该字段:那些不了解检索模式的已有的应用可以把该intent当做非结构化检索。"vnd.android.cursor.item/audio"
播放指定的歌曲。
附加extras:
EXTRA_MEDIA_ALBUM
- 专辑。EXTRA_MEDIA_ARTIST
- 艺术家。"android.intent.extra.genre"
- 风格。EXTRA_MEDIA_TITLE
(必须) - 歌曲名称。QUERY
(必须) - 字符串,包含了艺术家、专辑、歌曲名称或风格的组合。这个extra是为了向后兼容, 所以需要提供该字段:那些不了解检索模式的已有的应用可以把该intent当做非结构化检索。Audio.Playlists.ENTRY_CONTENT_TYPE
播放指定的播放列表或匹配附加extra指定的标准的播放列表。
附加extras:
EXTRA_MEDIA_ALBUM
- 专辑。EXTRA_MEDIA_ARTIST
- 艺术家。"android.intent.extra.genre"
- 风格。"android.intent.extra.playlist"
- 播放列表。EXTRA_MEDIA_TITLE
- 播放列表参考的歌曲名称。QUERY
(必须) - 字符串,包含了艺术家、专辑、歌曲名称或风格的组合。这个extra是为了向后兼容, 所以需要提供该字段:那些不了解检索模式的已有的应用可以把该intent当做非结构化检索。intent事例:
如果用户想听指定艺术家的音乐,那么检索应用可能生成下面的intent:
public void playSearchArtist(String artist) {
Intent intent = new Intent(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH);
intent.putExtra(MediaStore.EXTRA_MEDIA_FOCUS,
MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE);
intent.putExtra(MediaStore.EXTRA_MEDIA_ARTIST, artist);
intent.putExtra(SearchManager.QUERY, artist);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
android:name="android.intent.category.DEFAULT" />
在处理这个intent时,你的activity应该检查在传入的Intent中EXTRA_MEDIA_FOCUS extra的值来确定检索模式。一旦你的activity辨别出检索模式了,就应该读取那个特定的检索模式对应的附加extra的值。有了这些信息,你的应用就能在自己的曲库中播放那些匹配检索查询条件的歌曲了。例如:
protected void onCreate(Bundle savedInstanceState) {
...
Intent intent = this.getIntent();
if (intent.getAction().compareTo(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH) == 0) {
String mediaFocus = intent.getStringExtra(MediaStore.EXTRA_MEDIA_FOCUS);
String query = intent.getStringExtra(SearchManager.QUERY);
// 根据检索类型而异,下面有些extra可能不可用
String album = intent.getStringExtra(MediaStore.EXTRA_MEDIA_ALBUM);
String artist = intent.getStringExtra(MediaStore.EXTRA_MEDIA_ARTIST);
String genre = intent.getStringExtra("android.intent.extra.genre");
String playlist = intent.getStringExtra("android.intent.extra.playlist");
String title = intent.getStringExtra(MediaStore.EXTRA_MEDIA_TITLE);
// 确定检索模式并使用合适的extra
if (mediaFocus == null) {
// ‘非结构化’检索模式(向后兼容)
playUnstructuredSearch(query);
} else if (mediaFocus.compareTo("vnd.android.cursor.item/*") == 0) {
if (query.isEmpty()) {
// ‘任意’检索模式
playResumeLastPlaylist();
} else {
// ‘非结构化’检索模式
playUnstructuredSearch(query);
}
} else if (mediaFocus.compareTo(MediaStore.Audio.Genres.ENTRY_CONTENT_TYPE) == 0) {
// ‘风格’检索模式
playGenre(genre);
} else if (mediaFocus.compareTo(MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE) == 0) {
// ‘艺术家’检索模式
playArtist(artist, genre);
} else if (mediaFocus.compareTo(MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE) == 0) {
// ‘专辑’检索模式
playAlbum(album, artist);
} else if (mediaFocus.compareTo("vnd.android.cursor.item/audio") == 0) {
// ‘歌曲’检索模式
playSong(album, artist, genre, title);
} else if (mediaFocus.compareTo(MediaStore.Audio.Playlists.ENTRY_CONTENT_TYPE) == 0) {
// ‘播放列表’检索模式
playPlaylist(album, artist, genre, playlist, title);
}
}
}
要打开电话应用并拨号,请使用ACTION_DIAL
action并使用下面定义的URI scheme指定电话号码。当电话应用打开时,它已经显示了该电话号码,但是用户必须按下拨号键才会开始拨号。
要想直接拨打电话,请使用ACTION_CALL
action并使用下面定义的URI scheme指定电话号码。 当电话应用打开时,它就直接拨号了,用户不需要再去按拨号键了。
ACTION_CALL
action需要你在你的manifest文件中添加CALL_PHONE
权限:
android:name="android.permission.CALL_PHONE" />
ACTION_DIAL
- 打开拨号或电话应用。ACTION_CALL
- 直接拨号(需要CALL_PHONE
权限)tel:
voicemail:
合法的电话号码是像the IETF RFC 3966中定义的那样。下面列举一些合法的事例:
tel:2125551212
tel:(212) 555 1212
电话拨号应用擅长规范格式,例如电话号码。所以在Uri.parse()方法中并没有要求使用严格定义的scheme。然而,如果你没有试过某个scheme或者不确定它能否被处理,请换用Uri.fromParts()
。
intent事例:
public void dialPhoneNumber(String phoneNumber) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + phoneNumber));
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
要支持在你应用的上下文里搜索,请像下面的intent filter事例那样在你的应用中使用SEARCH_ACTION
action声明intent filter。
"com.google.android.gms.actions.SEARCH_ACTION"
QUERY
intent filter事例:
android:name=".SearchActivity">
android:name="com.google.android.gms.actions.SEARCH_ACTION"/>
android:name="android.intent.category.DEFAULT"/>
要使用网络搜索,请使用ACTION_WEB_SEARCH
action并在SearchManager.QUERY extra中指定要搜索的字符串。
ACTION_WEB_SEARCH
SearchManager.QUERY
intent事例:
public void searchWeb(String query) {
Intent intent = new Intent(Intent.ACTION_SEARCH);
intent.putExtra(SearchManager.QUERY, query);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
当你的应用需要打开系统设置中的窗口让用户修改的时候,请在intent action中使用对应的action名称打开设置窗口。
ACTION_SETTINGS
ACTION_WIRELESS_SETTINGS
ACTION_AIRPLANE_MODE_SETTINGS
ACTION_WIFI_SETTINGS
ACTION_APN_SETTINGS
ACTION_BLUETOOTH_SETTINGS
ACTION_DATE_SETTINGS
ACTION_LOCALE_SETTINGS
ACTION_INPUT_METHOD_SETTINGS
ACTION_DISPLAY_SETTINGS
ACTION_SECURITY_SETTINGS
ACTION_LOCATION_SOURCE_SETTINGS
ACTION_INTERNAL_STORAGE_SETTINGS
ACTION_MEMORY_CARD_SETTINGS
请参阅Settings
文档了解更多可用的设置窗口。
intent事例:
public void openWifiSettings() {
Intent intent = new Intent(Intent.ACTION_WIFI_SETTINGS);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
要编写一条SMS或MMS文本消息,请使用下面其中一种intent action,并使用下面列举的extra键来指定消息细节,例如电话号码、主题、消息内容等。
ACTION_SENDTO
或ACTION_SEND
或ACTION_SEND_MULTIPLE
sms:
smsto:
mms:
mmsto:
这些scheme可以用同样的方式处理。
PLAIN_TEXT_TYPE
("text/plain"
)
"image/*"
"video/*"
"subject"
"sms_body"
EXTRA_STREAM
Uri
。如果使用的是
ACTION_SEND_MULTIPLE
action,那么这个extra应该是一个由指向图片/视频的
Uri组成的ArrayList
。
intent事例:
public void composeMmsMessage(String message, Uri attachment) {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setType(HTTP.PLAIN_TEXT_TYPE);
intent.putExtra("sms_body", message);
intent.putExtra(Intent.EXTRA_STREAM, attachment);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
如果你想确保你的intent只能背文本消息应用处理(而不是其他的邮件或社交应用),那么请使用ACTION_SENDTO
action并包含"smsto:"
data scheme。例如:
public void composeMmsMessage(String message, Uri attachment) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setData(Uri.parse("smsto:")); // This ensures only SMS apps respond
intent.putExtra("sms_body", message);
intent.putExtra(Intent.EXTRA_STREAM, attachment);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="android.intent.action.SEND" />
android:type="text/plain" />
android:type="image/*" />
android:name="android.intent.category.DEFAULT" />
注意:如果你正在开发一款SMS/MMS消息应用,为了能在Android 4.4或更高版本的平台上作为系统的默认SMS应用,你必须实现针对许多额外action的intent filter。更多信息,请参阅Telephony
。
要打开网络页面,请使用ACTION_VIEW
action并在intent data中注定网络URL。
ACTION_VIEW
http:
https:
PLAIN_TEXT_TYPE
("text/plain"
)
"text/html"
"application/xhtml+xml"
"application/vnd.wap.xhtml+xml"
intent事例:
public void openWebPage(String url) {
Uri webpage = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, webpage);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
intent filter事例:
...>
android:name="android.intent.action.VIEW" />
android:scheme="http" android:host="www.example.com" />
android:name="android.intent.category.DEFAULT" />
android:name="android.intent.category.BROWSABLE" />
提示:如果你的Android应用提供的功能和你的网站差不多,请为指向你网站的URL指定一个intent filter。然后,如果用户安装了你的应用,那么在邮件或其他网页中打开指向你网站站点的超链接时,会直接打开你的Android应用,而不是你的网页。
要验证你的应用能否响应那些你想要支持的intent,你可以使用adb
工具来发出特定的intent:
adb
发出intent: adb shell am start -a -t -d \
-e -n
例如:
adb shell am start -a android.intent.action.DIAL \
-d tel:555-5555 -n org.example.MyApp/.MyActivity
更多信息,请参阅Using activity manager (am)。
Google Now可以辨识出许多语音命令并为它们发出对应的intent。像这样,如果你的应用声明了相应的intent filter,用户就能通过Google Now语音命令来启动你的应用了。例如,如果你的引用可以设置闹钟(set an alarm)并且你在manifest文件中添加了相应的intent filter,那么当用户需要设置闹钟时,Google Now就能让用户选择你的应用了,如图1所示。
图1. Google Now让用户从支持给定action的已安装应用里挑选。
Google Now识别针对表1所列举的action的语音命令。更多关于每种intent filter声明的信息,请点击相关action描述。
表1. Google Now可以识别的语音命令(Google Search应用v3.6).
类别 | 详情和事例 | Action名称 |
---|---|---|
闹钟 | Set alarm(设置闹钟)
|
AlarmClock.ACTION_SET_ALARM |
Set timer(设置时间)
|
AlarmClock.ACTION_SET_TIMER |
|
联系 | Call a number(拨号)
|
Intent.ACTION_CALL |
健康 | Start/stop a bike ride(开始/结束骑单车)
|
FitnessIntents.ACTION_TRACK |
Start/stop a run(开始/结束跑步)
|
FitnessIntents.ACTION_TRACK |
|
Start/stop a workout(开始/结束锻炼)
|
FitnessIntents.ACTION_TRACK |
|
Show heart rate(显示心率)
|
FitnessIntents.ACTION_VIEW |
|
Show step count(显示步数)
|
FitnessIntents.ACTION_VIEW |
|
本地 | Book a car(叫车)
|
ReserveIntents |
媒体 | Play music from search(搜索并播放音乐)
|
MediaStore |
Take a picture(拍照)
|
MediaStore |
|
Record a video(录视频)
|
MediaStore |
|
搜索 | Search using a specific app(使用指定应用搜索)
|
"com.google.android.gms.actions |
网络浏览器 | Open URL(打开URL)
|
Intent.ACTION_VIEW |