Android 4.0 API

API 级别14

Android 4.0 (ICE_CREAM_SANDWICH) 是一个主要平台版本,为用户和应用开发者添加了各种新功能。除了下面讨论的所有新功能和 API 之外,Android 4.0 还是一个重要的平台版本,因为它将 Android 3.x 中的大量 API 和全息主题带到了较小的屏幕上。作为应用开发者,您现在拥有单一平台和统一的 API 框架,可让您使用单个 APK 开发和发布应用,以便在运行相同版本的 Android - Android 4.0(API 级别 14)或更高版本时为手机、平板电脑等设备提供优化的用户体验。

对于开发者来说,Android 4.0 平台可作为 Android SDK 的可下载组件提供。可下载平台包含 Android 库、系统映像,以及一组模拟器皮肤等。如需开始针对 Android 4.0 进行开发或测试,请使用 Android SDK 管理器将该平台下载到您的 SDK 中。

API 概览

以下部分提供了 Android 4.0 中新 API 的技术概览。

联系人提供程序中的社交 API

ContactsContract 提供程序定义的联系人 API 已经过扩展,以支持新的面向社交的功能,例如设备所有者的个人资料以及允许用户邀请各个联系人加入设备上安装的社交网络的功能。

用户个人资料

Android 现在包含代表设备所有者的个人资料(如 ContactsContract.Profile 表所定义)。维护用户身份的社交应用可以通过在 ContactsContract.Profile 中创建新的 ContactsContract.RawContacts 条目来提供用户个人资料数据。也就是说,代表设备用户的原始联系人并不属于由 ContactsContract.RawContacts URI 定义的传统原始联系人表;相反,您必须在 CONTENT_RAW_CONTACTS_URI 处的表中添加个人资料原始联系人。然后,此表中的原始联系人会汇总到标记为“我”的单个用户可见个人资料中。

为个人资料添加新的原始联系人需要 android.Manifest.permission#WRITE_PROFILE 权限。同样,如需从配置文件表中读取数据,您必须请求 android.Manifest.permission#READ_PROFILE 权限。不过,大多数应用都不需要读取用户个人资料,即使在向个人资料贡献数据时。读取用户个人资料是一项敏感权限,因此用户应该对请求该权限的应用持怀疑态度。

邀请意图

借助 INVITE_CONTACT intent 操作,应用可以调用一项操作,指明用户想将联系人添加到社交网络。接收应用的应用会使用它来邀请指定联系人加入该社交网络。大多数应用都将处于此操作的接收端。例如,当用户为联系人详细信息中列出的特定社交应用选择“添加连接”时,内置的“联系人”应用会调用邀请 intent。

如需使您的应用显示在“添加连接”列表中,您的应用必须提供同步适配器,以便从社交网络同步联系信息。然后,您必须向应用的同步配置文件添加 inviteContactActivity 属性,并指定一个 Activity 的完全限定名称,让系统在发送邀请 intent 时启动该 activity,以告知系统您的应用会响应 INVITE_CONTACT intent。然后,启动的 activity 可以从 intent 的数据中检索相关联系人的 URI,并执行必要的工作来邀请该联系人加入网络或将用户添加到用户的连接中。

大型照片

Android 现在支持为联系人添加高分辨率照片。现在,当您将照片推送到联系人记录中时,系统会将照片同时处理为 96x96 缩略图(如前所述)和 256x256“显示照片”(存储在基于文件的新照片存储区中),并将其存储为 256x256 的“显示照片”(系统选择的确切尺寸将来可能会有所不同)。您可以向联系人添加大照片,方法是将大照片放在数据行的常规 PHOTO 列中,然后系统会将其处理为相应的缩略图并显示照片记录。

联系人使用情况反馈

借助新的 ContactsContract.DataUsageFeedback API,您可以跟踪用户使用特定方法联系用户的频率,例如用户使用每个电话号码或电子邮件地址的频率。此信息有助于提升与每个人相关的每种联系方式的排名,并提供更好的联系建议。

日历提供程序

借助新的日历 API,您可以读取、添加、修改和删除存储在日历提供程序中的日历、活动、参加者、提醒和提醒。

各种应用和微件可以使用这些 API 读取和修改日历活动。但是,一些最具吸引力的用例是同步适配器,它可将用户日历服务中的其他日历服务与日历提供程序同步,从而为所有用户的活动提供统一的位置。例如,Google 日历事件通过 Google 日历同步适配器与日历提供程序同步,以便使用 Android 的内置日历应用查看这些事件。

日历提供程序中的日历和事件相关信息的数据模型由 CalendarContract 定义。用户的所有日历数据存储在 CalendarContract 的各个子类所定义的多个表中:

  • CalendarContract.Calendars 表包含特定于日历的信息。此表中的每一行都包含一个日历的详细信息,例如名称、颜色、同步信息等。
  • CalendarContract.Events 表包含事件特定信息。此表中的每一行都包含单个活动的信息,例如活动标题、地点、开始时间、结束时间等。事件可以发生一次,也可以多次重复。参加者、提醒和扩展属性存储在单独的表中,并使用活动的 _ID 将其与活动相关联。
  • CalendarContract.Instances 表包含事件发生的开始时间和结束时间。此表中的每一行都表示一次出现。对于一次性事件,实例与事件是一对一的映射关系。对于周期性事件,系统会自动生成多个行,以分别对应多个事件实例。
  • CalendarContract.Attendees 表包含活动参加者或邀请对象信息。每一行都表示活动的一位邀请对象。它指明了邀请对象的类型以及对方对事件的回复。
  • CalendarContract.Reminders 表包含提醒/通知数据。每一行代表事件的一个提醒。一个活动可以有多个提醒。每个事件的提醒数在 MAX_REMINDERS 中指定,该值由拥有给定日历的同步适配器设置。提醒以事件安排前的分钟数形式指定,并指定闹钟方法,例如使用提醒、电子邮件或短信提醒用户。
  • CalendarContract.ExtendedProperties 表包含同步适配器使用的不透明数据字段。提供程序不会对此表中的项执行任何操作,除非在项的相关事件被删除时一并删除。

如需使用日历提供程序访问用户的日历数据,您的应用必须请求 READ_CALENDAR 权限(读取权限)和 WRITE_CALENDAR 权限(写入权限)。

事件 intent

如果您只是想将事件添加到用户的日历,则可以使用 ACTION_INSERT intent 并提供由 Events.CONTENT_URI 定义的数据,以便在日历应用中启动一个可创建新事件的 activity。使用该 intent 不需要任何权限,而且您可以使用以下 extra 指定事件详细信息:

语音信箱提供商

借助新的语音信箱提供程序,应用可以将语音信息添加到设备,以便在单个可视化演示文稿中呈现用户的所有语音信息。例如,用户可能会有多个语音信箱来源,例如一个来自电话服务提供商,另一个来自 VoIP 或其他替代语音服务。这些应用可以使用 Voicemail Provider API 将其语音信息添加到设备上。然后,内置的“电话”应用会以统一的展示形式向用户显示所有语音信息。虽然系统的“电话”应用是唯一可以读取所有语音信息的应用,但每个提供语音信息的应用都可以读取其已添加到系统中的语音信息(但无法读取其他服务中的语音信息)。

