Android 4.2 API

API 级别:17

Android 4.2(JELLY_BEAN_MR1) 是对 Jelly Bean 版本的更新,为用户和应用提供了新功能 开发者。本文档介绍了 Google Cloud 中 实用的新 API

作为应用开发者,您应从以下网址下载 Android 4.2 系统映像和 SDK 平台: SDK 管理器。如果您 如果您没有运行 Android 4.2 的设备来测试您的应用,请使用 Android 4.2 系统 映像,以在 Android 模拟器上测试您的应用。 然后,针对 Android 4.2 平台构建应用,以开始使用最新的 API。

为了更好地针对运行 Android 4.2 的设备优化您的应用, 您应将 targetSdkVersion 设置为 "17",将其安装在 Android 4.2 系统映像上; 然后发布包含此更改的更新

您 可以使用 Android 4.2 中的 API,同时通过添加 条件,在执行之前检查系统 API 级别 您的minSdkVersion不支持的 API。 要详细了解 保持向后兼容性,请阅读创建向后兼容的 界面

如需详细了解 API 级别的工作原理,请参阅什么是 API 水平?

重要的行为变更

如果您之前发布过 Android 应用,请注意以下事项 可能影响应用行为的更改:

  • 默认情况下,系统不再导出 content provider。也就是说, android:exported 属性的现已设为 “false"。如果其他应用必须 能够访问您的内容提供程序,现在必须明确设置 android:exported="true"

    仅当您将 android:targetSdkVersionandroid:minSdkVersion 设置为 17 或更高版本时,此更改才会生效。否则,默认值仍为 “true" 甚至在 Android 4.2 及更高版本上运行时也能如此。

  • 与以前的 Android 版本相比,用户位置信息结果可能不太准确 如果您的应用请求 ACCESS_COARSE_LOCATION 权限,但 不请求 ACCESS_FINE_LOCATION 权限。

    当您的应用请求获得以下权限时,满足用户在隐私权方面的期望: 粗略位置(而非精确位置)时,系统不会提供用户位置估算值 比城市街区更准确。

  • Settings.System 定义的某些设备设置现在为 只读属性。如果您的应用尝试将 Settings.System 中定义的设置更改写入 Settings.Global, 在 Android 4.2 及更高版本上运行时,写入操作将静默失败。

    即使 android:targetSdkVersionandroid:minSdkVersion 的值低于 17,您的应用也无法修改 在 Android 4.2 及更高版本上运行时已移至 Settings.Global

  • 如果您的应用使用 WebView,Android 4.2 会在 因此您可以更安全地将 JavaScript 绑定到您的 Android 代码。如果您将 targetSdkVersion 17 或更高版本,现在必须将 @JavascriptInterface 注解添加到您 (该方法也必须为公开方法)。如果您没有提供 注解,则 WebView 中的网页无法访问此方法 在 Android 4.2 或更高版本上运行时。如果您将 targetSdkVersion 版本 16 或更低版本,则不是必需的,但我们建议您更新目标版本 并添加注释以提高安全性。

    详细了解绑定 JavaScript 代码转换为 Android 代码

Daydream

Daydream 是一种适用于 Android 设备的全新互动式屏保模式。它会自动激活 当设备插入基座时,或当设备插入基座时处于空闲状态时 充电(而不是关闭屏幕)。Daydream 一次显示一个梦, 是纯视觉的被动显示,轻触时会关闭,或者可能是互动式的自适应型显示设备 一整套输入事件。梦想会在应用进程中运行,并且拥有以下全部权限: Android 界面工具包(包括视图、布局和动画),使其更加灵活 比动态壁纸或应用微件更强大。

您可以通过实现 DreamService 的子类为 Daydream 创建梦想。DreamService API 是 在设计上与Activity的设计类似要为 实现以下目的后,随时将布局资源 ID 或 View 传递给 setContentView(): 一个窗口,例如在 onAttachedToWindow() 中 回调。

DreamService 类提供了其他重要的生命周期回调 方法,例如 onDreamingStarted()onDreamingStopped()onDetachedFromWindow()Service 您不能从DreamService 应用,由系统自动启动。

