StupidBeauty
Read times:1203Posted at:Thu May 22 21:27:00 2014
- no title specified

安卓开发文档翻译:常用意图,Common Intents

在一个 Intent 对象中说明妳希望进行的一个简单动作(例如"查看一个地图"或"拍摄一张照片"),就可以启动另一个应用中的某个活动(activity)。这种类型的意图被称作 意图,因为它并未指定要启动的应用程序组件,而是指定了一个 动作 action ),并且提供了一些用于执行该动作的 数据 data )。

当妳调用 startActivity() startActivityForResult() 并且给它传递一个隐式意图的时候,系统会 解析 该意图 ,找到一个能够处理该意图的应用,并且启动其中的相应的 活动 。如果有多个应用都能够处理该意图的话,则系统会显示一个对话框,由用户来选择要使用哪个应用处理。

这个页面说明了一些隐式意图,妳可以使用它们来触发常见的动作,这些意图是按照处理它们的应用的类型来组织的。在每个小节中,还会告诉妳,该怎么创建一个 意图过滤 ,以宣称妳的应用可以完成该动作。

警告:如果当前设备上没有任何应用能够处理该隐式意图的话,则,妳的应用在调用 startActivity() 时会崩溃。妳应当先对妳的 Intent 对象调用 resolveActivity() ,以确认是否有任何应用能够处理该意图。如果返回值为非空(non-null),则,最少有一个应用能够处理该意图,那么妳就可以安全地调用 startActivity() 。如果结果为空(null),那么,妳不应当使用该意图,并且,在可能的情况下,禁用掉会触发该意图的特性。

如果妳还不熟悉如何创建意图和意图过滤器的话,那么,妳应当先去阅读一下 意图 和意图过滤器

闹钟

创建一个闹钟

要想创建一个闹钟的话,就使用 ACTION_SET_ALARM 这个动作,并且使用以下定义的额外数据来指定闹钟的详情,例如时间和消息。

注意 在安卓2.3(应用编程接口版本9)系统中,只能使用小时、分钟和消息体这三个额外参数。其它的额外参数是在日后的平台版本中加入的。

动作

ACTION_SET_ALARM

数据 的统一资源标识符

多媒体类型

额外参数

EXTRA_HOUR

闹钟的小时数。

EXTRA_MINUTES

闹钟的分钟数值。

EXTRA_MESSAGE

用于标识该闹钟的一个自定义消息。

EXTRA_DAYS

一个 ArrayList ,其中包含的是,在一个星期中,哪些天是要重复该闹钟的。每个日期都必须以 Calendar 类中的一个整数来声明,例如 MONDAY

对于只响一次的闹钟,不要指定这个额外参数。

EXTRA_RINGTONE

一个 content:类型的统一资源标识符,用于指定该闹钟的铃声,或者使用 VALUE_RINGTONE_SILENT 以表示不要铃声。

要想使用默认的铃声的话,不要指定这个额外参数。

EXTRA_VIBRATE

一个逻辑值,表示,对于这个闹钟,是否要震动。

EXTRA_SKIP_UI

一个逻辑值,表示,对该意图作出响应的那个应用是否应当在设置闹钟时跳过不必要的界面。如果为真,则,目标应用应当跳过任何的确认界面,直接设置好指定的闹钟。

示例意图:

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 意图的话,妳的应用必须拥有 SET_ALARM 权限

<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />

示例意图过滤器:

<activity ...>

<intent-filter>

<action android:name="android.intent.action.SET_ALARM" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

创建一个定时器

要想创建一个倒计时定时器的话,就使用 ACTION_SET_TIMER 动作,并且使用以下定义的额外参数来指定定时器的详细参数,例如持续时间。

注意 这个意图是在安卓4.4(应用编程接口版本19)中加入的。

动作

ACTION_SET_TIMER

数据 的统一资源标识符

多媒体类型

额外参数

EXTRA_LENGTH

该定时器的持续时间,以秒为单位。

EXTRA_MESSAGE

一个自定义消息,用于标识该定时器。

EXTRA_SKIP_UI

一个逻辑值,表示,对该意图作出响应的那个应用是否应当在设置定时器的时候跳过不必要的界面。如果为真,则该应用应当跳过它的确认界面,直接设置好指定的定时器。

示例意图:

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 意图的话,妳的应用必须拥有 SET_ALARM 权限:

<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />

示例意图过滤 器:

<activity ...>

<intent-filter>

<action android:name="android.intent.action.SET_TIMER" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

显示所有的闹钟

要想显示所有闹钟的列表,则使用 ACTION_SHOW_ALARMS 动作。

尽管没有多少应用会调用这个意图(主要是系统应用会调用这个意图),但是,任何一个实现了闹钟功能的应用都应当实现这个意图过滤器,并且显示出当前活跃的闹钟列表作为响应。

注意 这个意图是在安卓4.4(应用编程接口版本19)中加入的。

动作

ACTION_SHOW_ALARMS

数据 的统一资源标识符

多媒体类型

示例意图过滤 器:

<activity ...>

<intent-filter>

