多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
API等级:18 Android 4.3(JELLY_BEAN_MR2)是Jelly Bean版本的更新,为用户和应用程序开发人员提供了新功能。本文档介绍了最值得注意的新API。 作为应用程序开发人员,您应该尽快从SDK Manager中下载Android 4.3系统映像和SDK平台。如果您没有运行Android 4.3的设备来测试您的应用,请使用Android 4.3系统映像在Android模拟器上测试您的应用。然后根据Android 4.3平台构建您的应用程序,以开始使用最新的API。 #### **更新您的目标API级别** 为了更好地为运行Android 4.3的设备优化您的应用程序,您应该设置targetSdkVersion为 "18",在Android 4.3系统映像上安装它,对其进行测试,然后使用此更改发布更新。 您可以使用Android 4.3中的API,同时还可以通过在代码中添加条件来检查系统API级别,然后执行不受您的支持的API minSdkVersion。要了解更多关于保持向后兼容性,阅读支持不同平台版本。 Android 支持库中还提供了各种API ,使您可以在旧版本的平台上实现新功能。 有关API级别如何工作的更多信息,请阅读什么是API级别? #### **重要的行为变化** 如果您以前发布过Android版应用,请注意您的应用可能会受到Android 4.3更改的影响。 #### **如果你的应用程序使用隐含的意图...** 您的应用在受限个人资料环境中可能会行为不当。 受限制的配置文件环境中的用户可能没有可用的所有标准Android应用程序。例如,受限制的配置文件可能会禁用Web浏览器和相机应用程序。因此,您的应用程序不应该假设哪些应用程序可用,因为如果您在startActivity()未验证应用程序是否可用来处理的情况下调用Intent,则您的应用程序可能会在受限制的配置文件中崩溃。 当使用隐式意图时,您应该始终通过调用resolveActivity()或来验证应用程序是否可用来处理意图queryIntentActivities()。例如: ~~~ Intent intent = new Intent(Intent.ACTION_SEND); ... if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } else { Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show(); } ~~~ #### **如果你的应用程序依赖于帐户...** 您的应用在受限个人资料环境中可能会行为不当。 受限制的配置文件环境中的用户默认无权访问用户帐户。如果您的应用程序依赖于某个应用程序Account,那么您的应用程序在受限制的配置文件中使用时可能会意外崩溃 如果您希望防止受限制的配置文件完全使用您的应用,因为您的应用依赖于敏感的帐户信息,请android:requiredAccountType在清单`<application>` 元素中指定该属性。 如果您希望允许受限个人资料继续使用您的应用,即使他们无法创建自己的帐户,也可以禁用需要帐户的应用功能或允许受限个人资料访问由主要用户创建的帐户。有关更多信息,请参阅以下有关在受限个人资料中支持帐户的部分。 #### **如果您的应用程序使用VideoView ...** 在Android 4.3上,您的视频可能会显得较小。 在以前的Android版本中,VideoView小部件错误地计算了"wrap_content"值layout_height并layout_width与之相同"match_parent"。因此,在使用"wrap_content"高度或宽度时,可能以前提供了您所需的视频布局,这样做可能会导致Android 4.3及更高版本上的视频小得多。要解决此问题,替换 "wrap_content"与"match_parent"和验证在Android 4.3以及对旧版本如预期的视频出现。 ### **受限制的配置文件** 在Android平板电脑上,用户现在可以基于主要用户创建受限的配置文件。当用户创建一个受限制的配置文件时,他们可以启用限制,比如哪个应用程序可用于配置文件。Android 4.3中的一组新的API还允许您为开发的应用程序构建精细限制设置。例如,通过使用新的API,您可以允许用户在受限制的配置文件环境中运行时控制应用程序中可用的内容类型。 系统的“设置”应用程序管理用户控制您构建的限制的用户界面。为了让您的应用程序的限制设置显示给用户,您必须通过创建一个BroadcastReceiver接收该ACTION_GET_RESTRICTION_ENTRIES意图来声明您的应用程序提供的限制。系统调用这个意图来查询所有应用程序的可用限制,然后构建UI以允许主要用户管理每个受限配置文件的限制。 在onReceive()你的方法中BroadcastReceiver,你必须RestrictionEntry为你的应用程序提供的每个限制创建一个。每个RestrictionEntry定义一个限制标题,说明和下列数据类型之一: * TYPE_BOOLEAN 要么是真的要么是假的。 * TYPE_CHOICE 对于具有多个互斥选项的限制(单选按钮选项)。 * TYPE_MULTI_SELECT对于具有多个不相互排斥的选择的限制(复选框选项)。 然后你把所有的RestrictionEntry对象放到一个ArrayList广播接收器的结果中作为EXTRA_RESTRICTIONS_LIST额外的值 。 系统会在“设置”应用程序中为您的应用程序的限制创建UI,并使用您为每个RestrictionEntry 对象提供的唯一键保存每个限制。当用户打开您的应用程序时,您可以通过调用查询任何当前的限制getApplicationRestrictions()。这将返回一个Bundle包含您用RestrictionEntry对象定义的每个限制的键值对。 如果要提供更多特定的限制,这些限制不能通过布尔值,单选项和多选项值来处理,则可以创建一个活动,用户可以指定限制并允许用户从限制设置中打开该活动。在您的广播接收机中,EXTRA_RESTRICTIONS_INTENT在结果中包含额外的内容Bundle。这额外的必须指定一个Intent 指示Activity要启动的类(使用该 putParcelable()方法来传递EXTRA_RESTRICTIONS_INTENT意图)。当主用户输入您的活动来设置自定义限制时,您的活动必须使用EXTRA_RESTRICTIONS_LIST或EXTRA_RESTRICTIONS_BUNDLE键返回包含限制值的结果,这取决于您是分别指定 RestrictionEntry对象还是键值对。 #### **支持受限制的帐户** 添加到主用户的任何帐户都可用于受限配置文件,但AccountManager默认情况下,这些帐户无法从API 访问。如果您尝试AccountManager在受限个人资料中添加帐户,则会收到失败结果。由于这些限制,您有以下三种选择: 允许从受限个人资料访问所有者的帐户。 要从受限制的配置文件访问帐户,您必须将该android:restrictedAccountType属性添加到`<application>`标记中: ~~~ <application ... android:restrictedAccountType = “com.example.account.type” > ~~~ > 警告:启用此属性可让您的应用程序从受限制的配置文件访问主用户的帐户。所以,只有当您的应用显示的信息不会泄露被认为是敏感的个人身份信息(PII)时,您才应该允许这样做。系统设置将通知主要用户,您的应用程序会将受限制的配置文件授予其帐户,因此用户应该清楚,帐户访问权限对于您的应用程序的功能很重要。如果可能的话,您还应该为主要用户提供足够的限制控制,以确定您的应用允许多少帐户访问。 * 无法修改帐户时禁用某些功能。 如果您想使用帐户,但实际上并不需要这些帐户用于您的应用程序的主要功能,则可以检查帐户可用性,并在不可用时禁用功能。您应该首先检查是否有现有的帐户可用。如果不是,那么通过调用查询是否可以创建一个新的账户,getUserRestrictions()并检查DISALLOW_MODIFY_ACCOUNTS结果中的多余部分。如果是true,那么你应该禁用你的应用程序需要访问帐户的任何功能。例如: ~~~ UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); Bundle restrictions = um.getUserRestrictions(); if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { // cannot add accounts, disable some functionality } ~~~ > 注:在这种情况下,你应该不是在你的清单文件中声明的任何新的属性。 * 无法访问私人帐户时禁用您的应用。 如果您的应用程序不适用于受限个人资料,这一点非常重要,因为您的应用程序依赖于帐户中的敏感个人信息(还因为受限个人资料目前无法添加新帐户),请将该android:requiredAccountType属性添加到`<application>`标记中: ~~~ <application ... android:requiredAccountType = “com.example.account.type” > ~~~ 例如,Gmail应用程序使用此属性为受限个人资料禁用自身,因为所有者的个人电子邮件不应用于受限个人资料。 ### **无线和连接** #### **低功耗蓝牙(智能就绪)** Android现在支持蓝牙低功耗(LE)和新的API android.bluetooth。借助新的API,您可以构建可与蓝牙低功耗外设(如心率监视器和计步器)进行通信的Android应用程序。 由于蓝牙LE是一种在所有Android设备上都不可用的硬件功能,因此您必须在清单文件中声明以下<uses-feature> 元素"android.hardware.bluetooth_le": ~~~ <uses-feature android:name = “android.hardware.bluetooth_le” android:required = “true” /> ~~~ 如果您已经熟悉Android的Classic Bluetooth API,请注意使用Bluetooth LE API有一些差异。最重要的是,现在有一个BluetoothManager类应该用于某些高级操作,例如获取BluetoothAdapter,获取连接设备列表以及检查设备状态。例如,以下是您现在应该如何获取 BluetoothAdapter: ~~~ final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); ~~~ 要发现蓝牙LE外设,叫startLeScan()上BluetoothAdapter,它传递的实现BluetoothAdapter.LeScanCallback接口。当蓝牙适配器检测到蓝牙LE外设时,您的BluetoothAdapter.LeScanCallback实施会接收到对该onLeScan()方法的调用 。此方法为您提供一个BluetoothDevice表示检测到的设备的对象,设备的RSSI值以及包含设备广告记录的字节数组。 如果您只想扫描特定类型的外设,则可以调用startLeScan()并包含UUID指定您应用支持的GATT服务的对象数组。 > 注意:您只能扫描Bluetooth LE设备或 使用以前的API扫描Classic Bluetooth设备。您无法同时扫描LE和Classic Bluetooth设备。 然后连接到蓝牙LE外围设备,调用connectGatt()相应的 BluetoothDevice对象,传递给它的一个实现 BluetoothGattCallback。您的实现BluetoothGattCallback接收有关与设备的连接状态和其他事件的回调。在onConnectionStateChange() 回调期间,如果该方法STATE_CONNECTED作为新状态通过,则可以开始与设备进行通信。 在设备上访问蓝牙功能还要求您的应用程序请求某些蓝牙用户权限。有关更多信息,请参阅Bluetooth Low Energy API指南。 #### **Wi-Fi只扫描模式** 在尝试识别用户的位置时,Android可能会使用Wi-Fi通过扫描附近的接入点来确定位置。但是,用户经常关闭Wi-Fi以节省电池,导致位置数据不准确。Android现在包括一个仅扫描模式,允许设备Wi-Fi扫描接入点以帮助获取位置,而无需连接到接入点,从而大大降低电池使用量。 如果您想要获取用户的位置,但是Wi-Fi当前处于关闭状态,则可以通过startActivity()以该操作调用来请求用户启用Wi-Fi只扫描模式ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE。 #### **Wi-Fi配置** 新的WifiEnterpriseConfigAPI允许面向企业的服务自动化托管设备的Wi-Fi配置。 #### **快速响应来电** 自从Android 4.0以来,一种名为“快速响应”的功能允许用户使用即时文本消息响应来电,而无需接听电话或解锁设备。到目前为止,这些快速消息总是由默认的消息应用程序处理。现在,任何应用程序都可以通过为其创建一个Service 意图过滤器来声明其处理这些消息的能力ACTION_RESPOND_VIA_MESSAGE。 当用户以一个快速响应来响应来电时,电话应用程序ACTION_RESPOND_VIA_MESSAGE用一个描述接收者(主叫者)的URI和EXTRA_TEXT用户想要发送的消息的额外URI来发送意图。当您的服务收到意图时,它应该传递消息并立即停止(您的应用程序不应该显示一个活动)。 为了获得这个意图,你必须声明SEND_RESPOND_VIA_MESSAGE权限。 ### **多媒体** #### **MediaExtractor和MediaCodec增强功能** Android现在使你更容易通过HTTP编写自己的动态自适应流按照ISO / IEC 23009-1标准(DASH)的玩家,在使用现有的API MediaCodec和MediaExtractor。这些API的基础架构已更新,以支持分段MP4文件的解析,但您的应用程序仍然负责解析MPD元数据并将各个流传递给MediaExtractor。 如果要使用加密内容的DASH,请注意该getSampleCryptoInfo()方法会返回MediaCodec.CryptoInfo描述每个加密媒体样本结构的元数据。此外,该getPsshInfo()方法已添加到 MediaExtractor您可以访问您的DASH媒体的PSSH元数据。此方法将UUID对象映射为字节,并 UUID指定加密方案,字节是该方案的特定数据。 #### **媒体DRM** 新的MediaDrm课程通过将DRM问题与媒体播放分离开来,为您的媒体内容提供数字版权管理(DRM)的模块化解决方案。例如,这个API分离允许您播放Widevine加密的内容,而无需使用Widevine媒体格式。此DRM解决方案还支持DASH通用加密,因此您可以在流媒体内容中使用各种DRM方案。 您可以使用它MediaDrm来获取不透明的密钥请求消息,并处理来自服务器的密钥响应消息以获取许可证和供应。您的应用程序负责处理与服务器的网络通信; 的MediaDrm类只提供了产生和处理信息的能力。 这些MediaDrmAPI旨在与MediaCodecAndroid 4.1(API级别16)中引入的API 一起使用 ,包括MediaCodec编码和解码内容,MediaCrypto处理加密内容以及MediaExtractor 提取和解复用内容。 你必须首先构造MediaExtractor和 MediaCodec对象。然后,您可以UUID通过内容中的元数据访问DRM方案标识 ,并使用它的构造函数构造MediaDrm对象实例。 #### **来自Surface的视频编码** Android 4.1(API级别16)添加了MediaCodec用于媒体内容的低级编码和解码的类。在对视频进行编码时,Android 4.1要求您为媒体提供一个ByteBuffer阵列,但现在Android 4.3允许您使用a Surface作为编码器的输入。例如,这可以让您对现有视频文件的输入进行编码,或使用OpenGL ES生成的帧进行编码。 要使用Surface作为输入到编码器,第一个电话configure()你MediaCodec。然后打电话createInputSurface()来接收Surface您可以流媒体的信息。 例如,您可以将给定的值Surface作为OpenGL上下文的窗口eglCreateWindowSurface()。然后,在渲染曲面的同时,调用eglSwapBuffers()以将帧传递给MediaCodec。 为了开始编码,拨打start()上MediaCodec。完成后,调用signalEndOfInputStream() 终止编码,并调用release()上 Surface。 #### **Media muxing** 新MediaMuxer类可以在一个音频流和一个视频流之间进行复用。这些API作为MediaExtractor Android 4.2中添加的用于解复用(解复用)媒体的类的对应物。 支持的输出格式在中定义MediaMuxer.OutputFormat。目前,MP4是唯一支持的输出格式,并且MediaMuxer一次仅支持一个音频流和/或一个视频流。 MediaMuxer大多是设计来处理,MediaCodec 所以你可以通过执行视频处理,MediaCodec然后将输出保存到MP4文件MediaMuxer。您也可以MediaMuxer结合使用MediaExtractor来执行媒体编辑,而无需编码或解码。 #### **为RemoteControlClient播放进度和清理** 在Android 4.0(API等级14)中,RemoteControlClient添加了该功能以启用远程控制客户端的媒体播放控制,例如锁定屏幕上提供的控件。Android 4.3现在提供了这样的控制器显示回放位置和控制清除回放的能力。如果您已经使用RemoteControlClientAPI 为媒体应用程序启用了远程控制,则可以通过实施两个新界面来允许播放清理。 首先,你必须FLAG_KEY_MEDIA_POSITION_UPDATE通过传递来启用标志 setTransportControlsFlags()。 然后实现以下两个新的接口: * RemoteControlClient.OnGetPlaybackPositionListener 这包括回调onGetPlaybackPosition(),当遥控器需要更新其UI中的进度时,请求媒体的当前位置。 * RemoteControlClient.OnPlaybackPositionUpdateListener 这包括回调onPlaybackPositionUpdate(),当用户使用遥控器UI擦洗回放时,该回调会告诉您的应用程序新媒体的时间码。 一旦您用新的位置更新您的播放,请致电setPlaybackState()以指示新的播放状态,位置和速度。 通过定义这些接口,您可以分别RemoteControlClient通过调用setOnGetPlaybackPositionListener()和 设置它们setPlaybackPositionUpdateListener()。 ### **图像** #### **支持OpenGL ES 3.0** Android 4.3增加了Java接口和本地支持OpenGL ES 3.0。OpenGL ES 3.0提供的关键新功能包括: * 先进的视觉效果加速 * 高质量的ETC2 / EAC纹理压缩作为标准功能 * 具有整数和32位浮点支持的GLSL ES着色语言的新版本 * 高级纹理渲染 * 更广泛的标准化纹理大小和渲染缓冲区格式 Android提供了OpenGL ES 3.0的Java接口GLES30。在使用OpenGL ES 3.0时,请确保使用<uses-feature> 标记和android:glEsVersion属性在清单文件中声明它 。例如: ~~~ <manifest> <uses-feature android:glEsVersion="0x00030000" /> ... </manifest> ~~~ 并且记得通过调用指定OpenGL ES上下文setEGLContextClientVersion(),3作为版本传递。 有关使用OpenGL ES的更多信息,包括如何在运行时检查设备支持的OpenGL ES版本,请参阅OpenGL ES API指南。 #### **可绘制的Mipmapping** 使用mipmap作为位图或绘图的源代码是提供高质量图像和各种图像比例的简单方法,如果您期望在动画过程中缩放图像,这可能特别有用。 Android 4.2(API级别17)在Bitmap 类中添加Bitmap了对mipmap的支持- 当您提供mipmap源并已启用时,Android会交换mip图像setHasMipMap()。现在,在Android 4.3中,您也可以BitmapDrawable通过提供mipmap资源并将该android:mipMap属性设置为位图资源文件或调用,为对象启用mipmap hasMipMap()。 ### **用户界面** #### **查看重叠** 新ViewOverlay类提供了一个透明图层View,您可以在其上添加可视内容,而不会影响布局层次结构。你可以打电话ViewOverlay给任何View人getOverlay()。覆盖总是和主机视图(创建它的视图)具有相同的大小和位置,允许您添加出现在主机视图前面但不能扩展该主机视图边界的内容。 ViewOverlay当您想要创建动画时,使用a 特别有用,例如在容器外部滑动视图或在屏幕上移动项目而不影响视图层次结构。但是,因为叠加层的可用区域被限制在与其主机视图相同的区域,所以如果要为布局中移动到其位置外的视图设置动画效果,则必须使用具有所需布局边界的父视图中的叠加层。 为小部件视图(如a)创建叠加层时Button,可以Drawable通过调用将对象添加到叠加层 add(Drawable)。如果你要求getOverlay()一个布局视图,比如RelativeLayout返回的对象是一个ViewGroupOverlay。该 ViewGroupOverlay班是的子类ViewOverlay也允许您添加View 调用对象add(View)。 > 注意:添加到叠加层的所有可绘制和视图只是可视化的。他们无法获得焦点或输入事件。 例如,以下代码通过将视图放置在父视图的叠加层中,然后在该视图上执行翻译动画,来动画一个视图向右滑动: ~~~ View view = findViewById(R.id.view_to_remove); ViewGroup container = (ViewGroup) view.getParent(); container.getOverlay().add(view); ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight()); anim.start(); ~~~ #### **光学边界布局** 对于包含9个补丁背景图像的视图,您现在可以指定它们应该基于背景图像的“光学”边界而不是视图的“剪辑”边界与相邻视图对齐。 例如,图1和图2各自显示相同的布局,但是图1中的版本使用剪辑边界(默认行为),而图2使用光学边界。由于用于按钮和相框的九个补丁图像包括边缘周围的填充,所以在使用剪辑边界时,它们看起来不会彼此对齐或显示为文本。 > 注意:图1和图2中的屏幕截图具有“显示布局边界”开发者设置。对于每个视图,红线表示光学边界,蓝色线表示剪辑边界,粉红色表示边界。 将鼠标悬停以隐藏布局边界。 ![](https://box.kancloud.cn/c0d5e2d37244ba35b248afbe365c750e_301x294.png) 图1.使用剪辑边界的布局(默认) ![](https://box.kancloud.cn/48b804e5e598201454bbc3084dc85b0c_302x301.png) 图2.使用光学边界的布局 要根据光学边界对齐视图,请将该android:layoutMode属性设置"opticalBounds"为父布局之一。例如: ~~~ <LinearLayout android:layoutMode="opticalBounds" ... > ~~~ ![](https://box.kancloud.cn/63ea795f55299e7c290edc3ffcff2f0c_243x297.png) 图3.带有光学边界的Holo按钮9path的放大视图。 为此,应用于视图背景的九个补丁图像必须使用沿九个补丁文件的底部和右侧的红线指定光学边界(如图3所示)。红线表示应该从剪辑边界中减去的区域,留下图像的光学边界。 当ViewGroup在布局中启用光学边界时,所有后代视图将继承光学边界布局模式,除非通过设置android:layoutMode为覆盖组"clipBounds"。所有的布局元素也都尊重其子视图的光学边界,根据视图的光学边界来调整它们自己的边界。但是,布局元素(的子类ViewGroup)目前不支持应用于自己背景的九块图像的光学边界。 如果通过子类创建自定义视图View,ViewGroup或任何亚类的化合物,您的视图将继承这些光学约束行为。 > 注:由全息主题支持的所有部件已与光学界,包括更新Button, Spinner, EditText,等。所以,你可以立即被设定受益 android:layoutMode属性"opticalBounds",如果您的应用程序适用于一个霍洛主题(Theme.Holo,Theme.Holo.Light,等)。 要使用Draw 9-patch工具为自己的九分图像指定光学边界,请在单击边框像素时按住Ctrl键。 #### **Rect值的动画** 您现在可以Rect使用新的动画在两个值之间进行动画RectEvaluator。这个新类是TypeEvaluator你可以传递给它的一个实现ValueAnimator.setEvaluator()。 #### **窗口附加和焦点侦听器** 以前,如果您想要听取何时将视图附加到/分离到窗口或其焦点发生了变化,您需要重写View要实现的类onAttachedToWindow()和onDetachedFromWindow()/或 onWindowFocusChanged()。 现在,要接收附加和分离事件,您可以实现ViewTreeObserver.OnWindowAttachListener并将其设置在视图上 addOnWindowAttachListener()。为了接收焦点事件,你可以ViewTreeObserver.OnWindowFocusChangeListener用一个视图来实现和设置它 addOnWindowFocusChangeListener()。 #### **电视过扫描支持** 为了确保您的应用程序在每台电视机上都能显示整个屏幕,现在可以为您的应用程序布局启用过扫描。过扫描模式由FLAG_LAYOUT_IN_OVERSCAN标志确定,您可以使用平台主题启用标志,例如 Theme_DeviceDefault_NoActionBar_Overscan启用windowOverscan自定义主题中的 样式。 #### **屏幕方向** 该`<activity>` 标签的screenOrientation 属性现在支持附加值来遵守用户对自动旋转的偏好: * "userLandscape" 行为相同"sensorLandscape",除非用户禁用自动旋转,那么它锁定在正常的横向,不会翻转。 * "userPortrait" 行为相同"sensorPortrait",除非用户禁用自动旋转,然后锁定在正常的纵向方向,不会翻转。 * "fullUser" "fullSensor"与所有四个方向的行为相同,并允许旋转,除非用户禁用自动旋转,然后锁定用户的首选方向。 此外,您现在还可以声明"locked"将应用的方向锁定到屏幕的当前方向。 #### **旋转动画** 新的rotationAnimation字段 WindowManager允许您在系统切换屏幕方向时选择要使用的三种动画之一。这三个动画是: * ROTATION_ANIMATION_CROSSFADE * ROTATION_ANIMATION_JUMPCUT * ROTATION_ANIMATION_ROTATE > 注意:只有在您将活动设置为使用“全屏”模式时,才可以使用这些动画Theme.Holo.NoActionBar.Fullscreen。 例如,以下是如何启用“淡入淡出”动画: ~~~ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WindowManager.LayoutParams params = getWindow().getAttributes(); params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; getWindow().setAttributes(params); ... } ~~~ ### **用户输入** #### **新的传感器类型** 新的TYPE_GAME_ROTATION_VECTOR传感器可以让您检测设备的旋转,而不用担心磁干扰。与TYPE_ROTATION_VECTOR传感器不同,TYPE_GAME_ROTATION_VECTOR它不是基于磁性北极。 新的TYPE_GYROSCOPE_UNCALIBRATED和TYPE_MAGNETIC_FIELD_UNCALIBRATED传感器提供原始的传感器数据,而不考虑偏差估计。也就是说,现有的TYPE_GYROSCOPE和TYPE_MAGNETIC_FIELD 传感器提供的传感器数据分别考虑了陀螺漂移和设备中硬铁的估计偏差。而这些传感器的新“未校准”版本则提供原始传感器数据,并分别提供估计偏差值。这些传感器允许您通过增加外部数据的估计偏差来为传感器数据提供您自己的定制校准。 #### **通知监听器** Android 4.3添加了一个新的服务类,NotificationListenerService允许您的应用程序接收系统发布的新通知的相关信息。 如果您的应用当前使用辅助功能服务API访问系统通知,则应该更新您的应用以使用这些API。 #### **联系人提供商** #### **查询“可联系人”** 新的“联系人提供者”查询Contactables.CONTENT_URI提供了一种有效的方法,可以获取Cursor包含与指定查询匹配的所有联系人的所有电子邮件地址和电话号码的联系人。 #### **查询联系人增量** 新的API已添加到联系人提供程序,使您可以有效地查询联系人数据的最近更改。以前,当联系人数据中的某些内容发生变化时,可能会通知您的应用程序,但是您不知道发生了什么变化,并且需要检索所有联系人,然后遍历它们以发现变化。 要跟踪对插入和更新的更改,现在可以在CONTACT_LAST_UPDATED_TIMESTAMP选择时包含参数,以仅查询自上次查询提供者以来发生更改的联系人。 要跟踪哪些联系人已被删除,新表ContactsContract.DeletedContacts提供已删除联系人的日志(但删除的每个联系人在此表中保留有限的时间)。与之类似CONTACT_LAST_UPDATED_TIMESTAMP,您可以使用新的选择参数CONTACT_DELETED_TIMESTAMP来检查自上次查询提供者以来哪些联系人已被删除。该表还包含包含DAYS_KEPT_MILLISECONDS日志将保留的天数(以毫秒为单位)的常量。 另外,CONTACTS_DATABASE_CREATED当用户通过系统设置菜单清除联系人存储时,联系人提供者现在广播该动作,有效地重新创建联系人提供者数据库。它旨在表示他们需要放弃所有存储的联系信息,并重新加载新的查询。 有关使用这些API检查联系人更改的示例代码,请查看SDK示例下载中提供的ApiDemos示例。 ### **本土化** #### **改进了对双向文本的支持** 以前版本的Android支持从右向左(RTL)语言和布局,但有时不能正确处理混合方向的文本。因此,Android 4.3增加了BidiFormatterAPI,可以帮助您正确地设置具有相反方向内容的文本,而不会混淆其中的任何部分。 例如,当你想创建一个带有字符串变量的句子,比如“你的意思是15 Bay Street,Laurel,CA?”时,你通常会传递一个本地化的字符串资源和变量 String.format(): ~~~ Resources res = getResources(); String suggestion = String.format(res.getString(R.string.did_you_mean), address); ~~~ 但是,如果语言环境是希伯来语,那么格式化的字符串就像这样出来: 你的意思是15湾街,劳雷尔,加州? 这是错误的,因为“湾街”应该留下“15”。解决方案是使用BidiFormatter和它的unicodeWrap()方法。例如,上面的代码变成: ~~~ Resources res = getResources(); BidiFormatter bidiFormatter = BidiFormatter.getInstance(); String suggestion = String.format(res.getString(R.string.did_you_mean), bidiFormatter.unicodeWrap(address)); ~~~ 默认情况下,unicodeWrap()使用第一个强方向性估计启发式,如果文本方向的第一个信号不能代表整个内容的合适方向,则可能会出错。如果有必要,你可以通过传递一个指定不同的启发式TextDirectionHeuristic常数从TextDirectionHeuristics 到unicodeWrap()。 > 注意:这些新的API也可通过Android 支持库以及BidiFormatter类和相关的API 用于以前版本的Android 。 ### **无障碍服务** #### **处理关键事件** 一个AccessibilityService现在可以接收按键输入事件的回调onKeyEvent()回调方法。这使得您的辅助功能服务可以处理键盘输入设备(如键盘)的输入,并将这些事件转换为以前可能只能通过触摸输入或设备的方向键才能进行的特殊操作。 #### **选择文本并复制/粘贴** 在AccessibilityNodeInfo现在提供的API,允许AccessibilityService在一个节点来选择,剪切,复制和粘贴文本。 要指定文本剪切或复制的选择,您可访问服务可以使用新的动作,ACTION_SET_SELECTION与它通过选择开始和结束位置ACTION_ARGUMENT_SELECTION_START_INT和ACTION_ARGUMENT_SELECTION_END_INT。或者,您可以通过使用现有操作来操作光标位置来选择文本ACTION_NEXT_AT_MOVEMENT_GRANULARITY (之前仅用于移动光标位置),并添加参数ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN。 然后,您可以剪切或复制用ACTION_CUT, ACTION_COPY,再后来用粘贴 ACTION_PASTE。 > 注意:这些新的API也可以通过Android 支持库与以前版本的Android 一起使用AccessibilityNodeInfoCompat 。 #### **声明可访问性功能** 从Android 4.3开始,可访问性服务必须在其元数据文件中声明可访问性功能,以便使用某些辅助功能。如果在元数据文件中没有请求功能,则该功能将是无操作的。要声明服务的可访问性功能,必须使用与AccessibilityServiceInfo 该类中的各种“能力”常量相对应的XML属性。 例如,如果一个服务没有请求这个flagRequestFilterKeyEvents能力,那么它将不会收到关键事件。 ### **测试和调试** #### **自动UI测试** 新的UiAutomation类提供了API,允许您模拟用户的测试自动化操作。通过使用平台的AccessibilityServiceAPI,UiAutomation API允许您检查屏幕内容并注入任意的键盘和触摸事件。 获取一个实例UiAutomation,调用Instrumentation.getUiAutomation()。为了使这个工作,你必须提供-w选项与instrument运行你的InstrumentationTestCase从命令adb shell。 使用该UiAutomation实例,可以执行任意事件来通过调用来测试您的应用程序executeAndWaitForEvent(),将其传递Runnable给执行,操作的超时时间以及UiAutomation.AccessibilityEventFilter接口的实现。在您的UiAutomation.AccessibilityEventFilter实现中,您会收到一个调用,允许您筛选感兴趣的事件,并确定给定测试用例的成功或失败。 要观察测试过程中的所有事件,请创建一个实现UiAutomation.OnAccessibilityEventListener并将其传递给setOnAccessibilityEventListener()。您的监听器接口随后会在onAccessibilityEvent() 每次发生事件时接收一个调用,接收AccessibilityEvent描述该事件的对象。 UiAutomationAPI在很低的级别上提供了各种各样的其他操作来鼓励UI测试工具(例如uiautomator)的开发。比如, UiAutomation也可以: * 注入输入事件 * 改变屏幕的方向 * 截图 而对于UI测试工具来说,最重要的是,这些UiAutomationAPI跨越应用程序界限工作,不像那些API Instrumentation。 #### **Systrace事件的应用程序** Android 4.3为这个Trace类添加了两个静态方法, beginSection()并endSection()允许你定义包含systrace报告的代码块。通过在您的应用程序中创建可追踪代码的部分,systrace日志将为您提供更详细的分析,了解您的应用程序在哪里出现放缓。 有关使用Systrace工具的信息,请阅读使用Systrace 分析显示和性能。 #### **安全** #### **应用程序专用密钥的Android密钥存储区** Android现在在KeyStore 工具中提供了一个名为Android Key Store 的自定义Java安全提供程序,它允许您生成并保存可能仅被您的应用程序查看和使用的私钥。加载Android密钥库,传递 "AndroidKeyStore"给KeyStore.getInstance()。 要在Android Key Store中管理您的应用程序的私人凭据,请使用KeyPairGeneratorwith 生成一个新的密钥 KeyPairGeneratorSpec。首先KeyPairGenerator通过调用来获得一个实例getInstance()。然后调用 initialize(),传递一个KeyPairGeneratorSpec你可以使用 的实例 KeyPairGeneratorSpec.Builder。最后,KeyPair通过打电话给你generateKeyPair()。 #### **硬件凭证存储** Android现在还支持硬件支持存储KeyChain 凭据,通过使密钥不可用于提取更安全。也就是说,一旦密钥位于硬件支持的密钥存储区(安全元件,TPM或TrustZone)中,它们就可以用于加密操作,但不能导出私有密钥材料。即使OS内核也无法访问这个密钥材料。虽然并非所有基于Android的设备都支持硬件上的存储,但您可以在运行时检查硬件支持的存储是否可以通过调用进行访问 KeyChain.IsBoundKeyAlgorithm()。 #### **清单声明** #### **可申报的必需功能** <uses-feature> 元素现在支持以下值,因此您可以确保您的应用仅安装在提供您应用所需功能的设备上。 * FEATURE_APP_WIDGETS 声明您的应用程序提供了应用程序小部件,并且应该只安装在包含主屏幕或用户可以嵌入应用程序小部件的类似位置的设备上。例: ~~~ <uses-feature android:name = “android.software.app_widgets” android:required = “true” /> ~~~ * FEATURE_HOME_SCREEN 声明您的应用程序表现为主屏幕替换,并且应该只安装在支持第三方主屏幕应用程序的设备上。例: ~~~ <uses-feature android:name="android.software.home_screen" android:required="true" /> ~~~ * FEATURE_INPUT_METHODS 声明您的应用程序提供自定义输入法(使用键盘构建InputMethodService),并且应该只安装在支持第三方输入法的设备上。例: ~~~ <uses-feature android:name="android.software.input_methods" android:required="true" /> ~~~ * FEATURE_BLUETOOTH_LE 声明您的应用程序使用蓝牙低功耗API,并且应该只安装在能够通过蓝牙低功耗与其他设备进行通信的设备上。例: ~~~ <uses-feature android:name="android.software.bluetooth_le" android:required="true" /> ~~~ ### **用户权限** 现在支持以下值<uses-permission> 来声明您的应用程序访问某些API所需的权限。 * BIND_NOTIFICATION_LISTENER_SERVICE 需要使用新的NotificationListenerServiceAPI。 * SEND_RESPOND_VIA_MESSAGE 需要接收ACTION_RESPOND_VIA_MESSAGE 意图。 有关Android 4.3中所有API更改的详细视图,请参阅 API差异报告。