由于这些 API 目前不允许第三方应用读取系统中的所有语音信息,因此只有那些有语音信息要发送给用户的第三方应用才能使用这些语音信箱 API。

VoicemailContract 类定义了语音信箱 Provder 的内容提供程序。子类 VoicemailContract.VoicemailsVoicemailContract.Status 提供了一些表,应用可在其中插入语音信息数据以在设备上存储。如需查看语音信箱提供程序应用的示例,请参阅语音信箱提供程序演示

多媒体

Android 4.0 针对与照片、视频和音乐等媒体互动的应用添加了几个新的 API。

媒体效果

借助新的媒体效果框架,您可以向图片和视频应用各种视觉效果。例如,通过图片效果,您可以轻松修正红眼、将图片转换为灰度模式、调整亮度、调整饱和度、旋转图片、应用鱼眼效果等等。系统会在 GPU 上执行所有效果处理,以获得最佳性能。

为了获得最佳性能,效果会直接应用于 OpenGL 纹理,因此您的应用必须具有有效的 OpenGL 上下文,然后才能使用效果 API。您要应用效果的纹理可能来自位图、视频甚至相机。不过,纹理必须满足以下特定限制:

  1. 它们必须绑定到一个 GL_TEXTURE_2D 纹理图像
  2. 它们必须包含至少一个 mipmap 级别

Effect 对象定义可应用于图片帧的单一媒体效果。创建 Effect 的基本工作流如下:

  1. 从 OpenGL ES 2.0 上下文调用 EffectContext.createWithCurrentGlContext()
  2. 使用返回的 EffectContext 调用 EffectContext.getFactory(),后者会返回 EffectFactory 的实例。
  3. 调用 createEffect(),并向其传递 @link android.media.effect.EffectFactory} 的效果名称,例如 EFFECT_FISHEYEEFFECT_VIGNETTE

您可以通过调用 setParameter() 并传递参数名称和参数值来调整效果的参数。每种效果类型都接受不同的参数,这些参数与效果名称一起记录。例如,EFFECT_FISHEYE 有一个用于失真 scale 的参数。

如需对纹理应用效果,请对 Effect 调用 apply() 并传入输入纹理、其宽度和高度以及输出纹理。输入纹理必须绑定到 GL_TEXTURE_2D 纹理图片(通常通过调用 glTexImage2D() 函数完成)。您可以提供多个 mipmap 级别。如果输出纹理尚未绑定到纹理图片,则效果将自动将其绑定为一个 GL_TEXTURE_2D 并具有一个 mipmap 级别 (0),该级别与输入的大小相同。

保证支持 EffectFactory 中列出的所有效果。不过,并非所有设备都支持来自外部库的一些额外效果,因此您必须先通过调用 isEffectSupported() 检查是否支持来自外部库的所需效果。

遥控器客户端

新的 RemoteControlClient 允许媒体播放器从远程控制客户端(例如设备锁定屏幕)启用播放控件。媒体播放器还可以公开当前播放的媒体的相关信息以显示在遥控器上,例如曲目信息和专辑封面。

如需为您的媒体播放器启用远程控制客户端,请使用其构造函数实例化 RemoteControlClient,并向其传递可广播 ACTION_MEDIA_BUTTONPendingIntent。intent 还必须在应用中声明用于处理 ACTION_MEDIA_BUTTON 事件的显式 BroadcastReceiver 组件。

如需声明播放器可以处理的媒体控件输入,您必须对 RemoteControlClient 调用 setTransportControlFlags(),并传递一组 FLAG_KEY_MEDIA_* 标志,例如 FLAG_KEY_MEDIA_PREVIOUSFLAG_KEY_MEDIA_NEXT

然后,您必须注册 RemoteControlClient,方法是将其传递给 MediaManager.registerRemoteControlClient()。注册后,当您实例化 RemoteControlClient 时声明的广播接收器会在用户按遥控器上的按钮时收到 ACTION_MEDIA_BUTTON 事件。您收到的 intent 包含按下媒体键的 KeyEvent,您可以使用 getParcelableExtra(Intent.EXTRA_KEY_EVENT) 从 intent 中检索该 intent。

如需在遥控器上显示媒体播放方面的信息,请调用 editMetaData() 并将元数据添加到返回的 RemoteControlClient.MetadataEditor。您可以为媒体图片、数字信息(如已播放时间)以及文本信息(如曲目标题)提供位图。如需了解可用键,请参阅 MediaMetadataRetriever 中的 METADATA_KEY_* 标志。

如需查看示例实现,请参阅随机音乐播放器。该播放器提供了兼容性逻辑,因此可在 Android 4.0 设备上启用遥控器客户端,同时继续为支持 Android 2.1 的设备提供支持。

媒体播放器

  • MediaPlayer 流式传输在线媒体现在需要 INTERNET 权限。如果您使用 MediaPlayer 播放来自互联网的内容,请务必向清单中添加 INTERNET 权限,否则从 Android 4.0 开始,媒体播放将无法正常运行。
  • setSurface() 允许您定义 Surface,以充当视频接收器。
  • setDataSource() 允许您随请求发送额外的 HTTP 标头,这对于 HTTP(S) 实时流式传输非常有用
  • HTTP(S) 直播现在会跨请求遵循 HTTP Cookie

媒体类型

Android 4.0 增加了对以下内容的支持:

  • HTTP/HTTPS 实时流式传输协议版本 3
  • ADTS 原始 AAC 音频编码
  • WEBP 图片
  • Matroska 视频

如需了解详情,请参阅支持的媒体格式

摄像头

Camera 类现在包含用于检测人脸以及控制对焦和测光区域的 API。

人脸检测

相机应用现在可以使用 Android 的人脸检测 API 来增强其功能。这些 API 不仅可以检测拍摄对象的面部,还可以检测特定的面部特征,例如眼睛和嘴巴。

如需在相机应用中检测人脸,您必须通过调用 setFaceDetectionListener() 来注册 Camera.FaceDetectionListener。然后,您可以通过调用 startFaceDetection() 启动相机 Surface 并开始检测人脸。

当系统在相机场景中检测到一个或多个人脸时,它会在您的 Camera.FaceDetectionListener 实现(包括 Camera.Face 对象数组)中调用 onFaceDetection() 回调。

Camera.Face 类的实例提供有关检测到的人脸的各种信息,包括:

  • 一个 Rect,用于指定人脸相对于镜头当前视野的边界
  • 一个介于 1 到 100 之间的整数,表示系统对于相应对象是人脸的信心程度
  • 一个唯一 ID,便于您跟踪多个面孔
  • 指示眼睛和嘴巴所在位置的多个 Point 对象

注意:某些设备可能不支持人脸检测,因此您应通过调用 getMaxNumDetectedFaces() 进行检查,并确保返回值大于零。此外,某些设备可能不支持眼睛和嘴巴识别,在这种情况下,Camera.Face 对象中的这些字段将为 null。

对焦和测光区域