<action android:name="android.intent.action.SHOW_ALARMS" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

日历

添加一个日历事件

要想向用户的日历中添加一个新事件的话,则使用 ACTION_INSERT 动作,并且使用 Events.CONTENT_URI 来指定数据的统一资源标识符。然后,妳可以使用以下定义的额外参数来指定各种各样的事件详情。

动作

ACTION_INSERT

数据 的统一资源标识符

Events.CONTENT_URI

多媒体类型

"vnd.android.cursor.dir/event"

额外参数

EXTRA_EVENT_ALL_DAY

一个逻辑值,表示,这个事件是否是一个全天事件。

EXTRA_EVENT_BEGIN_TIME

该事件的起始时间(自纪元元年(epoch)以来的毫秒数)

EXTRA_EVENT_END_TIME

该事件的结束时间(自纪元元年(epoch)以来的毫秒数)

TITLE

该事件的文字标题。

DESCRIPTION

该事件的文字说明。

EVENT_LOCATION

事件的位置。

EXTRA_EMAIL

使用逗号分隔的邮件地址列表,包含着受邀参与者的邮件地址。

可使用 CalendarContract.EventsColumns 类中定义的那些常量来指定更多的事件详情。

示例意图:

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);

}

}

示例意图过滤 器:

<activity ...>

<intent-filter>

<action android:name="android.intent.action.INSERT" />

<data android:mimeType="vnd.android.cursor.dir/event" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

摄像头

拍摄一张照片或一段视频并且返回它

要想启动一个摄像头应用并且接收到拍摄的照片或视频的话,则使用 ACTION_IMAGE_CAPTURE ACTION_VIDEO_CAPTURE 动作。并且,使用 EXTRA_OUTPUT 这个额外参数来指定妳所希望将该照片或视频保存到的目标统一资源标识符位置。

动作

ACTION_IMAGE_CAPTURE
ACTION_VIDEO_CAPTURE

数据 的统一资源标识符模式

多媒体类型

额外参数

EXTRA_OUTPUT

该摄像头应用应当将该照片或视频保存到的目标统一资源标识符位置(以一个 Uri 对象的方式来指定)。

当该摄像头应用成功将焦点返回给妳的活动(妳的应用会收到 onActivityResult() 回调函数)时,妳可以使用之前通过 EXTRA_OUTPUT 值指定的统一资源标识符处访问到该照片或视频。

注意 当妳使用 ACTION_IMAGE_CAPTURE 来拍摄一张照片时,目标摄像头应用可能会在返回的 Intent 中传递一张对于该照片的缩略图,具体就是 "data" 这个额外字段中的一个 Bitmap 对象。

示例意图:

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中的完整尺寸的照片做其它事

...

}

}

欲知更多关于如何使用这个意图来拍摄照片的说明,以及如何针对输出位置创建一个适当的 Uri ,则阅读 简单地拍照 简单地拍摄视频

示例意图过滤器:

<activity ...>

<intent-filter>

<action android:name="android.media.action.IMAGE_CAPTURE" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

当妳在处理这个意图时,应当在妳的活动中检查所传入的 Intent 中包含的额外参数 EXTRA_OUTPUT ,并将拍摄到的图片或视频保存到那个额外参数所指定的位置,最后调用 setResult() ,传入一个 Intent ,其中应当包含一个名为 "data" 的额外参数,该额外参数中储存着一张缩略图。

联系人应用

选中一个联系人

要让用户选中一个联系人并且使得妳的应用程序访问到该联系人的所有相关信息的话,则使用 ACTION_PICK 这个动作,并且将多媒体类型指定为 Contacts.CONTENT_TYPE

在通过 onActivityResult() 回调函数回传给妳的 Intent 结果中,会包含一个指向所选中联系人的 content: 形式的统一资源标识符。这个回复信息会临时允许妳的应用使用 联系人提供者 应用编程接口来读取那个联系人的信息,即使妳的应用未包含这 READ_CONTACTS 个权限也不会被阻止。

提示:如果妳只需要获取联系人信息中的某个特定的属性的话,比如说一个电话号码或者邮件地址,则,应当参考下一小节中关于如何 选中特定的联系人数据 的说明。

动作

ACTION_PICK

数据 的统一资源标识符模式

多媒体类型

Contacts.CONTENT_TYPE

示例意图:

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处保存的那个已选中的联系人做某些操作

...

}

}

欲知如何在已经拥有了某个联系人的统一资源标识符的情况下获取该联系人的详细信息,则阅读 获取一个联系人的详细信息 。记住,当妳使用以上说明的这个意图来获取该联系人的统一资源标识符的时候,妳 并不 需要 READ_CONTACTS 权限就可以读取该联系人的详细信息。

特定的联系人数据

要想让用户选择某个联系人的某个特定信息的话,例如电话号码、邮件地址或其它数据类型,则使用 ACTION_PICK 动作,并且将多媒体类型指定为以下列出的内容类型中的某一个,例如 CommonDataKinds.Phone.CONTENT_TYPE 表示获取该联系人的电话号码。