如果您的梦境是交互式的,您可以从梦中启动一个 activity,以将用户引导至 应用的完整界面,以获取更多详细信息或控制。您可以使用 finish() 结束 Dream,以便用户可以看到 新活动。

如需使系统能够使用 Daydream,请使用 <service> 元素声明 DreamService 。然后,您必须添加一个具有 "android.service.dreams.DreamService" 操作的 intent 过滤器。例如:

<service android:name=".MyDream" android:exported="true"
    android:icon="@drawable/dream_icon" android:label="@string/dream_label" >
    <intent-filter>
        <action android:name="android.service.dreams.DreamService" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>

DreamService 中还有其他一些有用的方法 需要注意的事项:

  • setInteractive(boolean) 控制是否 该梦境会接收输入事件,或者在用户输入后立即退出。如果梦想是 互动,用户可以使用“返回”或“主屏幕”按钮退出梦想,或者您也可以调用 finish()让梦想停止。
  • 如果您想实现完全沉浸式显示屏,可以调用 setFullscreen() 来隐藏状态栏。
  • 在 Daydream 启动前,显示屏会变暗,以告知用户闲置超时 逼近。调用 setScreenBright(true) 可让您改为将显示屏设置为其正常亮度。

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

辅助显示屏

Android 现在允许您的应用在连接的其他屏幕上显示独特的内容 通过有线连接或 Wi-Fi 连接到用户的设备。 如需为辅助显示屏创建独特的内容,请扩展 Presentation 类,并实现 onCreate() 回调。介于 onCreate(),为辅助显示屏指定界面 方法是调用 setContentView()。 作为 Dialog 类的扩展,Presentation 类提供您的应用可在其中显示唯一界面的区域 辅助显示屏。

如需检测可用于显示 Presentation 的辅助显示屏, 使用 DisplayManagerMediaRouter API。虽然 DisplayManager API 可让您 则通常应使用 MediaRouter 来快速访问系统的默认显示屏, 演示文稿。

如需获取演示文稿的默认显示方式,请调用 MediaRouter.getSelectedRoute() 并将其传递 ROUTE_TYPE_LIVE_VIDEO。这将返回一个 MediaRouter.RouteInfo 对象,用于描述系统当前选定的路线 。如果 MediaRouter.RouteInfo 不为 null,请调用 getPresentationDisplay(),用于获取表示已连接屏幕的 Display

然后,您可以通过传递 Display 对象来显示演示文稿 转换为 Presentation 类的构造函数。现在,您的演示文稿将 显示在辅助显示屏上

如需在运行时检测何时连接了新屏幕,请创建一个 MediaRouter.SimpleCallback 实例,并在其中实现 onRoutePresentationDisplayChanged() 回调方法,系统会在有新的屏幕连接时调用该方法 已连接展示显示屏。然后注册 MediaRouter.SimpleCallback,方法是将其与 ROUTE_TYPE_LIVE_VIDEO 路线类型一起传递给 MediaRouter.addCallback()。收到以下电话号码的来电时 onRoutePresentationDisplayChanged(),只需按上文所述调用 MediaRouter.getSelectedRoute() 即可。

如需进一步优化 Presentation 中的界面,请执行以下操作: 您可以应用 一个不同的主题,具体方法是在您之前创建好的 <style> 中指定 android:presentationTheme 属性 应用到您的应用或活动

请注意,连接到用户设备的屏幕通常较大, 可能不同的屏幕密度由于屏幕特性可能会有所不同,因此您应该 提供专门针对如此大屏幕进行了优化的资源。如果您需要 如需从 Presentation 请求其他资源,请调用 getContext().getResources() 以获取与显示屏对应的 Resources 对象。这提供了 从您的应用中选出最适合您的应用的 辅助显示屏的屏幕尺寸和密度

如需了解详情和查看一些代码示例,请参阅 Presentation 类文档。

锁屏微件

Android 现在允许用户将应用微件添加到锁定屏幕。使您的应用微件可用于 锁屏时,请将 android:widgetCategory 属性添加到用于指定 AppWidgetProviderInfo 的 XML 文件中。此属性支持两个值:home_screenkeyguard。默认情况下,该属性设置为 home_screen,以便用户添加您的 添加到主屏幕。如果您希望在锁屏状态下也提供应用微件 屏幕上,添加 keyguard 值:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:widgetCategory="keyguard|home_screen">
</appwidget-provider>