相机应用现在可以控制相机用于对焦以及白平衡和自动曝光测光的区域。这两项功能都使用新的 Camera.Area 类来指定相机当前视图应对焦或测光的区域。Camera.Area 类的实例使用整数定义包含 Rect 的区域的边界,以及该区域的权重(表示该区域相对于所考虑的其他区域的重要性级别)。

在设置对焦区域或测光区域之前,您应先分别调用 getMaxNumFocusAreas()getMaxNumMeteringAreas()。如果这些响应返回零,则表示设备不支持相应的功能。

如需指定要使用的对焦或测光区域,只需调用 setFocusAreas()setMeteringAreas() 即可。每个对象都接受 Camera.Area 对象的 List,这些对象指示要用于对焦或测光的区域。例如,您可以实现一项功能,让用户能够通过触摸预览区域来设置对焦区域,然后将该区域转换为 Camera.Area 对象,并请求相机将焦点放在场景中的该区域。该区域的焦点或曝光会随着该区域内的场景的变化而不断更新。

为照片添加连续自动对焦功能

您现在可以在拍摄照片时启用连续自动对焦 (CAF)。如需在相机应用中启用 CAF,请将 FOCUS_MODE_CONTINUOUS_PICTURE 传递给 setFocusMode()。准备好拍摄照片后,调用 autoFocus()。您的 Camera.AutoFocusCallback 会立即收到一个回调,以指明是否已实现焦点。如需在收到回调后恢复 CAF,您必须调用 cancelAutoFocus()

注意:使用 API 级别 9 中引入的 FOCUS_MODE_CONTINUOUS_VIDEO 拍摄视频时,也支持连续自动对焦功能。

其他相机功能

摄像头广播 intent

  • Camera.ACTION_NEW_PICTURE:这表示用户已拍摄了新照片。内置的相机应用会在拍摄照片后调用此广播,第三方相机应用也应在拍摄照片后广播此 intent。
  • Camera.ACTION_NEW_VIDEO:这表示用户已拍摄新视频。内置的相机应用会在录制视频后调用此广播,第三方相机应用也应在拍摄视频后广播此 intent。

Android Beam(使用 NFC 进行 NDEF 推送)

Android Beam 是一项新的 NFC 功能,可让您将 NDEF 消息从一个设备发送到另一台设备(此过程也称为“NDEF 推送”)。当两台支持 Android Beam 的 Android 设备离得很近(大约 4 厘米)时(通常是背靠背接触),就会启动数据传输。NDEF 消息内的数据可以包含您希望在设备之间共享的任何数据。例如,“联系人”应用使用 Android Beam 分享联系人,YouTube 分享视频,以及“浏览器”分享网址。

如需使用 Android Beam 在设备之间传输数据,您需要创建一个 NdefMessage,其中包含您希望在 activity 位于前台时共享的信息。然后,您必须通过以下两种方式之一将 NdefMessage 传递给系统:

如果您想在系统成功将 NDEF 消息传送到其他设备后运行某些特定的代码,可以实现 NfcAdapter.OnNdefPushCompleteCallback 并使用 setNdefPushCompleteCallback() 进行设置。然后,系统会在传递消息时调用 onNdefPushComplete()

在接收设备上,系统会发送 NDEF 推送消息,方式与常规 NFC 标签类似。系统通过根据 NdefMessage 中的第一个 NdefRecord 设置网址或 MIME 类型,调用具有 ACTION_NDEF_DISCOVERED 操作的 intent 来启动 activity。对于您要响应的 activity,您可以为应用关注的网址或 MIME 类型声明 intent 过滤器。如需详细了解标签调度,请参阅 NFC 开发者指南。

如果您希望 NdefMessage 带有 URI,现在可以使用便捷方法 createUri 根据字符串或 Uri 对象构造新的 NdefRecord。如果您想让应用在 Android Beam 事件期间收到一种特殊格式,则应使用相同的 URI 架构为 activity 创建一个 intent 过滤器,以便接收传入的 NDEF 消息。

您还应使用 NdefMessage 传递“Android 应用记录”,以确保您的应用会处理传入的 NDEF 消息,即使其他应用过滤相同的 intent 操作也是如此。您可以通过调用 createApplicationRecord() 并向其传递应用的软件包名称来创建 Android 应用记录。当其他设备收到包含应用记录的 NDEF 消息,并且多个应用包含可处理指定 intent 的 activity 时,系统始终会将该消息传递给应用中的 activity(根据匹配的应用记录)。如果目标设备当前未安装您的应用,系统会使用 Android 应用记录启动 Google Play,并将用户转到相应应用进行安装。

如果您的应用不使用 NFC API 执行 NDEF 推送消息,Android 会提供一种默认行为:当您的应用在一部设备上的前台运行且 Android Beam 被另一部 Android 设备调用时,另一台设备将收到一条 NDEF 消息,其中包含用于标识您的应用的 Android 应用记录。如果接收设备已安装您的应用,系统会启动该应用;如果未安装,Google Play 会打开并将用户引导至您的应用,以便安装它。

您可以在 NFC 基础知识开发者指南中详细了解 Android Beam 和其他 NFC 功能。如需查看一些使用 Android Beam 的示例代码,请参阅 Android Beam 演示

Wi-Fi P2P

Android 现在支持 Android 设备与其他设备类型之间的 Wi-Fi 点对点 (P2P) 连接(符合 Wi-Fi 联盟的 Wi-Fi DirectTM 认证计划的要求),无需热点或互联网连接。Android 框架提供了一组 Wi-Fi 点对点 API,可让您发现并连接到其他设备(当每台设备支持 Wi-Fi 点对点时),然后通过高速连接进行通信,这些距离远比蓝牙连接长。

新软件包 android.net.wifi.p2p 中包含用于通过 Wi-Fi 执行点对点连接的所有 API。您需要使用的主要类是 WifiP2pManager,您可以通过调用 getSystemService(WIFI_P2P_SERVICE) 获取该类。WifiP2pManager 包含可让您执行以下操作的 API:

  • 通过调用 initialize() 初始化您的应用以进行点对点连接
  • 通过调用 discoverPeers() 发现附近的设备
  • 通过调用 connect() 启动点对点连接
  • 其他数据

此外,还必须提供其他几个接口和类,例如:

为了使用 Wi-Fi P2P API,您的应用必须请求以下用户权限:

在某些 Wi-Fi 点对点事件期间,Android 系统还会广播几种不同的操作:

如需了解详情,请参阅 WifiP2pManager 文档。另请参阅 Wi-Fi 点对点演示示例应用。

蓝牙健康设备

Android 现在支持使用蓝牙健康配置文件设备,因此您可以创建使用蓝牙与支持蓝牙功能的健康设备(例如心率监测仪、血糖仪、温度计和体重秤)进行通信的应用。

与常规耳机和采用 A2DP 配置文件的设备类似,您必须使用 BluetoothProfile.ServiceListenerHEALTH 配置文件类型调用 getProfileProxy(),才能与配置文件代理对象建立连接。

获取健康配置文件代理(BluetoothHealth 对象)后,连接到配对的健康设备并与其通信涉及以下新的蓝牙类:

如需详细了解如何使用蓝牙健康配置文件,请参阅 BluetoothHealth 的文档。