如果妳只需要获取关于某个联系人的一种类型的数据,那么,将 CONTENT_TYPE 指定为 ContactsContract.CommonDataKinds 类中的某个类型,比指定为 Contacts.CONTENT_TYPE (上一小节中就是那么使用的)更高效。因为,这样所返回的结果中直接包含了妳想要的数据,不需要再对 内容提供者 发起一次复杂的查询。

在通过onActivityResult()回调函数回传给妳的Intent结果中,会包含一个指向所选中联系人的数据的content:形式的统一资源标识符。这个回复信息会临时允许妳的应用读取那个联系人数据,即使妳的应用未包含这READ_CONTACTS个权限也不会被阻止。

动作

ACTION_PICK

数据 的统一资源标识符模式

多媒体类型

CommonDataKinds.Phone.CONTENT_TYPE

从联系人列表中选中某个电话号码。

CommonDataKinds.Email.CONTENT_TYPE

从联系人列表中选中某个邮件地址。

CommonDataKinds.StructuredPostal.CONTENT_TYPE

从联系人列表中选中某个邮政地址。

ContactsContract 中还有更多可用的 CONTENT_TYPE 值。

示例意图:

static final int REQUEST_SELECT_PHONE_NUMBER = 1;

public void selectContact() {

// 启动一个活动,让用户从联系人列表中选择一个电话号码

Intent intent = new Intent(Intent.ACTION_PICK);

intent.setType(CommonDataKinds.Phone.CONTENT_TYPE);

if (intent.resolveActivity(getPackageManager()) != null) {

startActivityForResult(intent, REQUEST_SELECT_PHONE_NUMBER);

}

}

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if (requestCode == REQUEST_SELECT_PHONE_NUMBER && resultCode == RESULT_OK) {

// 获取对应的统一资源标识符,从内容提供者中查询得到该电话号码

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 动作,并且使用一个 content: 形式的统一资源标识符作为意图数据来指定目标联系人。

主要有两种方法来最初获取到那个联系人的统一资源标识符:

  • •.使用 ACTION_PICK 返回的那个联系人统一资源标识符,这一点在前一小节中已经展示过了(不需要拥有任何的应用权限)。

  • •.按照获取 到一个联系人列表 中的方法,直接访问到所有联系人组成的列表(这要求妳的应用拥有 READ_CONTACTS 权限)。

动作

ACTION_VIEW

数据 的统一资源标识符模式

content:<URI>

多媒体类型

无。类型可由联系人的统一资源标识符推断出来。

示例意图:

public void viewContact(Uri contactUri) {

Intent intent = new Intent(Intent.ACTION_VIEW, contactUri);

if (intent.resolveActivity(getPackageManager()) != null) {

startActivity(intent);

}

}

编辑一个已有的联系人

要想编辑一个已知的联系人,则使用 ACTION_EDIT 动作,使用一个 content: 形式的统一资源标识符作为意图数据来指定目标联系人,并且使用 ContactsContract.Intents.Insert 中指定的那些常量来在额外参数中包含任何已知的联系人信息。

主要有两种方法来最初获取到那个联系人的统一资源标识符:

  • •.使用 ACTION_PICK 返回的那个联系人统一资源标识符,这一点在前一小节中已经展示过了(不需要拥有任何的应用权限)。

  • •.按照获取 到一个联系人列表 中的方法,直接访问到所有联系人组成的列表(这要求妳的应用拥有 READ_CONTACTS 权限)。

动作

ACTION_EDIT

数据 的统一资源标识符模式

content:<URI>

多媒体类型

类型可由联系人的统一资源标识符推断出来。

额外参数

一个或多个在 ContactsContract.Intents.Insert 中定义的额外参数,这样,妳可以向该联系人的详情中填入一些已知字段。

示例意图:

public void editContact(Uri contactUri, String email) {

Intent intent = new Intent(Intent.ACTION_EDIT);

intent.setDataAndType(contactUri, Contacts.CONTENT_TYPE);

intent.putExtra(Intents.Insert.EMAIL, email);

if (intent.resolveActivity(getPackageManager()) != null) {

startActivity(intent);

}

}

欲知更多关于如何编辑联系人的说明,则阅读 使用意图 来修改联系人信息

插入一个联系人

要想插入一个新联系人的话,则使用 ACTION_INSERT 这个动作,指定多媒体类型为 Contacts.CONTENT_TYPE ,并且使用 ContactsContract.Intents.Insert 中指定的那些常量来在额外参数中包含任何已知的联系人信息。

动作

ACTION_INSERT

数据 的统一资源标识符模式

多媒体类型

Contacts.CONTENT_TYPE

额外参数

一个或多个在 ContactsContract.Intents.Insert 中定义的额外参数。

示例意图:

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);

}

}

欲知更多关于如何插入联系人的说明,则阅读 使用意图 来修改联系人信息

电子邮件

编写一封电子邮件,并且带上可选的附件

要想编写一封电子邮件,则,根据妳是否要包含附件,使用以下三个动作中的一个,并且使用以下列出的额外参数来包含邮件中的详细信息,例如收件人和主题。

