API 级别:16
Android 4.1 (JELLY_BEAN
) 是 Android 平台的一个进步版本,可提供更高的性能和增强的用户体验。它为用户和应用开发者添加了新功能。本文旨在向应用开发者介绍其中最值得关注且实用的新 API。
作为应用开发者,您可以通过 SDK 管理器将 Android 4.1 作为可在 Android 模拟器中运行的系统映像,以及可据以构建应用的 SDK 平台使用。您应尽快下载系统映像和平台,以便在 Android 4.1 上构建和测试您的应用。
要进一步优化您的应用在搭载 Android 4.1 的设备上的性能,应将您的 targetSdkVersion
设置为 "16"
,在 Android 4.1 系统映像上安装您的应用并进行测试,然后发布此变更的更新。
您可以通过在代码中添加条件,在执行您的 minSdkVersion
不支持的 API 之前检查系统 API 级别,实现在使用 Android 4.1 中的 API 的同时仍为旧版本提供支持。如需详细了解如何保持向后兼容性,请参阅创建向后兼容的界面。
如需详细了解 API 级别的运作方式,请参阅什么是 API 级别?
应用组件
隔离的服务
通过在 <service>
标记中指定 android:isolatedProcess="true"
,您的 Service
将在自己的独立用户 ID 进程下运行,该进程自身没有权限。
内存管理
新的 ComponentCallbacks2
常量(如 TRIM_MEMORY_RUNNING_LOW
和 TRIM_MEMORY_RUNNING_CRITICAL
)可在系统调用 onLowMemory()
之前为前台进程提供有关内存状态的更多信息。
借助新的 getMyMemoryState(ActivityManager.RunningAppProcessInfo)
方法,您可以检索常规内存状态。
content provider
借助新方法 acquireUnstableContentProviderClient()
,您可以访问可能“不稳定”的 ContentProviderClient
,这样一来,即使 content provider 发生崩溃,您的应用也不会崩溃。当您在单独的应用中与内容提供程序互动时,此方法非常有用。
动态壁纸
新增了 intent 协议,用于直接启动动态壁纸预览 activity,以便您帮助用户轻松选择您的动态壁纸,而无需强制他们离开您的应用并在主屏幕壁纸选择器中导航。
如需启动动态壁纸选择器,请使用 ACTION_CHANGE_LIVE_WALLPAPER
和在 EXTRA_LIVE_WALLPAPER_COMPONENT
中将动态壁纸 ComponentName
指定为字符串的 extra 调用 startActivity()
中的 Intent
。
应用堆栈导航
Android 4.1 让您可以更轻松地为向上导航实现适当的设计模式。您只需向清单文件中的每个 <activity>
元素添加 android:parentActivityName
即可。当用户按下操作栏中的“向上”按钮时(同时结束当前 activity),系统会使用此信息打开相应的 activity。因此,如果您为每个 activity 声明 android:parentActivityName
,则无需使用 onOptionsItemSelected()
方法来处理操作栏应用图标上的点击事件,因为系统现在会处理该事件,并恢复或创建相应的 activity。
对于用户通过“深入探究”intent(例如来自通知或来自其他应用的 intent)进入应用的某个 activity 的情况,此功能尤为强大(如在应用之间导航设计指南中所述)。当用户以这种方式进入您的 activity 时,您的应用可能不会自然地包含可在用户向上导航时恢复的 activity 返回堆栈。不过,当您为 activity 提供 android:parentActivityName
属性时,系统会识别您的应用是否已包含父 activity 的返回堆栈,如果没有,则构建包含所有父 activity 的合成返回堆栈。
注意:当用户进入应用中的深层 activity 并为应用创建新任务时,系统实际上会将父 activity 的堆栈插入该任务中。因此,按返回按钮也会通过父 activity 堆栈返回。
当系统为应用创建合成返回堆栈时,它会构建基本 Intent
以创建每个父 activity 的新实例。因此,父 activity 没有保存的状态,这与您预期用户自然浏览每个 activity 的方式不同。如果任何父 Activity 正常显示依赖于用户上下文的界面,则将缺少该上下文信息,您应在用户返回堆栈时提供该上下文信息。例如,如果用户在音乐应用中查看某张专辑,则向上导航可能会将其带到一个 activity,其中列出了所选音乐类型中的所有专辑。在这种情况下,如果必须创建堆栈,您必须告知父 activity 当前影集所属的类型,以便父 activity 能够显示适当的列表,就像用户实际上来自该 activity 一样。如需将此类信息传递给合成父 activity,您必须替换 onPrepareNavigateUpTaskStack()
方法。这会为您提供系统创建的 TaskStackBuilder
对象,以便合成父 activity。TaskStackBuilder
包含系统用于创建每个父 activity 的 Intent
对象。在 onPrepareNavigateUpTaskStack()
实现中,您可以修改相应的 Intent
以添加额外数据,以便父 activity 使用这些数据来确定适当的上下文并显示适当的界面。
当系统创建 TaskStackBuilder
时,它会从 activity 树顶部开始,按逻辑顺序添加用于创建父 activity 的 Intent
对象。因此,最后添加到内部数组的 Intent
是当前 activity 的直接父项。如果您想修改 activity 的父级的 Intent
,请先使用 getIntentCount()
确定数组的长度,然后将该值传递给 editIntentAt()
。
如果您的应用结构更复杂,您可以使用其他一些 API 来处理向上导航的行为并完全自定义合成返回堆栈。可让您实现更多控制的部分 API 包括:
onNavigateUp()
- 替换此方法可在用户按下“向上”按钮时执行自定义操作。
navigateUpTo(Intent)
- 调用此方法可结束当前 activity 并转到所提供的
Intent
所指示的 activity。如果 activity 存在于返回堆栈中,但不是最近的父 activity,则当前 activity 与使用 intent 指定的 activity 之间的所有其他 activity 也会结束。 getParentActivityIntent()
- 调用此方法可获取将启动当前 activity 的逻辑父项的
Intent
。 shouldUpRecreateTask(Intent)
- 调用此方法可查询是否必须创建合成返回堆栈才能向上导航。如果必须创建合成堆栈,则返回 true;如果相应的堆栈已存在,则返回 false。
finishAffinity()
- 调用此方法可结束当前 activity 以及与当前 activity 链接且具有相同任务关联的所有父 activity。
如果您替换了默认行为(例如
onNavigateUp()
),则应在向上导航时创建合成返回堆栈时调用此方法。 onCreateNavigateUpTaskStack
- 如果您需要完全控制合成任务堆栈的创建方式,请替换此方法。如果您只想向返回堆栈的 intent 添加一些额外数据,则应改为替换
onPrepareNavigateUpTaskStack()
不过,大多数应用不需要使用这些 API 或实现 onPrepareNavigateUpTaskStack()
,只需向每个 <activity>
元素添加 android:parentActivityName
即可实现正确的行为。
多媒体
媒体编解码器
MediaCodec
类可让您使用低级别媒体编解码器,以便对媒体进行编码和解码。您可以通过调用 createEncoderByType()
对媒体进行编码,或调用 createDecoderByType()
解码媒体,从而实例化 MediaCodec
。每种方法都接受您要编码或解码的媒体类型的 MIME 类型,例如 "video/3gpp"
或 "audio/vorbis"
。
创建 MediaCodec
的实例后,您可以调用 configure()
来指定媒体格式或内容是否加密等属性。
无论您是编码还是解码媒体,创建 MediaCodec
后,其余流程都是相同的。首先调用 getInputBuffers()
以获取输入 ByteBuffer
对象的数组,然后调用 getOutputBuffers()
以获取输出 ByteBuffer
对象的数组。
准备好进行编码或解码后,请调用 dequeueInputBuffer()
以获取您应用于馈入源媒体的 ByteBuffer
(从输入缓冲区数组)的索引位置。使用源媒体填充 ByteBuffer
后,请调用 queueInputBuffer()
释放缓冲区所有权。
同样,对于输出缓冲区,请调用 dequeueOutputBuffer()
以获取您将接收结果的 ByteBuffer
的索引位置。从 ByteBuffer
读取输出后,请通过调用 releaseOutputBuffer()
释放所有权。
您可以通过将 queueSecureInputBuffer()
与 MediaCrypto
API(而不是常规的 queueInputBuffer()
)结合调用,在编解码器中处理加密媒体数据。
如需详细了解如何使用编解码器,请参阅 MediaCodec
文档。
按提示录制音频
借助新方法 startRecording()
,您可以根据 MediaSyncEvent
定义的提示开始录音。MediaSyncEvent
用于指定音频会话(例如由 MediaPlayer
定义的会话),当该会话完成时,会触发音频录音机开始录制。例如,您可以使用此功能播放指示录制会话开始的音频提示音并自动开始录制,这样您就不必手动同步提示音和录制的开头。
定时文本轨道
MediaPlayer
现在同时处理带内文本轨道和带外文本轨道。带内文本轨道是指 MP4 或 3GPP 媒体源中的文本轨道。您可以通过 addTimedTextSource()
方法将带外文本轨道添加为外部文本源。添加所有外部文本轨道来源后,应调用 getTrackInfo()
以获取数据源中所有可用轨道的刷新列表。
如需设置要与 MediaPlayer
一起使用的轨道,您必须使用要使用的轨道的索引位置调用 selectTrack()
。
如需在文本轨道可以播放时收到通知,请实现 MediaPlayer.OnTimedTextListener
接口并将其传递给 setOnTimedTextListener()
。
音效
AudioEffect
类现在支持在捕获音频时使用其他音频预处理类型:
- 结合使用
AcousticEchoCanceler
的回声消除器 (AEC) 会从捕获的音频信号中移除从远程方接收的信号贡献。 - 使用
AutomaticGainControl
的自动增益控制 (AGC) 功能会自动对捕获的信号的输出进行归一化。 - 带有
NoiseSuppressor
的噪声抑制器 (NS) 可从捕获的信号中滤除背景噪声。
您可以使用 AudioEffect
子类之一,将这些预处理器效果应用于使用 AudioRecord
捕获的音频。
注意:我们无法保证所有设备都支持这些效果,因此请务必先对相应的音频效果类调用 isAvailable()
以检查可用性。
无间断播放
现在,您可以在两个单独的 MediaPlayer
对象之间进行无缝播放。在第一个 MediaPlayer
完成之前的任何时间调用 setNextMediaPlayer()
,Android 会在第一个播放器停止时尝试启动第二个播放器。
相机
自动对焦移动
借助新接口 Camera.AutoFocusMoveCallback
,您可以监听自动对焦移动的变化。您可以向 setAutoFocusMoveCallback()
注册接口。然后,当相机处于连续自动对焦模式 (FOCUS_MODE_CONTINUOUS_VIDEO
或 FOCUS_MODE_CONTINUOUS_PICTURE
) 时,您会收到对 onAutoFocusMoving()
的调用,该调用会告知您自动对焦是否已开始移动或已停止移动。
相机提示音
MediaActionSound
类提供了一组简单的 API,用于生成相机或其他媒体操作发出的标准音效。在构建自定义静态摄像头或视频摄像头时,您应使用这些 API 播放适当的声音。
如需播放声音,只需实例化 MediaActionSound
对象,调用 load()
来预加载所需的声音,然后在适当的时间调用 play()
即可。
连接
Android Beam
Android BeamTM 现在支持通过蓝牙传输大型有效负载。当您使用新的 setBeamPushUris()
方法或新的回调接口 NfcAdapter.CreateBeamUrisCallback
定义要传输的数据时,Android 会将数据传输交给蓝牙或其他备用传输方式,以实现更快的传输速度。这对于图片和音频文件等大型载荷特别有用,并且无需在设备之间进行明显配对。您的应用无需执行任何额外操作,即可利用蓝牙传输功能。
setBeamPushUris()
方法接受一个 Uri
对象数组,用于指定您要从应用传输的数据。或者,您也可以实现 NfcAdapter.CreateBeamUrisCallback
接口,并通过调用 setBeamPushUrisCallback()
为 activity 指定该接口。
使用回调接口时,当用户使用 Android Beam 执行分享时,系统会调用接口的 createBeamUris()
方法,以便您在分享时定义要分享的 URI。如果要共享的 URI 可能会因 activity 中的用户上下文而异,则调用 setBeamPushUris()
会很有用;如果要共享的 URI 不会发生变化,并且您可以提前安全地定义它们,则调用 setBeamPushUris()
会很有用。
网络服务发现
Android 4.1 添加了对基于多播 DNS 的服务发现的支持,可让您通过 Wi-Fi 找到并连接到对等设备(例如移动设备、打印机、相机、媒体播放器以及在本地网络上注册的其他设备)提供的服务。
新软件包 android.net.nsd
包含新的 API,可让您在本地网络上广播服务、发现网络上的本地设备以及连接到设备。
如需注册服务,您必须先创建一个 NsdServiceInfo
对象,然后使用 setServiceName()
、setServiceType()
和 setPort()
等方法定义服务的各种属性。
然后,您需要实现 NsdManager.RegistrationListener
并使用 NsdServiceInfo
将其传递给 registerService()
。
如需发现网络上的服务,请实现 NsdManager.DiscoveryListener
并将其传递给 discoverServices()
。
当 NsdManager.DiscoveryListener
收到有关找到的服务的回调时,您需要通过调用 resolveService()
来解析服务,并向其传递 NsdManager.ResolveListener
的实现,该实现会接收包含所发现服务的相关信息的 NsdServiceInfo
对象,以便您发起连接。
WLAN 点对点服务发现
Android 4.1 增强了 Wi-Fi 点对点 API,以支持 WifiP2pManager
中的预关联服务发现。这样,您就可以在连接到附近的设备之前,使用 Wi-Fi P2P 按服务发现和过滤附近的设备,而网络服务发现可让您在已连接的现有网络(例如本地 Wi-Fi 网络)上发现服务。
如需通过 Wi-Fi 将您的应用作为服务广播,以便其他设备可以发现您的应用并连接到它,请使用描述应用服务的 WifiP2pServiceInfo
对象调用 addLocalService()
。
如需通过 Wi-Fi 启动附近设备的发现,您需要先决定是使用 Bonjour 还是 Upnp 进行通信。如需使用 Bonjour,请先使用 setDnsSdResponseListeners()
设置一些回调监听器,该监听器同时接受 WifiP2pManager.DnsSdServiceResponseListener
和 WifiP2pManager.DnsSdTxtRecordListener
。如需使用 Upnp,请调用 setUpnpServiceResponseListener()
,该方法接受一个 WifiP2pManager.UpnpServiceResponseListener
作为参数。
您还需要调用 addServiceRequest()
,才能开始在本地设备上发现服务。当您传递给此方法的 WifiP2pManager.ActionListener
收到成功回调后,您就可以通过调用 discoverServices()
开始在本地设备上发现服务。
发现本地服务后,您会收到对 WifiP2pManager.DnsSdServiceResponseListener
或 WifiP2pManager.UpnpServiceResponseListener
的回调,具体取决于您注册使用 Bonjour 还是 Upnp。在任一情况下收到的回调都包含一个代表对等设备的 WifiP2pDevice
对象。
网络用量
新方法 isActiveNetworkMetered()
可让您检查设备当前是否连接到按流量计费的网络。通过在执行密集的网络事务之前检查此状态,您可以帮助管理可能会给用户带来费用的数据流量,并就是否立即执行事务(例如在设备连接到 Wi-Fi 时)做出明智的决策。
无障碍
无障碍服务 API
在 Android 4.1 中,无障碍服务 API 的覆盖范围显著扩大。现在,您可以通过向 AccessibilityEvent
、AccessibilityNodeInfo
和 AccessibilityRecord
类添加内容,构建可监控和响应更多输入事件的服务,例如使用 onGesture()
的复杂手势和其他输入事件。
无障碍服务还可以代表用户执行操作,包括使用 performAction
和 setMovementGranularities
点击、滚动和逐字逐句浏览文本。performGlobalAction()
方法还允许服务执行“返回”“主屏幕”等操作,以及打开“最近用过的应用”和“通知”。
可自定义的应用导航栏
构建 Android 应用时,您现在可以使用 findFocus()
和 focusSearch()
查找可聚焦的元素和输入 widget,并使用 setAccessibilityFocused()
设置焦点,从而自定义导航栏方案。
更易于访问的微件
借助新的 android.view.accessibility.AccessibilityNodeProvider
类,您可以向无障碍服务显示复杂的自定义视图,以便它们以更易于访问的方式呈现信息。借助 android.view.accessibility.AccessibilityNodeProvider
,包含高级内容(例如日历网格)的用户 widget 可以为无障碍服务呈现逻辑语义结构,该结构与 widget 的布局结构完全分离。借助这种语义结构,无障碍服务可以为视障用户提供更实用的交互模型。
复制和粘贴
使用 intent 复制和粘贴
您现在可以使用 setClipData()
方法将 ClipData
对象与 Intent
相关联。当使用 intent 将多个 content:
URI 传输到另一个应用时,这尤其有用,例如在共享多个文档时。以这种方式提供的 content:
URI 也会遵循 intent 的标志提供读取或写入权限,让您能够授予对 intent 中的多个 URI 的访问权限。启动 ACTION_SEND
或 ACTION_SEND_MULTIPLE
intent 时,intent 中提供的 URI 现在会自动传播到 ClipData
,以便接收器可以获得对它们的访问权限。
支持 HTML 和字符串样式
ClipData
类现在支持带样式的文本(HTML 或 Android 带样式的字符串)。您可以使用 newHtmlText()
向 ClipData
添加 HTML 样式的文本。
Renderscript
增强了 RenderScript 计算功能,新增了以下功能:
- 支持在一个脚本中使用多个内核。
- 在新脚本 API
rsSample
中,支持使用已过滤的采样器从计算中读取数据。 - 支持
#pragma
中的不同级别的 FP 精度。 - 支持通过计算脚本从 RS 对象查询其他信息。
- 进行了多项性能改进。
您还可以使用新的 pragma 来设定计算 Renderscript 所需的浮点精确率。这样,您就可以启用诸如 CPU 路径上的快速矢量数学运算等 NEON 运算,使用完整的 IEEE 754-2008 标准是不可能实现的。
注意:实验性 Renderscript 图形引擎现已弃用。
动画
activity 启动动画
您现在可以使用缩放动画或您自己的自定义动画启动 Activity
。如需指定所需的动画,请使用 ActivityOptions
API 构建一个 Bundle
,然后将其传递给启动 activity 的任何方法(例如 startActivity()
)。
ActivityOptions
类针对您可能希望在 activity 打开时显示的每种类型的动画提供了不同的方法:
makeScaleUpAnimation()
- 创建一个动画,以便从屏幕上的指定起始位置和指定的起始大小放大 activity 窗口。例如,Android 4.1 中的主屏幕在打开应用时使用此名称。
makeThumbnailScaleUpAnimation()
- 创建一个动画,从指定位置和提供的缩略图开始放大 activity 窗口。例如,Android 4.1 中的“最近用过的应用”窗口会在返回应用时使用此窗口。
makeCustomAnimation()
- 创建由您自己的资源定义的动画:一个用于定义 activity 打开的动画,另一个用于定义 activity 停止的动画。
时间动画
新版 TimeAnimator
通过 TimeAnimator.TimeListener
提供了一种简单的回调机制,可在动画的每一帧中通知您。此 Animator 没有时长、插值或对象值设置。监听器的回调会接收每个帧的信息,包括总经过时间和自上一动画帧以来经过的时间。
界面
通知
在 Android 4.1 中,您可以创建具有更大内容区域、大图像预览、多个操作按钮和可配置优先级的通知。
通知样式
借助新方法 setStyle()
,您可以为通知指定三种新样式中的一种,每种样式都提供更大的显示区域。如需为大内容区域指定样式,请将以下对象之一传递给 setStyle()
:
Notification.BigPictureStyle
- 。适用于包含大型图片附件的通知。
Notification.BigTextStyle
- 对于包含大量文字的通知,例如单个电子邮件。
Notification.InboxStyle
- 适用于包含字符串列表的通知,例如来自多封电子邮件的摘要。
通知操作
现在,无论通知使用的是常规样式还是较大的样式,都可以在通知消息底部显示最多两个操作按钮。
如需添加操作按钮,请调用 addAction()
。此方法接受三个实参:图标的可绘制资源、按钮的文本,以及用于定义要执行的操作的 PendingIntent
。
优先事项
现在,您可以使用 setPriority()
设置优先级,以向系统暗示通知的重要性,从而影响通知在列表中的顺序。您可以从 Notification
类中的 PRIORITY_*
常量定义的五个不同优先级中选择一种。默认值为 PRIORITY_DEFAULT
,高于该值有两个级别,低于该值有两个级别。
高优先级通知是用户通常希望快速响应的内容,例如新的即时消息、短信或即将发生的活动提醒。低优先级通知包括已过期的日历活动或应用促销活动等。
系统界面控件
Android 4.0 (Ice Cream Sandwich) 添加了新标志,用于控制系统界面元素的可见性,例如调暗系统栏的外观或使其完全在手机上消失。Android 4.1 添加了更多标志,以便您通过调用 setSystemUiVisibility()
并传递以下标志,进一步控制系统界面元素的外观以及与这些元素相关的 activity 布局:
SYSTEM_UI_FLAG_FULLSCREEN
- 隐藏非关键系统界面(例如状态栏)。
如果您的 Activity 在叠加模式下使用操作栏(通过启用
android:windowActionBarOverlay
),则此标志也会隐藏操作栏,并在隐藏和显示操作栏时通过协调动画执行此操作。 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- 设置 activity 布局,使其可用的屏幕区域与启用了
SYSTEM_UI_FLAG_FULLSCREEN
时一样,即使系统界面元素仍可见也是如此。虽然布局的某些部分将由系统界面叠加,但如果您的应用经常使用SYSTEM_UI_FLAG_FULLSCREEN
隐藏和显示系统界面,这种做法会非常有用,因为这样可以避免布局在每次系统界面隐藏或显示时根据新的布局边界进行调整。 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- 将 activity 布局设置为使用在您启用
SYSTEM_UI_FLAG_HIDE_NAVIGATION
(在 Android 4.0 中引入)后可用的同一屏幕区域,即使系统界面元素仍然可见。虽然导航栏会叠加在布局的某些部分上,但如果您的应用经常使用SYSTEM_UI_FLAG_HIDE_NAVIGATION
隐藏和显示导航栏,则此方法非常有用,因为它可以避免布局在导航栏每次隐藏或显示时都调整到新的布局边界。 SYSTEM_UI_FLAG_LAYOUT_STABLE
- 如果您使用
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
和/或SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
,则可能需要添加此标志,以确保在视图上调用fitSystemWindows()
时,定义的边界就可用的屏幕空间保持一致。 也就是说,设置此标志后,即使您隐藏所有系统界面,fitSystemWindows()
的行为也会像系统界面元素的可见性保持不变一样。
如需详细了解其他相关的系统界面标志,请参阅 Android 4.0 中添加的标志。
远程视图
GridLayout
和 ViewStub
现在是远程视图,因此您可以在应用微件的布局和通知自定义布局中使用它们。
字体系列
Android 4.1 添加了 Roboto 字体样式的更多变体,总共有 10 种变体,并且所有这些变体都适用于应用。您的应用现在可以使用完整的浅色和紧凑变体。
可用的完整 Roboto 字体变体集如下:
- 常规
- 斜体
- 粗体
- 粗斜体
- 灯
- 浅色斜体
- 紧凑常规
- 紧凑斜体
- 紧凑粗体
- 粗斜体精简
您可以将新的 fontFamily
属性与 textStyle
属性结合使用,以应用上述任一插值器。
fontFamily
的支持值如下:
"sans-serif"
(适用于常规 Roboto)- 适用于 Roboto Light 的
"sans-serif-light"
"sans-serif-condensed"
(适用于 Roboto Condensed)
然后,您可以使用 textStyle
值 "bold"
和 "italic"
应用粗体和/或斜体。您可以按照以下方式应用这两项:android:textStyle="bold|italic"
。
您也可以使用 Typeface.create()
。
例如 Typeface.create("sans-serif-light", Typeface.NORMAL)
。
输入框架
多个输入设备
借助新的 InputManager
类,您可以查询当前连接的一组输入设备,并注册以便在添加、更改或移除新设备时收到通知。如果您正在构建一款支持多名玩家的游戏,并且希望检测连接的控制器数量以及控制器数量发生变化的时间,此方法将特别有用。
您可以通过调用 getInputDeviceIds()
查询已连接的所有输入设备。此方法会返回一个整数数组,其中每个整数表示不同输入设备的 ID。然后,您可以调用 getInputDevice()
来获取指定输入设备 ID 的 InputDevice
。
如果您希望在新的输入设备连接、更改或断开连接时收到通知,请实现 InputManager.InputDeviceListener
接口并向 registerInputDeviceListener()
注册该接口。
输入控制器的振动
如果已连接的输入设备具有自己的振动功能,您现在只需对 InputDevice
调用 getVibrator()
,即可使用现有的 Vibrator
API 控制这些设备的振动。
权限
以下是新权限:
READ_EXTERNAL_STORAGE
- 提供对外部存储空间的受保护读取权限。在 Android 4.1 中,所有应用在默认情况下仍然拥有读取权限。这将在未来的版本中更改,要求应用使用此权限明确请求读取权限。如果您的应用已请求写入权限,它也会自动获得读取权限。有一个新的开发者选项可开启读取访问限制,以便开发者针对 Android 未来的行为方式测试其应用。
- android.Manifest.permission.READ_USER_DICTIONARY
- 允许应用读取用户字典。只有输入法(IME)或字典编辑器(例如“设置”应用)才需要此权限。
READ_CALL_LOG
- 允许应用读取系统的通话记录,其中包含有关来电和去电的信息。
WRITE_CALL_LOG
- 允许应用修改存储在手机上的系统通话记录
- android.Manifest.permission.WRITE_USER_DICTIONARY
- 允许应用写入用户的字典。
设备功能
Android 4.1 针对专门在电视屏幕上显示界面的设备添加了新的功能声明:FEATURE_TELEVISION
。如需声明您的应用需要电视界面,请在清单文件中使用 <uses-feature>
元素声明此功能:
<manifest ... > <uses-feature android:name="android.hardware.type.television" android:required="true" /> ... </manifest>
此功能将“电视”定义为一种典型的起居室电视体验:显示在大屏幕上,用户坐在远处,主流输入形式是类似方向键的设备,并且一般不通过触摸或鼠标/指针设备。