无障碍功能

Android 4.0 通过全新的“轻触探索”模式以及可让您提供有关查看内容的更多信息或开发高级无障碍服务的扩展 API,改进了视障用户的无障碍功能。

“触摸浏览”模式

失明用户现在可以通过在屏幕上轻触并拖动手指来探索屏幕,让系统朗读内容的说明。由于轻触浏览模式的工作方式类似于虚拟光标,因此屏幕阅读器可以像用户使用方向键或轨迹球进行导航时一样识别描述性文字,也就是在模拟的“悬停”事件发生时读取 android:contentDescriptionsetContentDescription() 提供的信息。因此,谨在此提醒您,您应该为应用中的视图提供描述性文本,尤其是为 ImageButtonEditTextImageView 和其他可能不会自然包含描述性文本的 widget。

视图无障碍功能

为了丰富无障碍服务(如屏幕阅读器)可用的信息,您可以在自定义 View 组件中为无障碍事件实现新的回调方法。

首先请务必注意,sendAccessibilityEvent() 方法的行为在 Android 4.0 中已发生变化。与以前的 Android 版本一样,当用户在设备上启用无障碍服务并发生点击或悬停等输入事件时,系统会调用 sendAccessibilityEvent() 通知相应的视图。以前,sendAccessibilityEvent() 的实现会初始化 AccessibilityEvent 并将其发送到 AccessibilityManager。新行为涉及一些额外的回调方法,这些方法允许视图及其父级向事件添加更多上下文信息:

  1. 调用时,sendAccessibilityEvent()sendAccessibilityEventUnchecked() 方法会遵循 onInitializeAccessibilityEvent()

    View 的自定义实现可能希望实现 onInitializeAccessibilityEvent() 以将额外的无障碍功能信息附加到 AccessibilityEvent,但还应调用超类实现来提供默认信息,例如标准内容说明、项索引等。不过,您不应在此回调中添加额外的文本内容,接下来会发生。

  2. 初始化后,如果事件是应使用文本信息填充的几种类型之一,则视图随后会收到对 dispatchPopulateAccessibilityEvent() 的调用,该调用遵循 onPopulateAccessibilityEvent() 回调。

    如果 android:contentDescription 文本缺失或不足,View 的自定义实现通常应实现 onPopulateAccessibilityEvent() 以向 AccessibilityEvent 添加其他文本内容。如需向 AccessibilityEvent 添加更多文本说明,请调用 getText().add()

  3. 此时,View 通过对父视图调用 requestSendAccessibilityEvent() 将事件向上传递视图层次结构。然后,每个父视图都有机会通过添加 AccessibilityRecord 来扩充无障碍功能信息,直到最终到达根视图,根视图使用 sendAccessibilityEvent() 将事件发送到 AccessibilityManager

除了上面对扩展 View 类很有用的新方法之外,您还可以通过扩展 AccessibilityDelegate 并使用 setAccessibilityDelegate() 在视图上设置它,在任何 View 上拦截这些事件回调。当您这样做时,视图中的每个无障碍方法都会将调用推迟到委托中的相应方法。例如,当视图收到对 onPopulateAccessibilityEvent() 的调用时,会将其传递给 View.AccessibilityDelegate 中的同一方法。对于默认行为,委托未处理的所有方法都会直接提供给视图。这样,您就可以仅替换任何给定视图所需的方法,而无需扩展 View 类。

如果您希望保持与 Android 4.0 之前的版本兼容,同时支持新的无障碍功能 API,则可以通过最新版本的 v4 支持库(在兼容性软件包 r4 中)实现这一目的,这组实用程序类以向后兼容的设计提供了新的无障碍功能 API。

无障碍服务

如果您正在开发无障碍服务,则有关各种无障碍事件的信息已得到大幅扩展,以便为用户提供更高级的无障碍功能反馈。具体而言,事件是基于视图组合生成的,这样可以提供更好的上下文信息,并允许无障碍服务遍历视图层次结构,以获取额外的视图信息并处理特殊情况。

如果您要开发无障碍服务(例如屏幕阅读器),可以按照以下步骤访问其他内容信息并遍历视图层次结构:

  1. 从应用收到 AccessibilityEvent 后,调用 AccessibilityEvent.getRecord() 以检索特定的 AccessibilityRecord(该事件可能附加了多条记录)。
  2. AccessibilityEvent 或单个 AccessibilityRecord 中,您可以调用 getSource() 来检索 AccessibilityNodeInfo 对象。

    AccessibilityNodeInfo 表示窗口内容的单个节点,采用的格式允许您查询该节点的无障碍功能信息。从 AccessibilityEvent 返回的 AccessibilityNodeInfo 对象描述事件来源,而 AccessibilityRecord 中的来源描述事件来源的前身。

  3. 您可以使用 AccessibilityNodeInfo 查询其相关信息,调用 getParent()getChild() 来遍历视图层次结构,甚至可以向节点添加子视图。

为了让应用将自身作为无障碍服务发布到系统,它必须声明与 AccessibilityServiceInfo 对应的 XML 配置文件。如需详细了解如何创建无障碍服务,请参阅 AccessibilityServiceSERVICE_META_DATA,了解有关 XML 配置的信息。

其他无障碍功能 API

如果您对设备的无障碍状态感兴趣,可以查看 AccessibilityManager 提供的一些新 API,例如:

拼写检查服务

新的拼写检查工具框架允许应用以类似于输入法框架(适用于 IME)的方式创建拼写检查工具。若要创建新的拼写检查工具,您必须实现一项服务来扩展 SpellCheckerService 并扩展 SpellCheckerService.Session 类,以便根据接口的回调方法提供的文本提供拼写建议。在 SpellCheckerService.Session 回调方法中,您必须以 SuggestionsInfo 对象的形式返回拼写建议。

使用拼写检查服务的应用必须根据该服务的要求声明 BIND_TEXT_SERVICE 权限。 此服务还必须声明一个使用 <action android:name="android.service.textservice.SpellCheckerService" /> 作为 intent 操作的 intent 过滤器,并且应包含一个 <meta-data> 元素,用于为拼写检查工具声明配置信息。

请参阅示例 拼写检查工具服务应用和 拼写检查工具客户端应用示例,查看示例代码。

文字转语音引擎

Android 的文字转语音 (TTS) API 经过重大扩展,可让应用更轻松地实现自定义 TTS 引擎,而希望使用 TTS 引擎的应用则具有几个用于选择引擎的新 API。

使用文字转语音引擎

在以前的 Android 版本中,您可以使用 TextToSpeech 类通过系统提供的 TTS 引擎执行文字转语音 (TTS) 操作,也可以使用 setEngineByPackageName() 设置自定义引擎。在 Android 4.0 中,setEngineByPackageName() 方法已废弃,您现在可以使用接受 TTS 引擎软件包名称的新 TextToSpeech 构造函数来指定要使用的引擎。

您还可以使用 getEngines() 查询可用的 TTS 引擎。此方法会返回 TextToSpeech.EngineInfo 对象的列表,其中包括引擎的图标、标签和软件包名称等元数据。

构建文字转语音引擎