动作

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 动作,则,这个参数应当是一个由多个 Uri 对象组成的 ArrayList

示例意图:

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);

}

}

如果妳要确保妳的意图只被邮件应用处理(而不被其它的文本消息应用或社交应用处理),则使用 ACTION_SENDTO 动作,并且包含上 "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);

}

}

示例意图过滤 器:

<activity ...>

<intent-filter>

<action android:name="android.intent.action.SEND" />

<data android:type="*/*" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

<intent-filter>

<action android:name="android.intent.action.SENDTO" />

<data android:scheme="mailto" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

文件存储

获取某个特定类型的文件

要想让用户选择一个文件(例如一个文档或一张照片)并且返回一个引用给妳的应用的话,则使用 ACTION_GET_CONTENT 这个动作,并且指定妳所预期的多媒体类型。所返回给妳的应用的那个文件引用,是临时在妳的活动(activity)的当前生命周期中有效的,所以,如果妳想在日后再访问这个文件 的话,那么妳必须导入一个复件,以便日后访问。这个意图也允许用户在这个过程中创建一个新文件(例如,不选择一张已有的照片,而是用照相机拍摄一张新照片)。

返回给妳的 onActivityResult() 方法的结果意图中,包含着一个统一资源标识符,指向所选择的文件。这个统一资源标识符可能是任何东西,例如一个 http: 形式的统一资源标识符、 file: 形式的统一资源标识符 或 content: 形式的统一资源标识符。然而,如果妳想要限制可选择的文件的范围,使得只能选择那些能够通过一个内容提供者(一个 content: 形式的统一资源标识符)访问的文件,以及那些可通过 openFileDescriptor() 打开成为一个文件流的文件,那么,妳应当向意图中加入 CATEGORY_OPENABLE 这个类别。

在安卓4.3 (应用编程接口版本18)及更高版本的系统中,妳还可以允许用户选择多个文件,具体做法就是,向意图中加入 EXTRA_ALLOW_MULTIPLE ,并且把它的值设置为 true 。然后,妳可以通过 getClipData() 获取到一个 ClipData 对象,其中包含着被选中的所有文件。

动作

ACTION_GET_CONTENT

数据 的统一资源标识符模式

多媒体类型

与用户应当选择的文件类型对应的多媒体类型。

额外参数

EXTRA_ALLOW_MULTIPLE

一个逻辑值,表示,用户是否可以一次性选中多个文件。

EXTRA_LOCAL_ONLY

一个逻辑值,表示,所返回的文件是否应当是可在当前设备上直接访问到的,而不是要从远程服务器上下载的。

类别 (可选)

CATEGORY_OPENABLE

返回那种“可打开”的文件,即为那种可通过 openFileDescriptor() 打开成为一个文件流的文件。

示例意图,用于获取 一张照片:

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);

}

}

@Override

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();

// 对于fullPhotoUri所指向的照片做出处理

...

}

}

示例意图过滤 ,用于返回 一张照片:

<activity ...>

<intent-filter>

<action android:name="android.intent.action.GET_CONTENT" />

<data android:type="image/*" />

<category android:name="android.intent.category.DEFAULT" />

<!-- OPENABLE类别的意义是,返回的文件可通过一个支持 OpenableColumns ContentResolver.openFileDescriptor() 的内容提供者访问到-->

<category android:name="android.intent.category.OPENABLE" />

</intent-filter>

</activity>

打开一个特定类型的文件

之前我们说的是获取一个必须引入到妳的应用程序中去的文件复件(具体就是使用 ACTION_GET_CONTENT 这个动作),作为代替,如果妳的应用是运行在安卓4.4或更高版本的系统中,则,妳可以使用 ACTION_OPEN_DOCUMENT 动作并且指定一个多媒体类型,以请求 打开 一个由别的应用管理的文件。如果要允许用户创建一个可被妳的应用写入的新文件,则,使用 ACTION_CREATE_DOCUMENT 这个动作。例如,妳不希望从已有的PDF文档中选择文件的话,则,使用 ACTION_CREATE_DOCUMENT 意图,它允许用户选择要把新文档创建到哪里(在另一个可管理该文档的存储空间的应用里做操作)——然后,妳的应用就获取得到一个统一资源标识符位置,可向该位置写入新文档。

尽管 ACTION_GET_CONTENT 动作返回给妳的 onActivityResult() 方法的意图中可能会包含着任意类型的统一资源标识符,但是,由 ACTION_OPEN_DOCUMENT ACTION_CREATE_DOCUMENT 返回的结果意图中,永远都会以一个 content: 形式的统一资源标识符来表示所选择的文件,该统一资源标识符背后有一个 DocumentsProvider 支撑着。妳可以使用 openFileDescriptor() 来打开该文件,并且使用 DocumentsContract.Document 中的那些列来查询该文件的详情。

所返回的统一资源标识符会让妳的应用拥有长期读取该文件的权限(也可能会赋予写入权限)。所以 ACTION_OPEN_DOCUMENT 这个动作在以下情况中尤其有用(相对于 ACTION_GET_CONTENT ):妳想在不将文件复制到妳的应用中去的情况下读取某个已有文件;或者,妳想打开并且原地修改某个文件。