您还应当使用 android:initialKeyguardLayout 属性。这与 android:initialLayout 的工作原理相同,因为它提供 在应用微件初始化且能够更新 布局。

如需详细了解如何构建适用于锁定屏幕的应用微件,包括如何正确构建 调整应用微件的大小,请参阅应用微件指南。

多用户

Android 现在允许在平板电脑等可共享设备上设置多个用户空间。网站上的每位用户 拥有自己的账号、应用、系统设置、文件和 与用户相关的信息。

作为应用开发者,您需要执行任何其他操作才能让应用正常运行 并且支持在一台设备上同时支持多名用户无论有多少用户 您的应用为特定用户保存的数据将与应用保存的数据分开保存 为其他用户提供信息系统会跟踪哪些用户数据属于哪个用户进程 您的应用正在运行,并且仅允许您的应用访问该用户的数据,并且不允许 访问其他用户的数据。

在多用户环境中保存数据

每当您的应用保存用户偏好设置、创建数据库或将文件写入用户的 内部或外部存储空间,则只有在以该用户的身份运行时才能访问这些数据。

为了确保您的应用在多用户环境中正常运行,请不要引用您的 使用硬编码路径的内部应用目录或外部存储位置,并改为始终使用 相应的 API:

无论您使用上述哪个 API 来保存指定用户的数据, 可在以其他用户身份运行时访问从应用的角度来看,每位用户都在运行 在完全独立的设备上访问。

在多用户环境中识别用户

如果您的应用想要识别唯一身份用户,例如为了收集分析数据或创建其他账号 则应遵循建议的做法,识别 唯一安装次数。在应用启动时创建新的 UUID 第一次,您可以获取用于跟踪每个用户的唯一 ID,而不管有多少 用户在一台设备上安装您的应用。或者,您也可以保存从 也可以使用 Google 云消息传递提供的注册 ID。

请注意,如果您的应用请求某个硬件设备标识符(如 Wi-Fi MAC) 地址或 SERIAL 编号),它们将为每个网址提供相同的值 用户,因为这些标识符与硬件而非用户关联。更别说 如识别 应用安装博文。

新的全局设置

系统设置已更新,增加了 Settings.Global,以支持多用户。此设置集合类似于 Settings.Secure 设置,因为它们是只读的,但会应用于 设备上的所有用户空间

有多项现有设置从“Settings.System”或“Settings.Secure”转移到了这里。如果您的应用 目前正在更改之前在 Settings.System 中定义的设置 (例如 AIRPLANE_MODE_ON),那么您应该会发现 在搭载 Android 4.2 或更高版本的设备上,如果上述设置 已移至Settings.Global。您可以继续查看 Settings.Global,但由于设置不再安全 更改应用,尝试进行此类更改时将静默失败,并且系统会向 在 Android 4.2 或更高版本上运行应用时查看系统日志。

RTL 布局支持

Android 现在提供了多种 API,支持您构建 转换布局方向,以支持使用从右到左 (RTL) 界面和阅读 例如阿拉伯语和希伯来语

如需开始在应用中支持 RTL 布局,请在清单文件中将 android:supportsRtl 属性设置为 <application> 元素 并将其设为 “true"。启用后,系统将启用各种 RTL API 以 使用 RTL 布局显示您的应用。例如,操作栏会显示图标和标题 操作按钮位于右侧,操作按钮位于左侧,而您使用 框架提供的 View 类也会反转。