以前,自定义引擎要求使用未记录的原生头文件构建引擎。在 Android 4.0 中,有一整套用于构建 TTS 引擎的框架 API。

基本设置需要实现响应 INTENT_ACTION_TTS_SERVICE intent 的 TextToSpeechService。TTS 引擎的主要工作发生在扩展 TextToSpeechService 的服务中的 onSynthesizeText() 回调期间。系统会向此方法传递两个对象:

  • SynthesisRequest:其中包含各种数据,包括要合成的文本、语言区域、语速和音调。
  • SynthesisCallback:这是 TTS 引擎用于以流式音频形式提供生成的语音数据的接口。首先,引擎必须调用 start() 以表明引擎已准备好传送音频,然后调用 audioAvailable(),并通过字节缓冲区向其传递音频数据。在您的引擎通过缓冲区传递所有音频后,调用 done()

现在,框架支持真正的 API 来创建 TTS 引擎,因此不再支持原生代码实现。查找有关兼容性层的博文,您可以使用该层将旧的 TTS 引擎转换为新框架。

如需查看使用新 API 的示例 TTS 引擎,请参阅文字转语音引擎示例应用。

网络使用

Android 4.0 可让用户精确了解其应用所使用的网络数据流量。“设置”应用提供了一些控件,可让用户管理设定的网络流量消耗限制,甚至为各个应用停用后台流量。为了避免用户禁止应用在后台访问数据,您应该制定相关策略来高效使用数据连接,并根据可用连接类型调整用量。

如果您的应用执行大量网络事务,您应提供用户设置,以允许用户控制应用的数据习惯,例如应用同步数据的频率、是否仅在使用 Wi-Fi 时执行上传/下载、是否在漫游时使用数据等。为用户提供这些控件后,用户在应用数据访问权限接近限制时就不太可能停用应用对数据的访问权限,因为他们可以精确控制数据访问权限。如果您提供具有这些设置的偏好设置 activity,则应在其清单声明中添加用于 ACTION_MANAGE_NETWORK_USAGE 操作的 intent 过滤器。例如:

<activity android:name="DataPreferences" android:label="@string/title_preferences">
    <intent-filter>
       <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
       <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

此 intent 过滤器会向系统表明这是控制应用流量消耗的 activity。因此,当用户从“设置”应用中检查应用使用的数据量时,可以使用“查看应用设置”按钮来启动偏好设置 activity,以便用户优化应用使用的数据量。

另请注意,getBackgroundDataSetting() 现已废弃且始终返回 true,请改用 getActiveNetworkInfo()。在尝试任何网络事务之前,您应始终调用 getActiveNetworkInfo() 以获取代表当前网络的 NetworkInfo,并查询 isConnected() 以检查设备是否已连接到网络。然后,您可以查看其他连接属性,例如设备是否正在漫游或已连接到 Wi-Fi。

企业

Android 4.0 通过以下功能扩展了企业应用的功能。

VPN 服务

新的 VpnService 允许应用构建自己的 VPN(虚拟专用网),以 Service 的形式运行。VPN 服务利用自己的地址和路由规则为虚拟网络创建接口,并使用文件描述符执行所有读写操作。

如需创建 VPN 服务,请使用 VpnService.Builder,它允许您指定网络地址、DNS 服务器、网络路由等。完成后,您可以通过调用 establish()(返回 ParcelFileDescriptor)来建立该接口。

由于 VPN 服务可以拦截数据包,因此会对安全造成影响。因此,如果您实现 VpnService,则您的服务必须要求提供 BIND_VPN_SERVICE,以确保只有系统可以与其绑定(只有系统会被授予此权限,应用无法请求此权限)。如要使用您的 VPN 服务,用户必须在系统设置中手动启用该服务。

设备政策

管理设备限制的应用现在可以使用 setCameraDisabled()USES_POLICY_DISABLE_CAMERA 属性(通过政策配置文件中的 <disable-camera /> 元素应用)停用摄像头。

证书管理

新的 KeyChain 类提供了允许您在系统密钥库中导入和访问证书的 API。证书可以简化客户端证书(用于验证用户身份)和证书授权机构证书(用于验证服务器身份)的安装。网络浏览器或电子邮件客户端等应用可以访问已安装的证书,以向服务器验证用户身份。如需了解详情,请参阅 KeyChain 文档。

设备传感器

Android 4.0 中添加了两种新的传感器类型:

如果设备同时具有 TYPE_AMBIENT_TEMPERATURETYPE_RELATIVE_HUMIDITY 传感器,您可以使用它们来计算露点和绝对湿度。

旧版温度传感器 TYPE_TEMPERATURE 已弃用。您应改用 TYPE_AMBIENT_TEMPERATURE 传感器。

此外,Android 的三个合成传感器得到了极大改进,因此它们现在的延迟更低,输出更流畅。这些传感器包括重力传感器 (TYPE_GRAVITY)、旋转矢量传感器 (TYPE_ROTATION_VECTOR) 和线性加速度传感器 (TYPE_LINEAR_ACCELERATION)。改进后的传感器依赖陀螺仪传感器来提升其输出,因此这些传感器只会显示在配备陀螺仪的设备上。

操作栏

ActionBar 已更新,可支持多种新行为。最重要的是,在较小的屏幕上运行时,系统会妥善管理操作栏的尺寸和配置,以便在所有尺寸的屏幕上提供最佳用户体验。例如,当屏幕较窄时(例如手机处于竖屏模式时),操作栏的导航标签页将显示在主操作栏正下方的“堆叠栏”中。您还可以选择启用“分屏操作栏”,在屏幕较窄时,该栏会将所有操作项放置在屏幕底部的单独栏中。

拆分操作栏

如果您的操作栏包含多个操作项,那么在狭窄的屏幕上,并非所有操作项都能容纳到操作栏中,因此系统会将更多操作项放入溢出菜单中。不过,Android 4.0 允许您启用“拆分操作栏”,以便更多操作项可以显示在屏幕底部的单独栏中。如需启用拆分操作栏,请将带有 "splitActionBarWhenNarrow"android:uiOptions 添加到 <application> 标记或清单文件中的各个 <activity> 标记中。启用后,当屏幕较窄时,系统会在屏幕底部为所有操作项额外添加一个栏(主要操作栏中不会显示任何操作项)。

如果您想要使用 ActionBar.Tab API 提供的导航标签页,但不需要在顶部显示主操作栏(您希望仅标签页显示在顶部),请按上述方法启用分屏操作栏,并调用 setDisplayShowHomeEnabled(false) 以停用操作栏中的应用图标。如果主操作栏中没有任何内容,它会消失,左侧只是顶部的导航标签页和屏幕底部的操作项。

操作栏样式

如果想对操作栏应用自定义样式,可以使用新样式属性 backgroundStackedbackgroundSplit,分别将背景可绘制对象或颜色应用于堆叠栏和分屏栏。您还可以在运行时使用 setStackedBackgroundDrawable()setSplitBackgroundDrawable() 设置这些样式。

操作提供程序