妳还可以允许选择多个文件,具体做法就是向意图中加入 EXTRA_ALLOW_MULTIPLE ,并且设置为 true 。如果用户仅仅选中了一个文件,那么,妳可以通过 getData() 获取到该文件。如果用户选中了多个文件,那么, getData() 会返回空(null),这种情况下,妳应当通过 getClipData() 来获取一个 ClipData 对象,再从中获取每个文件。

注意 妳的意图中 必须 指定一个多媒体类型,并且 必须 声明 CATEGORY_OPENABLE 这个类别。必要的情况下,妳还可以指定多个多媒体类型,具体做法就是使用 EXTRA_MIME_TYPES 这个额外参数来添加一个多媒体类型数组——要这样做的话,妳必须在 setType() 中将主要的多媒体类型设置为 "*/*"

动作

ACTION_OPEN_DOCUMENT
ACTION_CREATE_DOCUMENT

数据 的统一资源标识符模式

多媒体类型

与用户应当选择的文件类型对应的多媒体类型。

额外参数

EXTRA_MIME_TYPES

由多媒体类型组成的数组,对应着妳的应用正在请求的文件的类型。如果妳使用这个额外参数的话,妳必须在 setType() 中将主要的多媒体类型设置为 "*/*"

EXTRA_ALLOW_MULTIPLE

一个逻辑值,表示,用户是否可以一次性选中多个文件。

EXTRA_TITLE

ACTION_CREATE_DOCUMENT 配套使用,用于指定一个初始文件名。

EXTRA_LOCAL_ONLY

一个逻辑值,表示,所返回的文件是否应当是可在当前设备上直接访问到的,而不是要从远程服务器上下载的。

类别

CATEGORY_OPENABLE

只返回那种“可打开”的文件,即为那种可通过openFileDescriptor()打开成为一个文件流的文件。

示例意图,用于获取 一张照片:

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);

}

@Override

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 动作的意图作出响应。所以,系统会接收到这个意图,并且将那些可从各种各样第三方应用中获取到的文件以一个统一的界面显示出来。

要想把妳的应用所拥有的文件提供到这个界面中以让其它应用打开它们的话,妳必须实现一个 DocumentsProvider ,并且包含一个针对 PROVIDER_INTERFACE ( "android.content.action.DOCUMENTS_PROVIDER" )的意图过滤器。例如:

<provider ...

android:grantUriPermissions="true"

android:exported="true"

android:permission="android.permission.MANAGE_DOCUMENTS">

<intent-filter>

<action android:name="android.content.action.DOCUMENTS_PROVIDER" />

</intent-filter>

</provider>

欲知更多关于如何让妳的应用中的文件可被其它应用打开的信息,则阅读 存储访问框架指南

地图

在地图上显示一个位置

要想打开一个地图,则使用 ACTION_VIEW 这个动作,并按照以下列出的模式在意图中指定位置信息。

动作

ACTION_VIEW

数据 的统一资源标识符模式

geo: latitude , longitude

显示指定经度和纬度处的地图。

示例:"geo:47.6,-122.3"

geo: latitude , longitude ?z= zoom

显示指定经度和纬度处的地图,并且按照指定级别缩放。缩放级别为1则表示显示整个地球,并且以指定的 经度 ,纬度坐标为中心。最高(放大到与视点距离最近)的缩放级别是23

示例:"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

显示"my street address"(可以是一个具体地址或者是一个地址查询要求)的位置。

示例:"geo:0,0?q=1600+Amphitheatre+Parkway%2C+CA"

注意 传递 geo形式的统一资源标识符中的所有字符串都必须编码。例如, 1st & Pike, Seattle 这个字符串,应当被编码为 1st%20%26%20Pike%2C%20Seattle 。字符串中的空格可以编码为 %20 或替换为加号(+)

多媒体类型

示例意图:

public void showMap(Uri geoLocation) {

Intent intent = new Intent(Intent.ACTION_VIEW);

intent.setData(geoLocation);

if (intent.resolveActivity(getPackageManager()) != null) {

startActivity(intent);

}

}

示例意图过滤 器:

<activity ...>

<intent-filter>

<action android:name="android.intent.action.VIEW" />

<data android:scheme="geo" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

音乐或视频

播放一个多媒体文件

要想播放一个音乐文件,则使用 ACTION_VIEW 这个动作,并在意图数据中指定该文件的统一资源标识符位置。

动作

ACTION_VIEW

数据 的统一资源标识符模式

file: <URI>

content: <URI>

http: <URL>

多媒体类型

"audio/*"

"application/ogg"

"application/x-ogg"

"application/itunes"

或者是其它可能被妳的应用请求的类型。

示例意图:

public void playMedia(Uri file) {

Intent intent = new Intent(Intent.ACTION_VIEW);

intent.setData(file);

if (intent.resolveActivity(getPackageManager()) != null) {

startActivity(intent);

}

}

示例意图过滤 器:

<activity ...>

<intent-filter>