在以 RTL 布局显示应用时,如果您需要进一步优化应用的外观, 有两种基本的优化等级:

  1. 将面向左侧和面向右侧的布局属性转换为面向开头和面向结尾的布局 属性。

    例如,使用 android:layout_marginStart 取代了 android:layout_marginLeftandroid:layout_marginEnd,用以取代 android:layout_marginRight

    RelativeLayout 类还提供了相应的布局 用于替换左侧/右侧位置的属性,例如 android:layout_alignParentStart 到 替换 android:layout_alignParentLeftandroid:layout_toStartOf,而非 android:layout_toLeftOf

  2. 或者,要提供针对 RTL 布局的全面优化, 使用 ldrtl 资源限定符的布局文件(ldrtl 代表 layout-direction-right-to-left})。例如,您可以将默认布局文件保存在 res/layout/ 以及 res/layout-ldrtl/ 中的 RTL 优化布局。

    ldrtl 限定符非常适合可绘制资源,因此您可以 朝向与阅读方向对应的方向的图形。

框架中还提供了各种其他 API 来支持 RTL 布局,例如 View 类,以便您可以为自定义 在 Configuration 中查询当前的布局方向。

注意:如果您使用的是 SQlite,并且有一些表格或列名称 “仅数字”是 请注意:使用 String.format(String, Object...) 可能导致错误,其中数字 已转换为对应的阿拉伯语(如果您的设备设置为阿拉伯语语言区域)。 您必须使用 String.format(Locale,String,Object...) 来确保号码 以 ASCII 格式保存。也使用 String.format("%d", int),而不是使用 String.valueOf(int): 设置数字格式。

嵌套 Fragment

您现在可以在 fragment 内嵌入 fragment。这适用于 您希望将动态且可重复使用的界面组件放入本身的界面组件中 而且是动态的且可重复使用例如,如果您使用 ViewPager 来 创建左右滑动并占用大部分屏幕空间的 fragment, 现在,将片段插入每个片段页面中

如需嵌套 fragment,只需在getChildFragmentManager() 要在其中添加 fragment 的 Fragment。这将返回一个 FragmentManager,您可以像往常在顶级 activity 中一样使用它 来创建 fragment 事务。例如,以下代码可从 一个现有的 Fragment 类:

Kotlin

val videoFragment = VideoPlayerFragment()
childFragmentManager.beginTransaction().apply {
    add(R.id.video_fragment, videoFragment)
    commit()
}

Java

Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();

在嵌套 fragment 中,您可以通过调用 getParentFragment()

Android 支持库现在支持嵌套 fragment,因此您可以实现嵌套式 fragment fragment 设计。

注意:如果某个布局 包含 <fragment>。嵌套 fragment 只有在添加到 fragment。

Renderscript

Renderscript 计算功能得到了增强,具体如下:

脚本内建函数

您可以使用 Renderscript 的内置脚本内建函数, 常见操作,例如:

如需使用脚本固有特性,请调用每个固有特性的静态 create() 方法 以创建脚本实例。然后,调用可用的 set()。 方法,以设置任何必要的输入和选项。 最后,调用 forEach() 方法来执行该脚本。

脚本组

ScriptGroup 用于将相关的 Renderscript 连在一起。 脚本,并通过一次调用执行这些脚本。

使用 ScriptGroup.Builder 将所有脚本添加到组中 方法是调用 addKernel()。在您 添加所有脚本,在 调用 addConnection() 来编写脚本。 添加完连接后,请调用 create() 创建脚本组在执行脚本组之前,请指定输入 Allocation 和要通过 setInput(Script.KernelID, Allocation) 方法并提供输出 Allocation,结果将写入其中,并作为最终脚本 使用 setOutput() 运行。最后,调用 execute():用于运行脚本组。

Filterscript

Filterscript 为现有 Renderscript API 定义了允许生成的代码运行的限制条件 在更多类型的处理器(CPU、GPU 和 DSP)上运行。如需创建 Filterscript 文件,请创建 .fs 文件而不是 .rs 文件,并将 #pragma rs_fp_relaxed 指定为 告知 Renderscript 运行时您的脚本不需要严格的 IEEE 754-2008 浮点精度。 这种精度允许非规格化数清零,还可进行向零舍入。此外,您的 Filterscript 脚本不得使用 32 位内置类型,并且必须使用 __attribute__((kernel)) 属性,因为 Filterscript 不支持指针, 由 root() 函数的默认签名定义。

注意:虽然平台支持 Filterscript,但开发者 SDK 工具版本 21.0.1 将提供相关支持。

如需详细了解 Android 4.2 中的所有 API 变更,请参阅 API 差异报告