通过新的 ActionProvider 类,您可以为操作项创建专用处理程序。操作提供器可以为其关联的每个操作项定义操作视图、默认操作行为和子菜单。如果您想创建具有动态行为(如变量操作视图、默认操作或子菜单)的操作项,那么扩展 ActionProvider 是创建可重复使用的组件的理想解决方案,而不是在 fragment 或 activity 中处理各种操作项转换。

例如,ShareActionProviderActionProvider 的扩展,可辅助操作栏中的“分享”操作。您可以使用此操作提供器来呈现操作视图,其中包含处理 ACTION_SEND intent 的应用下拉列表,而不是使用调用 ACTION_SEND intent 的传统操作项。当用户选择用于执行操作的应用时,ShareActionProvider 会记住您的选择,并在操作视图中提供,以便更快地访问与该应用共享内容。

如需为操作项声明操作提供器,请在 activity 选项菜单的 <item> 元素中添加 android:actionProviderClass 属性,并将操作提供程序的类名称作为值。例如:

<item android:id="@+id/menu_share"
      android:title="Share"
      android:showAsAction="ifRoom"
      android:actionProviderClass="android.widget.ShareActionProvider" />

在您的 activity 的 onCreateOptionsMenu() 回调方法中,从菜单项检索操作提供程序的实例,并设置 intent:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.options, menu)
    val shareActionProvider = menu.findItem(R.id.menu_share)?.actionProvider as? ShareActionProvider
    // Set the share intent of the share action provider.
    shareActionProvider?.setShareIntent(createShareIntent())
    ...
    return super.onCreateOptionsMenu(menu)
}

Java

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.options, menu);
    ShareActionProvider shareActionProvider =
          (ShareActionProvider) menu.findItem(R.id.menu_share).getActionProvider();
    // Set the share intent of the share action provider.
    shareActionProvider.setShareIntent(createShareIntent());
    ...
    return super.onCreateOptionsMenu(menu);
}

如需查看使用 ShareActionProvider 的示例,请参阅 ApiDemos 中的 ActionBarShareActionProviderActivity

折叠式操作视图

现在,提供操作视图的操作项可以在其操作视图状态和传统操作项状态之间切换。以前,只有 SearchView 支持收起作为操作视图时,但现在您可以为任何操作项添加操作视图,并在展开状态(操作视图可见)和收起状态(操作项可见)之间切换。

若要声明包含操作视图的操作项可收起,请在菜单 XML 文件中<item> 元素的 android:showAsAction 属性中添加 “collapseActionView" 标志。

如需在操作视图在展开和收起之间切换时收到回调,请通过调用 setOnActionExpandListener() 向相应的 MenuItem 注册 MenuItem.OnActionExpandListener 实例。通常,您应该在 onCreateOptionsMenu() 回调期间执行此操作。

如需控制可折叠操作视图,您可以对相应的 MenuItem 调用 collapseActionView()expandActionView()

创建自定义操作视图时,您还可以实现新的 CollapsibleActionView 接口,以在视图展开和收起时接收回调。

操作栏的其他 API

  • setHomeButtonEnabled() 可让您指定图标/徽标是用作导航主屏幕的按钮,还是用于“向上”导航(传递“true”可使其像按钮一样运行)。
  • 借助 setIcon()setLogo(),您可以在运行时定义操作栏图标或徽标。
  • Fragment.setMenuVisibility() 可让您启用或停用由 fragment 声明的选项菜单项的可见性。如果 fragment 已添加到 activity 中,但不可见,那么这会非常有用,因此菜单项应处于隐藏状态。
  • FragmentManager.invalidateOptionsMenu() 允许您在 fragment 生命周期的各种状态(使用 Activity 中的等效方法可能无法使用)期间使 activity 选项菜单失效。

界面和视图

Android 4.0 引入了各种新的视图和其他界面组件。

GridLayout

GridLayout 是一个新的视图组,可将子视图放置在矩形网格中。与 TableLayout 不同,GridLayout 依赖于扁平层次结构,不会利用中间视图(例如表行)来提供结构。相反,子项会指定它们应占用的行和列(单元格可以跨越多个行和/或列),并且默认情况下会按顺序排列在网格的行和/列中。GridLayout 方向决定顺序子项默认是水平布局还是垂直布局。可以通过使用新的 Space 视图的实例或为子级设置相关的外边距参数,指定子级之间的间距。

如需查看使用 GridLayout 的示例,请参阅 ApiDemos

TextureView

TextureView 是一个新视图,可让您显示内容流,例如视频或 OpenGL 场景。虽然与 SurfaceView 类似,但 TextureView 的独特之处在于,它的行为类似于常规视图,而不是创建单独的窗口,因此您可以像对待任何其他 View 对象一样对待它。例如,您可以应用转换,使用 ViewPropertyAnimator 为其添加动画效果,或使用 setAlpha() 调整其不透明度。

请注意,TextureView 只能在硬件加速的窗口中运行。

如需了解详情,请参阅 TextureView 文档。

切换微件

新的 Switch widget 是一个双状态切换开关,用户可以将其拖动到一侧或另一侧(或者直接点按),在两种状态之间切换选项。

您可以使用 android:textOnandroid:textOff 属性指定开关上打开和关闭设置时显示的文本。利用 android:text 属性,您还可以在开关旁边放置标签。

如需查看开关的使用示例,请参阅 switches.xml 布局文件和相应的开关 activity。

Android 3.0 引入了 PopupMenu 来创建简短的上下文菜单,这些菜单会在您指定的定位点(通常位于所选项目的点)上弹出。Android 4.0 通过几个实用功能扩展了 PopupMenu

偏好设置

新的 TwoStatePreference 抽象类可用作提供双状态选择选项的偏好设置的基础。新的 SwitchPreferenceTwoStatePreference 的扩展,它在偏好设置视图中提供了一个 Switch widget,可让用户开启或关闭某项设置,而无需打开额外的偏好设置屏幕或对话框。例如,“设置”应用会使用 SwitchPreference 进行 Wi-Fi 和蓝牙设置。

系统主题