<action android:name="android.intent.action.VIEW" />

<data android:type="audio/*" />

<data android:type="application/ogg" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

播放一个基于搜索的音乐

要想播放一个基于搜索结果的音乐,则使用 INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH 这个意图。一个应用可能会在收到用户要求播放音乐的语音命令时触发这个意图。收到这个意图的目标应用,会在自己的数据库中做搜索以按照给定的搜索条件匹配到已有的内容,然后开始播放该内容。

这个意图中应当包含 EXTRA_MEDIA_FOCUS 这个字符串额外参数,该参数会指定预期的搜索模式。例如,搜索模式中可以指定该搜索是以歌手名字为搜索目标还是以歌曲名字为搜索目标。

动作

INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH

数据 的统一资源标识符模式

多媒体类型

额外参数

MediaStore.EXTRA_MEDIA_FOCUS (必选)

指定搜索模式(用户是在找什么?特定的歌手、专辑、歌曲、播放列表还是收音机频道?)。大部分搜索模式都需要加入其它的额外参数。例如,如果用户想要搜索特定的某首歌曲,那么,该意图中可能会包含其它的三个额外参数:歌曲标题、歌手和专辑名字。对于 EXTRA_MEDIA_FOCUS 的每个值,这个意图支持以下搜索模式:

Any - "vnd.android.cursor.item/*"

播放任意音乐。接收到该意图的目标应用应当按照某种智能策略来选择一首歌曲播放,例如继续播放用户上次曾播放的播放列表中的下一首歌曲。

其它的额外参数:

  • •. QUERY (必选参数) - 一个空字符串。这个额外参数是必须要提供的,目的是保持向下兼容:已有的那些不理解搜索模式的应用,可以将这个意图当成一个未结构化的(unstructured)搜索来处理。

Unstructured - "vnd.android.cursor.item/*"

根据一个未结构化的搜索来播放某个特定的歌曲、专辑或流派(genre)。各个应用在无法确认用户想听什么类型的音乐时,可能会生成一个具有这种搜索模式的意图。在可能的情况下应当使用更加详细的搜索模式。

其它额外参数

  • •. QUERY (必选参数) - 一个字符串,包含着以下属性的任意组合:歌手、专辑、歌曲名或流派。

Genre - Audio.Genres.ENTRY_CONTENT_TYPE

播放特定流派的音乐。

其它额外参数

  • •. "android.intent.extra.genre" (必选参数) - 流派

  • •. QUERY (必选参数) - 流派。这个额外参数是必须要提供的,目的是保持向下兼容:已有的那些不理解搜索模式的应用,可以将这个意图当成一个未结构化的(unstructured)搜索来处理。

Artist - Audio.Artists.ENTRY_CONTENT_TYPE

播放特定歌手的音乐。

其它额外参数

  • •. EXTRA_MEDIA_ARTIST (必选参数) - 歌手

  • •. "android.intent.extra.genre" - 流派

  • •. QUERY (必选参数) - 一个字符串,是歌手名字或流派的任意组合。这个额外参数是必须要提供的,目的是保持向下兼容:已有的那些不理解搜索模式的应用,可以将这个意图当成一个未结构化的(unstructured)搜索来处理。

Album - Audio.Albums.ENTRY_CONTENT_TYPE

播放特定专辑中的音乐。

其它额外参数

  • •. EXTRA_MEDIA_ALBUM (必选参数) - 专辑

  • •. EXTRA_MEDIA_ARTIST - 歌手

  • •. "android.intent.extra.genre" - 流派

  • •. QUERY (必选参数) - 一个字符串,包含着专辑或歌手的任意组合。这个额外参数是必须要提供的,目的是保持向下兼容:已有的那些不理解搜索模式的应用,可以将这个意图当成一个未结构化的(unstructured)搜索来处理。

Song - "vnd.android.cursor.item/audio"

播放特定的一首歌曲。

其它额外参数

  • •. EXTRA_MEDIA_ALBUM - 专辑

  • •. EXTRA_MEDIA_ARTIST - 歌手

  • •. "android.intent.extra.genre" - 流派

  • •. EXTRA_MEDIA_TITLE (必选参数) - 歌曲名字

  • •. QUERY (必选参数) - 一个字符串,包含着以下属性的任意组合:歌手、专辑、歌曲名或流派。这个额外参数是必须要提供的,目的是保持向下兼容:已有的那些不理解搜索模式的应用,可以将这个意图当成一个未结构化的(unstructured)搜索来处理。

Radio channel - "vnd.android.cursor.item/radio"

播放某个特定的收音机频道,或者某个匹配了其它额外参数中指定的某些条件的收音机频道。

其它额外参数

  • •. EXTRA_MEDIA_ALBUM - 专辑名字

  • •. EXTRA_MEDIA_ARTIST - 歌手名字

  • •. "android.intent.extra.genre" - 流派

  • •. "android.intent.extra.radio_channel" - 收音机频道

  • •. EXTRA_MEDIA_TITLE - 该收音机频道所基于的歌曲名字。

  • •. QUERY (必选参数) - 一个字符串,包含以下属性的任意组合:专辑名字、歌手名字、流派、收音机频道或歌曲标题。这个额外参数是必须要提供的,目的是保持向下兼容:已有的那些不理解搜索模式的应用,可以将这个意图当成一个未结构化的(unstructured)搜索来处理。