以 Android 4.0 为目标平台的所有应用的默认主题(通过将 targetSdkVersionminSdkVersion 设置为 “14" 或更高版本)现在是“设备默认”主题:Theme.DeviceDefault。这可能是深色 Holo 主题,也可能是特定设备定义的其他深色主题。

在运行同一版本的 Android 时,Theme.Holo 主题系列保证不会在不同设备之间切换。如果您将任何 Theme.Holo 主题明确应用于 activity,那么请放心,这些主题不会在同一平台版本内的不同设备上更改字符。

如果您希望应用与整体设备主题浑然一体(例如,当不同的 OEM 为系统提供不同的默认主题时),应明确应用来自 Theme.DeviceDefault 系列的主题。

选项菜单按钮

从 Android 4.0 开始,您会发现手机不再需要“菜单”硬件按钮。不过,如果现有应用提供选项菜单并预计会有“菜单”按钮,则无需担心此问题。为了确保现有应用继续按预期运行,系统会为专为旧版 Android 设计的应用提供屏幕菜单按钮。

为了提供最佳用户体验,新应用和更新后的应用应改用 ActionBar 来提供菜单项的访问权限,并将 targetSdkVersion 设置为 "14",以利用最新的框架默认行为。

用于实现系统界面可见性的控件

从 Android 推出早期开始,系统一直管理着一个名为“状态栏”的界面组件,该组件位于手机设备顶部,用于传递运营商信号、时间、通知等信息。Android 3.0 为平板电脑设备添加了系统栏,该系统栏位于屏幕底部,用于提供系统导航控件(主屏幕、返回等),以及状态栏通常提供的元素界面。在 Android 4.0 中,系统提供了一种新的系统界面,称为导航栏。您可以将导航栏视为专为手机设计的系统栏的重新调优版本。它会为没有在系统中导航的硬件对应的设备提供导航控件,但省去了系统栏的通知界面和设置控件。因此,提供导航栏的设备在顶部也会显示状态栏。

现在,您可以使用 FLAG_FULLSCREEN 标志隐藏手机上的状态栏。在 Android 4.0 中,控制系统栏可见性的 API 已更新,以更好地反映系统栏和导航栏的行为:

  • SYSTEM_UI_FLAG_LOW_PROFILE 标志取代了 STATUS_BAR_HIDDEN 标志。设置后,此标志会为系统栏或导航栏启用“低调”模式。导航按钮会变暗,系统栏中的其他元素也会隐藏起来。启用此功能有助于创建沉浸感更强的游戏,而不会分散注意力,让系统导航按钮分心。
  • SYSTEM_UI_FLAG_VISIBLE 标志取代 STATUS_BAR_VISIBLE 标志,以请求系统栏或导航栏可见。
  • SYSTEM_UI_FLAG_HIDE_NAVIGATION 是一个新标志,用于请求完全隐藏导航栏。请注意,这仅适用于某些手机使用的导航栏(它不会在平板电脑上隐藏系统栏)。系统收到用户输入后,导航栏会立即返回视图。因此,此模式主要适用于视频播放或其他需要整个屏幕但不需要用户输入的情况。

您可以对 activity 中的任何视图调用 setSystemUiVisibility(),为系统栏和导航栏设置所有这些标志。窗口管理器会将窗口中所有视图的所有标记合并(或合并),只要您的窗口具有输入焦点,它们就会应用于系统界面。当您的窗口失去输入焦点(用户离开您的应用,或出现一个对话框)时,标记会失效。同样,如果您从视图层次结构中移除这些视图,其标志将不再适用。

如需在系统界面的可见性发生变化时同步 activity 中的其他事件(例如,在系统界面隐藏时隐藏操作栏或其他界面控件),您应注册 View.OnSystemUiVisibilityChangeListener,以便在系统栏或导航栏的可见性发生变化时收到通知。

有关不同系统界面选项的演示,请参阅 OverscanActivity 类。

输入框架

Android 4.0 添加了对光标悬停事件以及新的触控笔和鼠标按钮事件的支持。

悬停事件

View 类现在支持“悬停”事件,通过使用指针设备(例如鼠标或其他驱动屏幕光标的设备)实现更丰富的互动。

如需在视图上接收悬停事件,请实现 View.OnHoverListener 并使用 setOnHoverListener() 注册它。当视图上发生悬停事件时,监听器会收到对 onHover() 的调用,提供接收事件的 View 和描述所发生悬停事件类型的 MotionEvent。悬停事件可以是以下其中一项:

如果 View.OnHoverListener 会处理悬停事件,则应从 onHover() 返回 true。如果监听器返回 false,悬停事件将照常分派给父视图。

如果您的应用使用会根据当前状态更改其外观的按钮或其他 widget,您现在可以在状态列表可绘制对象中使用 android:state_hovered 属性,以便在光标悬停在视图上时提供不同的背景可绘制对象。

有关新悬停事件的演示,请参阅 ApiDemos 中的 Hover 类。

触控笔和鼠标按钮事件

Android 现在提供了用于从触控笔输入设备(例如数字化板外围设备或支持触控笔的触摸屏)接收输入的 API。

触控笔输入的运作方式与触摸或鼠标输入类似。当触控笔与数字转换器接触时,应用会接收触摸事件,就像用手指触摸显示屏时一样。当触控笔悬停在数字转换器上方时,应用会接收悬停事件,就像在没有按下任何按钮的情况下在显示屏上移动鼠标指针时一样。

您的应用可以使用 getToolType() 查询与 MotionEvent 中的每个指针关联的“工具类型”,从而区分手指、鼠标、触控笔和橡皮擦输入。当前定义的工具类型包括:TOOL_TYPE_UNKNOWNTOOL_TYPE_FINGERTOOL_TYPE_MOUSETOOL_TYPE_STYLUSTOOL_TYPE_ERASER。通过查询工具类型,您的应用可以选择以不同于手指或鼠标输入的不同方式处理触控笔输入。

您的应用还可以使用 getButtonState() 查询 MotionEvent 的“按钮状态”,从而查询按下的鼠标或触控笔按钮。目前定义的按钮状态包括:BUTTON_PRIMARYBUTTON_SECONDARYBUTTON_TERTIARYBUTTON_BACKBUTTON_FORWARD。为方便起见,向后和向前鼠标按钮会自动映射到 KEYCODE_BACKKEYCODE_FORWARD 键。您的应用可以处理这些键,以支持基于鼠标按钮的后退和前进导航。

除了精确测量触点的位置和压力之外,一些触控笔输入设备还会报告触控笔尖端与数字转换器之间的距离、触控笔倾斜角度和触控笔方向角。您的应用可以使用 getAxisValue()(采用轴代码 AXIS_DISTANCEAXIS_TILTAXIS_ORIENTATION)查询此信息。

有关工具类型、按钮状态和新轴代码的演示,请参阅 ApiDemos 中的 TouchPaint 类。

属性

新的 Property 类提供了一种快速、高效且简便的方式来为任何对象指定属性,以允许调用方通过一般方式设置/获取目标对象的值。它还允许传递字段/方法引用,并允许代码在不知道字段/方法是什么的详细信息的情况下设置/获取属性的值。

例如,如果要在对象 foo 上设置 bar 字段的值,则需预先添加以下值:

Kotlin

foo.bar = value

Java

foo.bar = value;

如果您要为底层不公开字段 bar 调用 setter,则之前需要添加以下代码:

Kotlin

foo.setBar(value)

Java

foo.setBar(value);

不过,如果您想传递 foo 实例并让一些其他代码设置 bar 值,在 Android 4.0 之前的版本中,确实无法做到这一点。

使用 Property 类,您可以在类 Foo 上声明 Property 对象 BAR,以便可以在 Foo 类的实例 foo 上设置该字段,如下所示:

Kotlin

BAR.set(foo, value)

Java

BAR.set(foo, value);

View 类现在利用 Property 类允许您设置各种字段,例如在 Android 3.0 中添加的转换属性(ROTATIONROTATION_XTRANSLATION_X 等)。

ObjectAnimator 类也使用 Property 类,因此您可以使用 Property 创建 ObjectAnimator,与基于字符串的方法相比,这种方法更快、更高效、更安全。

硬件加速

从 Android 4.0 开始,如果您的应用已将 targetSdkVersionminSdkVersion 设为 “14" 或更高版本,则默认情况下会启用所有窗口的硬件加速功能。硬件加速通常可使动画和滚动更流畅,并且能够提升整体性能和用户互动响应。

如有必要,您可以使用各个 <activity> 元素或 <application> 元素的 hardwareAccelerated 属性手动停用硬件加速。您也可以通过调用 setLayerType(LAYER_TYPE_SOFTWARE) 为各个视图停用硬件加速。

如需详细了解硬件加速(包括不支持的绘制操作的列表),请参阅硬件加速文档。

JNI 变更

在以前的 Android 版本中,JNI 局部引用不是间接句柄;Android 使用的是直接指针。只要垃圾回收器不移动对象,这就不会成为问题,但它似乎可以正常运行,因为它使编写有 bug 的代码成为可能。在 Android 4.0 中,系统现在使用间接引用来检测这些 bug。

JNI 提示中的“局部和全局引用”部分介绍了 JNI 局部引用的来龙去脉。在 Android 4.0 中, CheckJNI 已得到增强,可以检测这些错误。请访问 Android 开发者博客,查看即将推出的文章,了解 JNI 引用常见错误及解决方法。

JNI 实现中的这一变更只会影响以 Android 4.0 为目标平台的应用(通过将 targetSdkVersionminSdkVersion 设置为 “14" 或更高版本)。如果您将这些属性设为任何较低值,则 JNI 局部引用的行为与先前版本中的行为相同。

WebKit

  • WebKit 已更新至 534.30 版
  • WebView 和内置浏览器中支持印度语字体(梵文、孟加拉和泰米尔语,包括组合字形所需的复杂字符)
  • 支持 WebView 中的埃塞俄比亚、格鲁吉亚和亚美尼亚语字体,以及内置浏览器
  • WebDriver 的支持可让您更轻松地测试使用 WebView 的应用

Android 浏览器

浏览器应用程序添加了以下功能来支持 Web 应用程序:

权限

以下是新权限:

设备功能

以下是新的设备功能:

如需详细了解 Android 4.0(API 级别 14)中的所有 API 变更,请参阅 API 差异报告

旧版 API

除了上述各项之外,Android 4.0 自然也支持之前版本的所有 API。由于 Android 3.x 平台仅适用于大屏设备,因此如果您的开发主要是针对手机开发的,那么您可能不了解这些最近版本中添加到 Android 的所有 API。

下面来看一下您可能错过的一些最值得关注的 API,但这些 API 现在也已在手机上推出:

Android 3.0
  • Fragment:一种框架组件,可让您将 activity 的不同元素拆分为独立的模块,这些模块可定义自己的界面和生命周期。请参阅 fragment 开发者指南。
  • ActionBar:用于替代 activity 窗口顶部的传统标题栏。它左上角包括应用徽标,并为菜单项提供了新界面。请参阅操作栏开发者指南。
  • Loader:一种框架组件,有助于异步加载数据,并与界面组件结合使用,以动态加载数据而不阻塞主线程。请参阅加载器开发者指南。
  • 系统剪贴板:应用可以将数据(不仅仅是文本)复制并粘贴到系统级剪贴板,或从中粘贴数据。裁剪数据可以是纯文本、URI 或 intent。请参阅复制和粘贴开发者指南。
  • 拖放:一组内置于视图框架中的 API,有助于实现拖放操作。请参阅拖放开发者指南。
  • 借助全新的灵活动画框架,您可以为任何对象(View、Drawable、Fragment、Object 或任何其他对象)的任意属性添加动画效果,并定义动画方面,例如时长、插值、重复等。新框架使 Android 中的动画变得前所未有的简单。请参阅属性动画开发者指南。
  • RenderScript 图形和计算引擎:RenderScript 在原生级别提供高性能 3D 图形渲染和计算 API,该 API 是用 C(C99 标准)编写的,能够提供您期望原生环境的性能类型,同时在不同 CPU 和 GPU 上移植。请参阅 RenderScript 开发者指南。
  • 硬件加速 2D 图形:现在,您可以通过在清单元素的 <application> 元素中或为各个 <activity> 元素中设置 {android:hardwareAccelerated="true"},为您的应用启用 OpenGL 渲染程序。这样可以带来更流畅的动画和更流畅的滚动体验,从而提高用户交互的总体性能和响应速度。

    注意:如果您将应用的 minSdkVersiontargetSdkVersion 设置为 "14" 或更高版本,则硬件加速默认处于启用状态。

  • 以及更多内容。如需了解详情,请参阅 Android 3.0 平台说明。
Android 3.1
  • USB API:功能强大的全新 API,用于将已连接的外围设备与 Android 应用集成。这些 API 基于平台内置的 USB 堆栈和服务,包括对 USB 主机和设备交互的支持。请参阅 USB 主机和配件开发者指南。
  • MTP/PTP API:应用可以直接与连接的摄像头和其他 PTP 设备交互,以便在连接和移除设备时接收通知、管理这些设备上的文件和存储,以及与这些设备之间的文件和元数据。MTP API 可实现 MTP(媒体传输协议)规范的 PTP(图片传输协议)子集。请参阅 android.mtp 文档。
  • RTP API:Android 向其内置 RTP(实时传输协议)堆栈公开了一个 API,应用可以使用它来管理按需或交互式数据流。具体而言,提供 VoIP、推送通话、会议和音频流式传输的应用可以使用该 API 启动会话,并通过任何可用网络传输或接收数据流。请参阅 android.net.rtp 文档。
  • 支持操纵杆和其他通用动作输入。
  • 如需了解更多新 API,请参阅 Android 3.1 平台说明。
Android 3.2
  • 新屏幕支持 API,可让您更好地控制应用在不同屏幕尺寸上的显示方式。该 API 扩展了现有的屏幕支持模型,能够按尺寸精确定位特定屏幕尺寸范围,以密度无关像素单位(例如 600dp 或 720dp 宽)为单位,而不是按通用屏幕尺寸(例如大或特大)进行衡量。例如,这有助于您区分 5 英寸的设备和 7 英寸的设备,因为后者过去分桶为“大”屏幕。请参阅博文 用于管理屏幕尺寸的新工具
  • <uses-feature> 新增了常量,用于声明横向或纵向屏幕方向要求。
  • 现在,设备“屏幕尺寸”配置会在屏幕方向变化时发生变化。如果您的应用以 API 级别 13 或更高级别为目标平台,并且还想处理 "orientation" 配置变更,则必须自行处理 "screenSize" 配置变更。如需了解详情,请参阅 android:configChanges
  • 如需了解其他新 API,请参阅 Android 3.2 平台说明。

API 级别

Android 4.0 API 被分配一个整数标识符 (14),该标识符存储在系统本身中。此标识符称为“API 级别”,可让系统在安装应用之前正确确定应用是否与系统兼容。

如需在应用中使用 Android 4.0 中引入的 API,您需要针对支持 API 级别 14 或更高级别的 Android 平台编译应用。您可能还需要将 android:minSdkVersion="14" 属性添加到 <uses-sdk> 元素中,具体取决于您的需求。

如需了解详情,请参阅什么是 API 级别?