Playlist - Audio.Playlists.ENTRY_CONTENT_TYPE

播放某个特定的播放列表,或者某个匹配了其它额外参数中指定的某些条件的播放列表。

其它额外参数

  • •. EXTRA_MEDIA_ALBUM - 专辑名字

  • •. EXTRA_MEDIA_ARTIST - 歌手名字

  • •. "android.intent.extra.genre" - 流派

  • •. "android.intent.extra.playlist" - 播放列表

  • •. EXTRA_MEDIA_TITLE - 该播放列表所基于的歌曲名字。

  • •. QUERY (必选参数) - 一个字符串,包含着以下属性的任意组合:专辑名字、歌手名字、流派、播放列表或歌曲标题。这个额外参数是必须要提供的,目的是保持向下兼容:已有的那些不理解搜索模式的应用,可以将这个意图当成一个未结构化的(unstructured)搜索来处理。

示例意图:

如果用户想要收听某个播放特定歌手的歌曲的收音机频道,那么,一个搜索应用可能会生成以下意图:

public void playSearchRadioByArtist(String artist) {

Intent intent = new Intent(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH);

intent.putExtra(MediaStore.EXTRA_MEDIA_FOCUS,

"vnd.android.cursor.item/radio");

intent.putExtra(MediaStore.EXTRA_MEDIA_ARTIST, artist);

intent.putExtra(SearchManager.QUERY, artist);

if (intent.resolveActivity(getPackageManager()) != null) {

startActivity(intent);

}

}

示例意图过滤 器:

<activity ...>

<intent-filter>

<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

妳的活动(activity)在处理这个意图时,应当检查传来的 Intent 中的 EXTRA_MEDIA_FOCUS 这个额外参数,以确定所使用的搜索模式。一旦妳的活动确定了要使用的搜索模式,就应当读取对于该种特定搜索模式的其它额外参数的值。有了这个信息,妳的应用就可以在自己的数据库里搜索,并且播放与该搜索条件相匹配的内容了。例如:

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);

// 取决于搜索模式,其中某些额外参数可能不存在

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 rchannel = intent.getStringExtra("android.intent.extra.radio_channel");

String title = intent.getStringExtra(MediaStore.EXTRA_MEDIA_TITLE);

// 确定搜索模式,并且使用相应的额外参数

if (mediaFocus == null) {

// “未结构化的”('Unstructured')搜索模式(这是为了维持向下兼容性)

playUnstructuredSearch(query);

} else if (mediaFocus.compareTo("vnd.android.cursor.item/*") == 0) {

if (query.isEmpty()) {

// “任意”('Any')搜索模式

playResumeLastPlaylist();

} else {

// “未结构化的”('Unstructured')搜索模式

playUnstructuredSearch(query);

}

} else if (mediaFocus.compareTo(MediaStore.Audio.Genres.ENTRY_CONTENT_TYPE) == 0) {

// “流派”('Genre')搜索模式

playGenre(genre);

} else if (mediaFocus.compareTo(MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE) == 0) {

// “歌手”('Artist')搜索模式

playArtist(artist, genre);

} else if (mediaFocus.compareTo(MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE) == 0) {

// “专辑”('Album')搜索模式

playAlbum(album, artist);

} else if (mediaFocus.compareTo("vnd.android.cursor.item/audio") == 0) {

// “歌曲名”('Song')搜索模式

playSong(album, artist, genre, title);

} else if (mediaFocus.compareTo("vnd.android.cursor.item/radio") == 0) {

// “收音机频道”('Radio channel')搜索模式

playRadioChannel(album, artist, genre, rchannel, title);

} else if (mediaFocus.compareTo(MediaStore.Audio.Playlists.ENTRY_CONTENT_TYPE) == 0) {

// “播放列表”('Playlist')搜索模式

playPlaylist(album, artist, genre, playlist, title);

}

}

}

电话

发起一次电话呼叫

要想启动电话应用并且拨打一个电话号码的话,则使用 ACTION_DIAL 这个动作,并且使用以下定义的统一资源标识符模式来指定一个电话号码。当电话应用启动之后,会显示出对应的电话号码,但是用户必须按下 拨号按钮才能真正开始拨打电话

动作

ACTION_DIAL

数据 的统一资源标识符模式

tel:<phone-number>

多媒体类型

IETF RFC 3966 中定义的电话号码才是有效的电话号码。以下两个例子都是有效的电话号码:

  • •. tel:2125551212

  • •. tel:(212) 555 1212

手机上的拨号器狠擅长于将不同模式的字符串一般化,例如将电话号码一般化。所以在调用 Uri.parse() 方法时不需要严格按照所描述的模式来传递电话号码。然而,如果妳从没尝试过某种模式,或者不确定系统是否能够处理那种模式,那么,应当使用 Uri.fromParts() 方法。

示例意图:

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);

}

}

设置

打开特定的设置界面

要想在妳的应用需要用户来改变某种设置时打开系统设置中的某个界面的话,则,使用以下的某个意图动作来打开对应的设置界面。

动作

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

参考 设置 文档,以了解其它可用的设置界面。

数据 的统一资源标识符模式

多媒体类型

示例意图:

public void openWifiSettings() {

Intent intent = new Intent(Intent.ACTION_WIFI_SETTINGS);

if (intent.resolveActivity(getPackageManager()) != null) {

startActivity(intent);

}

}

文本消息

编写一条短信/带附件的彩信

要想编写一条短信或彩信的话,则使用以下列出的意图动作,并且使用以下列出的额外参数指定消息中的详细信息,例如电话号码、主题和消息内容。

动作

ACTION_SENDTO
ACTION_SEND
ACTION_SEND_MULTIPLE

数据 的统一资源标识符模式

sms: <phone_number>

smsto: <phone_number>

mms: <phone_number>

mmsto: <phone_number>

这些模式都是以同样的方式来处理的。

多媒体类型

PLAIN_TEXT_TYPE ("text/plain")

"image/*"

"video/*"

额外参数

"subject"

一个字符串,表示消息的主题(通常只用于彩信)

"sms_body"

一个字符串,表示消息的内容。

EXTRA_STREAM

一个 Uri ,指向要附加的图片或视频。如果使用的是 ACTION_SEND_MULTIPLE 这个动作,那么,这个额外参数应当是由 Uri 组成的一个 ArrayList ,其中每个URI都指向一个要附加的图片或视频。

示例意图:

public void composeMmsMessage(String message, Uri attachment) {

Intent intent = new Intent(Intent.ACTION_SEND);

intent.setType(HTTP.PLAIN_TEXT_TYPE);

intent.putExtra("sms_body", message);

intent.putExtra(Intent.EXTRA_STREAM, attachment);

if (intent.resolveActivity(getPackageManager()) != null) {

startActivity(intent);

}

}

如果妳想确保这个意图只被文本消息应用处理(而不被邮件应用或社交应用处理),则,使用 ACTION_SENDTO 这个动作,并且使用 "smsto:" 作为数据的模式。例如:

public void composeMmsMessage(String message, Uri attachment) {

Intent intent = new Intent(Intent.ACTION_SEND);

intent.setData(Uri.parse("smsto:")); // 这样可以确保只有短信应用会做出响应

intent.putExtra("sms_body", message);

intent.putExtra(Intent.EXTRA_STREAM, attachment);

if (intent.resolveActivity(getPackageManager()) != null) {

startActivity(intent);

}

}

示例意图过滤器:

<activity ...>

<intent-filter>

<action android:name="android.intent.action.SEND" />

<data android:type="text/plain" />

<data android:type="image/*" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

注意 如果妳正在开发一个短信/彩信应用的话,那么,妳必须实现针对若干个额外动作的意图过滤器,才能够成为安卓4.4及更高版本系统中的 默认短信应用 。欲知更多信息,则参考 电话功能 文档。

网页浏览器

载入一个网址

要想打开一个网页,则使用 ACTION_VIEW 这个动作,并且在意图的数据中指定要打开的网址。

动作

ACTION_VIEW

数据 的统一资源标识符模式

http: <URL>
https: <URL>

多媒体类型

PLAIN_TEXT_TYPE ("text/plain")

"text/html"

"application/xhtml+xml"

"application/vnd.wap.xhtml+xml"

示例意图:

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);

}

}

示例意图过滤器:

<activity ...>

<intent-filter>

<action android:name="android.intent.action.VIEW" />

<!-- 如果妳只想让妳的应用对于它所在的域名下的网址做出响应的话,则包含host属性-->

<data android:scheme="http" android:host="www.example.com" />

<category android:name="android.intent.category.DEFAULT" />

<!-- 要有BROWSABLE这个类别,才能够从网页中获取到链接。-->

<category android:name="android.intent.category.BROWSABLE" />

</intent-filter>

</activity>

提示 如果妳的安卓应用中提供了与网站上类似的功能,则,可以包含一个针对指向妳的网站的URL的意图过滤器。这样,用户安装了妳的应用之后,点击邮件或者其它网页上那些指向妳的网站的链接,就会打开妳的安卓应用,而不是跳转到妳的网页上去。

发起一次网页搜索

要想发起一次网页搜索的话,则使用 ACTION_WEB_SEARCH 这个动作,并且在 SearchManager.QUERY 这个额外参数中指定搜索字符串。

动作

ACTION_WEB_SEARCH

数据 的统一资源标识符模式

多媒体类型

额外参数

SearchManager.QUERY

搜索字符串。

示例意图:

public void searchWeb(String query) {

Intent intent = new Intent(Intent.ACTION_SEARCH);

intent.putExtra(SearchManager.QUERY, query);

if (intent.resolveActivity(getPackageManager()) != null) {

startActivity(intent);

}

}

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

HxLauncher: Launch Android applications by voice commands