设备兼容性模式

Android 会为声明了屏幕方向或尺寸调整限制的应用激活兼容模式。兼容模式可确保应用在大屏设备、可折叠翻盖手机和桌面环境中具有可接受的行为,但会降低应用的易用性。

设备制造商、虚拟设备所有者1 和用户可借助按应用替换项来更改应用行为,从而改善应用布局或防止应用在特定设备上出现故障。

Android 16

Android 16(API 级别 36)会忽略屏幕方向、宽高比和应用尺寸可调整性限制,以改进在最小宽度 >= 600dp 的设备上的应用布局。

以下按应用进行的替换对以 API 级别 36 为目标平台的应用无效:

选择停用

您的应用可以以 API 级别 36 为目标平台,但选择不采用 Android 16 行为,在这种情况下,OVERRIDE_ANY_ORIENTATION_TO_USER 不适用。

声明清单属性

如需停用 API 级别 36 行为,请声明 PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY 清单属性。

如需停用特定活动,请在 <activity> 元素中设置相应属性:

<activity ...>
    <property
        android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY"
        android:value="true" />
    ...
</activity>

如需为整个应用停用,请在 <application> 元素中设置该属性:

<application ...>
    <property
        android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY"
        android:value="true" />
    ...
</application>

参考设备

以下设备可能需要按应用进行替换,因为它们具有不寻常的配置或应用不太支持的配置:

  • 平板电脑:某些平板电脑(例如 Pixel Tablet)的自然屏幕方向为横向。当 Display#getRotation() 返回 Surface.ROTATION_0 时,设备处于自然屏幕方向。如果应用假定 ROTATION_0 为纵向,应用布局和相机预览可能会与设备显示屏不匹配。
  • 横向可折叠设备:有些可折叠设备(例如 Pixel Fold)在折叠时为竖屏方向,但在展开时为横屏方向。如果应用假定展开状态为竖屏,则可能会出现闪烁循环或布局问题。
  • 可折叠翻盖手机:展开的翻盖手机通常处于竖屏模式。不过,折叠后,这些手机通常会有一个横向的小显示屏。应用必须识别并适应显示屏的不同屏幕方向。
  • ���接显示���:���分设备可以在外接显示器上启动桌面窗口化会话。应用必须查询外部显示屏以获取屏幕尺寸和分辨率等信息;否则,应用可能会对显示屏做出错误的假设,从而导致应用行为不正确。
  • 车载显示屏:许多(但不是全部)车载显示屏都是横向的。为汽车显示屏开发停车状态下使用的应用与为平板电脑开发应用类似。

常见兼容性问题

应用之所以会发生兼容性问题,最常见的原因包括:应用在屏幕方向、尺寸可调整性和宽高比方面存在限制,未正确处理相机预览屏幕方向,以及滥用 API。

信箱模式

信箱模式会将应用放置在屏幕中央或大屏幕的某一侧,以方便用户使用。应用侧边或顶部和底部未使用的显示区域将以遮罩效果(纯色条或虚化壁纸)填满。

大屏设备上经常出现信箱模式,因为大屏设备显示屏的尺寸和宽高比通常与标准手机的尺寸和宽高比不同,而大多数应用是针对标准手机设计的。

图 1. 仅限纵向的应用在横屏平板电脑和可折叠设备上会进入信箱模式。

问题

应用仅支持部分显示配置,因为其屏幕方向固定、宽高比固定或不可调整大小。

以下配置设置可控制应用的屏幕方向和尺寸调整功能:

  • screenOrientation:为应用指定固定的屏幕方向。应用还可以使用 Activity#setRequestedOrientation() 在运行时设置屏幕方向。

  • resizeableActivity:指示系统是否可以调整应用大小,以适应不同尺寸的窗口。在 Android 11(API 级别 30)及更低版本中,指定应用是否支持多窗口模式。在 Android 12(API 级别 31)及更高版本中,指定应用在小屏(紧凑型窗口大小类)设备上是否支持多窗口模式。在 Android 12 及更高版本中,无论此设置如何,应用在大屏(中等或较大窗口大小类别)设备上均支持多窗口模式。

  • maxAspectRatio:指定应用支持的最大宽高比。只有 resizeableActivity 设置为 false 的应用才可以设置 maxAspectRatio

  • minAspectRatio:指定应用支持的最小宽高比。只有 resizeableActivity 设置为 false 的应用才可以设置 minAspectRatio

优化

应用应支持所有设备及多窗口模式显示屏方向和尺寸。请从应用布局和应用清单文件中移除对屏幕方向和固定宽高比方面的所有限制。

兼容性问题权宜解决方法

如果某个应用采用固定的屏幕方向或固定的宽高比,并且不直接支持其运行窗口的尺寸或屏幕方向,Android 就会让该应用进入信箱模式,以保持其连续性。

从 Android 12(API 级别 31)开始,一直到 Android 12L(API 级别 32),Android 平台会对进入信箱模式的应用使用各种增强功能。界面增强功能由设备制造商实现。您无需为应用进行任何额外开发即可受益于这些改进。

Android 12(API 级别 31)引入了以下提升美感的增强功能,可由设备制造商进行配置:

  • 圆角:让应用窗口的四角看起来更美观好看。
  • 系统栏透明度:叠加在应用上的状态栏和导航栏都是半透明的,使栏中的图标在信箱模式背景上始终清晰可见。
  • 可配置的宽高比:可调整应用的宽高比,以提升应用的外观。

图 2. 采用界面增强功能的应用在进入信箱模式后的显示效果。

Android 12L(API 级别 32)增加了以下功能改进:

  • 放置位置可配置:在大屏设备上,设备制造商可以将应用放置在显示屏左侧或右侧,让交互变得更轻松。

  • 经过重新设计的重启按钮:设备制造商可以为尺寸兼容模式的重启按钮赋予新的外观,让用户更易识别。

Android 13(API 级别 33)添加了一个用户指导对话框,用于介绍如何确定进入信箱模式的应用在屏幕上的位置或在分屏模式下添加信箱模式:

图 3. 包含用户指导对话框的进入信箱模式的应用。

尺寸兼容模式

尺寸兼容模式是指保持应用宽高比并包含重启控件的信箱模式。此控件让用户可重启应用并重新绘制显示屏。对于不可调整大小的应用,Android 会调用尺寸兼容模式。当某个 activity 移至与该 activity 的尺寸不兼容的显示容器时,系统可能会重新缩放此应用,使其至少在一个尺寸上填满设备显示屏。

可能触发尺寸兼容模式的设备配置更改包括:

  • 设备旋转
  • 可折叠设备的折叠或展开
  • 在全屏和分屏显示模式之间切换

问题

尺寸兼容模式通常适用于屏幕方向或宽高比受限且配置为(或被系统确定为)��可调整大小的 activity。

如果您的应用符合以下任一条件,则会被视为可调整大小,且不会置于尺寸兼容模式下:

如果您的应用不符合上述任一条件,会被视为不可调整大小,并可能会置于尺寸兼容模式下。

优化

应用应支持所有显示大小。在应用清单中将 <activity><application> 元素的 android:resizeableActivity 属性设置为 true,以使应用可调整大小。为您的应用设计响应式/自适应布局。如需了解详情,请参阅支持不同的显示屏尺寸支持多窗口模式

兼容性问题权宜解决方法

如果系统确定可将应用大小重新调整为填满显示屏窗口的至少一个尺寸,进而可提升进入信箱模式的应用的显示效果,Android 便会将应用置于尺寸兼容模式下。系统会显示一个重启控件,此控件可用于重新创建应用进程、重新创建 activity 并重新绘制显示屏。另请参阅进程和线程概览

显示兼容性模式

显示兼容性模式可防止应用在不同显示屏之间移动时重新启动,因为这可能会触发配置变更,例如色彩模式触控屏可用性屏幕密度变更。

游戏默认启用显示兼容性模式(基于 android:appCategory 标志),以提高稳定性和连续性。与尺寸兼容模式不同,显示兼容模式不会冻结应用的配置。应用仍然可以通过 onConfigurationChanged() 回调等 API 接收所有配置更新,但可以避免中断性重启。这意味着,即使游戏处于显示兼容模式,只要能正确支持 onConfigurationChanged() 等 API,仍可响应式地更新其界面。

如需选择不使用显示屏兼容性模式并在应用中处理配置更改,请在应用的 AndroidManifest.xml 文件中声明对配置更改的支持,并在 onConfigurationChanged() 回调中处理配置更改。

<activity
    android:name=".MyGameActivity"
    android:configChanges="colorMode|touchscreen|density|...">
    ...
</activity>

闪烁循环

如果某个应用仅支持部分显示屏方向,在发生配置更改时,此应用可能会反复请求新的屏幕方向,从而形成一个无限循环,使显示屏无休止地闪烁或使此应用无休止地旋转。

问题

在 Android 12(API 级别 31)及更高版本中,设备制造商可以将设备配置为忽略应用指定的屏幕方向限制,而改为强制执行兼容模式。例如,当某个 activity 显示在设备的横向内屏(平板电脑大小)中时,可折叠设备可以忽略此 activity 的 android:screenOrientation="portrait" 设置。

如果系统忽略了某个应用的屏幕方向限制,此应用可以通过调用 Activity#setRequestedOrientation() 以编程方式设置其屏幕方向。如果应用无法处理配置更改,此调用会触发应用重启(请参阅处理配置更改)。重启后,系统会再次忽略此应用的屏幕方向限制,应用则会重复调用 setRequestedOrientation(),而调用又会触发应用重启,如此循环往复。

另一种可能遇到此问题的情况是,设备屏幕的自然方向(即 Android 确定的通常屏幕方向)为横向(也就是说,调用 Display#getRotation() 会返回 Surface.ROTATION_0,而设备采用的是横向宽高比)。过去,应用假定 Display.getRotation() = Surface.ROTATION_0 表示设备处于竖屏模式,但有时并非如���,例如在某些可折叠设备的内屏和某些���板电脑上。

���可折叠设备的内屏上,横屏状态的应用可能会检查屏幕旋转情况,收到值 ROTATION_0,假定设备的自然屏幕方向为纵向,然后调用 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ) 以重新配置应用布局。在横屏状态下重启后,此应用可能会再次检查屏幕旋转情况,收到值 ROTATION_0,调用 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT),然后继续无限循环。

优化

应用不应执行以下操作:

  • 在 activity onCreate() 方法中使用 Activity#setRequestedOrientation() 设置默认屏幕方向,因为屏幕方向请求可能会由未处理的配置更改意外触发
  • 假定设备的自然屏幕方向 (ROTATION_0) 为纵向
  • 根据与当前窗口大小无关的信号设置屏幕方向,例如 Display#getRotation()、是否出现 FoldingFeature已废弃的 API 等信号。

兼容性问题权宜解决方法

在以下情况下,Android 会忽略对 Activity#setRequestedOrientation() 的调用:

  • activity 已通过之前对此方法的调用重新启动,或相机兼容性强制旋转处理已启用(请参阅下文的相机预览部分)。

    设备制造商可以通过 OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION 将此行为应用于应用。

  • activity 在一秒内发出了两个以上的屏幕方向请求,这表示发生了循环。对于循环中的两个请求,Android 会使用能让应用显示区域最大化的那一个请求。

    设备制造商可以通过 OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED 将此行为应用于应用。

  • 虚拟设��所有者已替换部分设备上的方法调用。

相机预览

在平板电脑、笔记本电脑和可折叠设备的显示屏上,相机应用的相机预览(或取景器)可能会未对齐或扭曲。

另请参阅桌面窗口化中的相机预览

问题

Android 兼容性定义文档中规定,摄像头图像传感器“必须朝向正确方向,以便摄像头的长度方向与屏幕的长度方向对齐”。

应用通常假定设备的屏幕方向和摄像头传感器方向为纵向,在标准手机上,这种假定是合理的。但是,平板电脑和笔记本电脑的自然屏幕方向及其摄像头传感器的自然方向可能是横向的。此外,可折叠设备等新外形规格的设备可能会具有多个自然屏幕方向,并且具有方向各异的多个摄像头传感器。

如果以应用无法预期的摄像头方向启动 activity 或在不同摄像头或设备屏幕(针对可折叠设备)之间切换,可能会导致相机预览未对齐或扭曲。

优化

相机应用必须正确识别和管理设备屏幕方向和摄像头传感器方向,以便显示正确对齐和缩放的相机预览。 应用必须计算设备旋转情况、传感器旋转情况,以及屏幕或窗口宽高比,然后将结果应用到相机预览。如需获得详细指南,请参阅相机预览相机取景器简介

兼容性问题权宜解决方法

Display#getRotation() 返回 Surface.ROTATION_0 时,设备处于自然屏幕方向。系统会根据设备的自然屏幕方向计算 CameraCharacteristics.SENSOR_ORIENTATION。针对仅限纵向的应用,Android 会根据设备的自然屏幕方向对齐纵向窗口,这也是大多数应用预期的情况。当传感器方向为横向且相机预览为纵向时,Android 还会剪裁摄像头传感器图像。具体的权宜解决方法包括:

  • 针对仅限纵向的应用强制旋转相机预览:如果应用仅限纵向,就会预期设备的自然屏幕方向和相机传感器方向均为纵向。不过,在 Android 12(API 级别 31)及更高版本中,如果设备制造商忽略屏幕方向规范,应用便可以在多种设备屏幕方向下运行。

    当仅限纵向的应用连接到相机时,Android 会强制旋转此应用,使应用的纵向窗口与设备的自然屏幕方向一致。

    在某些平板电脑(请参阅参考设备)上,应用纵向窗口会旋转为纵向全屏模式,以便与设备的自然屏幕方向一致。强制旋转后,应用将占满整个屏幕。

    在可折叠设备的横向内屏上(请参阅参考设备),系统会将仅限纵向的 activity 旋转为横向,以便与展开后的自然屏幕方向一致。强制旋转后,应用将进入信箱模式。

  • 内部前置摄像头剪裁:某些可折叠设备上的内部前置摄像头传感器的方向为横向。除了强制旋转可折叠内屏上的相机预览以外,Android 还会剪裁内部前置(横向)摄像头的视野范围,以便传感器能够捕获与设备屏幕方向相反的视图。

  • 强制刷新相机预览:强制旋转后,系统会循环使用 activity 方法 onStop()onStart()(默认)或 onPause()onResume()(由 OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE 按应用替换项采用),以确保相机预览能够正确显示。

  • 宽高比缩放:系统会动态地将强制旋转后的相机预览的宽高比更改为更高的最小宽高比,以确保相机预览能够正确缩放。

如果应用正确处理相机预览,应用开发者可以替换这些权宜解决方法。请参阅按应用替换项

常遭滥用的 API

由于 Android 增加了对多窗口模式等功能和可折叠设备等设备的支持,旧版 API 已废弃,取而代之的是适用于所有显示大小和设备外形规格的最新 API。不过,为实现向后兼容性,已废弃的 API 仍然可用。

有些 View API 专为特殊用途而设计,开发者有时并不了解它们。

问题

开发者继续使用已废弃的 Display API,并错误地假定这些 API 会返回应用边界,而不是返回设备显示区域边界。或者,开发者会错误地使用特殊用途的 view API 来获取常规显示指标。结果就是,在应用窗口大小调整事件发生后重新确定界面元素位置时出现计算错误,导致出现布局问题。

已废弃和常遭滥用的 Display API:

如需了解详情,请参阅支持多窗口模式

遭滥用的 View API

优化

从不依赖实际显示大小来确定界面元素位置。将您的应用迁移到基于 WindowMetrics 的 API,包括以下 WindowManager API:

兼容性问题权宜解决方法

两个替换项会调整已废弃的 Display API 和遭滥用的 View API,以返回应用边界:ALWAYS_SANDBOX_DISPLAY_APIS 适用于 Display API;OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS 适用于 View API。ALWAYS_SANDBOX_DISPLAY_APIS 还默认应用于符合尺寸兼容模式使用条件的应用。

透明 activity

透明 activity 是透明背景样式的结果,例如:

<style name="Transparent" parent="AppTheme">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
</style>

与对话框相关的主题(例如 Theme.MaterialComponents.Dialog)可包含会使 activity 透明的样式。

透明 activity 无法覆盖所有可用的显示空间,这使得它们难以管理,因为可用的显示区域可以因配置更改(例如设备旋转、设备折叠和展开,以及多窗口模式)而发生变化。

问题

透明 activity 应该符合任务 activity 堆栈中位于透明 activity 下的第一个不透明 activity 的边界。不过,用于启动权限对话框的不透明 activity 可能是 trampoline(一种用于启动其他 activity 然后消失的 activity);因此,系统无法确定启动透明权限对话框 activity 的 trampoline activity 的边界。

优化

透明 activity 会继承在任务 activity 堆栈中位于其下方最顶层的不透明 activity 的约束条件。此不透明 activity 必须在相应透明 activity 的整个���命周期(从 activity 创建到销毁)内保持可用。因此,请勿通过 trampoline activity 启动权限请求。

如果 trampoline activity 启动权限请求,用户可能无法看到权限对话框,因为在用户有机会响应对话框之前,trampoline activity 就已被销毁,并且对话框 activity 的尺寸和位置可能计算有误。

在用户做出权限决定之前,应用应该始终通过保持可见状态的 activity 启动权限请求。

圆角

如果某个 activity 使用的样式指定了背景透明度,或者该 activity 的内容未填满可用的显示空间,它就可以是透明 activity。若是某个透明 activity 填满了可用的显示空间,如果设备制造商配置了圆角,系统会自动将圆角应用到该 activity。但是,如果透明 activity(例如权限对话框)未填满可用空间,您可以决定是否应用圆角。

权限对话框不会填满可用的显示空间,因为对话框布局通常使用 LayoutParams.WRAP_CONTENT,而不是 LayoutParams.MATCH_PARENT

兼容性问题权宜解决方法

让用于启动对话框 activity 的 activity 在用户响应对话框之前一直保持可见。

系统会确保透明 activity 继承在 activity 堆栈中位于相应透明 activity 下面的第一个不透明 activity 的所有约束条件,包括与以下方面相关的约束条件:

  • 尺寸兼容模式
  • 屏幕方向
  • 宽高比

Unity 游戏

在 Android 设备上,Unity 游戏可以在全屏模式或多窗口模式下运行。不过,当应用被置于多窗口模式时,许多 Unity 游戏都会失去焦点,并停止绘制内容。

问题

Unity 在 2019.4 版本中添加了 Resizable Window 选项,以在 Android 设备上支持多窗口模式。不过,初始实现无法正确响应多窗口模式下的 activity 生命周期,导致 UnityPlayer 在应用失去焦点后暂停播放。播放器会渲染黑屏或游戏的最后一个冻结帧。只有在用户点按屏幕后,游戏内容才会恢复。许多使用 Unity 引擎的应用都会面临这一问题,并会在多窗口模式下渲染为黑色窗口。

优化

将 Unity 升级到 2019.4.40 或更高版本,然后重新导出游戏。在 Android 播放器设置中使 Resizable Window 选项保持选中状态,否则游戏将在失去焦点时暂停,即使游戏在多窗口模式下完全可见也会如此。

兼容性问题权宜解决方法

设备制造商可以采用 OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS 按应用替换项,从而在多窗口模式下向应用提供虚假焦点事件。此替换项会使 activity 能够重新绘制内容,且不出现黑屏。

窗口化模式

当应用在桌面窗口化环境中运行时,可能会遇到其他兼容模式。

锁定屏幕方向的应用可以自由调整大小。即使 activity 锁定为纵向,用户仍可将应用调整为横向。

纵向应用调整为横向的动画。

不过,如果 activity 被声明为不可调整大小 (resizeableActivity = false),则 activity 界面会缩放,同时保持相同的宽高比。

应用调整大小的动画。界面会缩放以填充桌面窗口。

桌面窗口模式下的相机预览

当应用在窗口化模式下运行时,显示屏旋转和窗口方向可能与在标准手机上以全屏模式运行时遇到的情况不同。

问题

应用通常假定设备的屏幕方向和摄像头传感器方向为纵向,这可能会导致相机预览未对齐或扭曲。

优化

相机应用必须正确识别和管理设备屏幕方向和摄像头传感器方向,以便显示正确对齐和缩放的相机预览。 应用必须计算设备旋转情况、传感器旋转情况和窗口宽高比,然后将结果应用到相机预览,相机预览还应响应窗口配置更改。如需获得详细指南,请参阅相机预览

兼容性问题权宜解决方法

当桌面窗口模式下的固定屏幕方向应用启动相机预览时,系统可能会触发相机兼容性处理,以避免预览画面拉伸和侧向显示。

该处理会以以下方式对环境进行沙盒处理,以匹配所请求的屏幕方向:

  • 将应用窗口设为信箱模式,以适应所请求的屏幕方向:这是为了避免因缩放不当而导致拉伸问题。

  • 对显示屏旋转进行沙盒处理:该处理会模拟设备放置在所请求的方向。由于相机预览最常见的错误假设是应用在纵向设备上运行,因此对于请求纵向屏幕方向的应用,显示旋转会沙盒化为 0 度;对于请求横向屏幕方向的设备,显示旋转会沙盒化为 90 度。

  • 摄像头画面剪裁:如果显示屏旋转方向发生变化,这会反映在摄像头画面上:如��设备处于横向屏幕方向,并且针对请求纵向屏幕方向的应用触发了处理,则摄像头视野范围会被剪裁,以类似于纵向屏幕方向的摄像头。

  • 旋转和裁剪相机 feed:在应用处理后,系统会循环使用 activity 方法 onStop()onStart()(默认)或 onPause()onResume()(由 OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE 按应用替换项采用),以确保相机预览能够正确显示。

如果应用正确处理相机预览,应用开发者可以替换这些权宜解决方法。请参阅按应用替换项

调整大小

当模拟的请求屏幕方向处理处于有效状态时,调整窗口大小会缩放取景器界面,同时保持其宽高比。应用窗口的其余部分可以自由调整大小。

测试应用是否存在兼容性问题

如需测试您的应用并了解它在不同外形规格上的行为方式,请利用以下资源:

为信箱模式

确认是否每个 activity 都可以使用应用可用的所有显示空间。首先,在测试文件夹中声明以下代码:

Kotlin

fun isLetterboxed(activity: AppCompatActivity): Boolean {
    if (isInMultiWindowMode) return false

    val wmc = WindowMetricsCalculator.getOrCreate()
    val currentBounds = wmc.computeCurrentWindowMetrics(this).bounds
    val maxBounds = wmc.computeMaximumWindowMetrics(this).bounds

    val isScreenPortrait = maxBounds.height() > maxBounds.width()

    return if (isScreenPortrait) {
        currentBounds.height() < maxBounds.height()
    } else {
        currentBounds.width() < maxBounds.width()
    }
}

Java

public boolean isLetterboxed(AppCompatActivity activity) {
    if (activity.isInMultiWindowMode()) {
        return false;
    }

    WindowMetricsCalculator wmc = WindowMetricsCalculator.getOrCreate();
    Rect currentBounds = wmc.computeCurrentWindowMetrics(activity).getBounds();
    Rect maxBounds = wmc.computeMaximumWindowMetrics(activity).getBounds();

    boolean isScreenPortrait = maxBounds.height() > maxBounds.width();

    return (isScreenPortrait)
        ? currentBounds.height() < maxBounds.height()
        : currentBounds.width() < maxBounds.width();
}

然后,运行测试以断言该行为,并确保目标 activity 未采用信箱模式:

Kotlin

@get:Rule
val activityRule = ActivityScenarioRule(MainActivity::class.java)

@Test
fun activity_launched_notLetterBoxed() {
    activityRule.scenario.onActivity {
        assertFalse(it.isLetterboxed())
    }
}

Java

@Rule
public ActivityScenarioRule<MainActivity> rule = new ActivityScenarioRule<>(MainActivity.class);

@Test
public void activity_launched_notLetterBoxed() {
    try (ActivityScenario<MainActivity> scenario =
        ActivityScenario.launch(MainActivity.class)) {
            scenario.onActivity( activity -> {
                assertFalse(activity.isLetterboxed());
            });
        }
}

理想情况下,只运行这种测试,直到测试通过,并断言应用的 activity 占用应用可用的整个显示空间。在所有类型的设备上测试您的应用,以确保行为一致。

按应用替换项

Android 提供可用于更改已配置的应用行为的替换项。例如,FORCE_RESIZE_APP 替换项指示系统绕过尺寸兼容模式,并将应用大小调整为适合显示屏尺寸,即使在应用清单中指定了 resizeableActivity="false" 也是如此。

设备制造商将替换项应用于特定设备上的所选应用或所有应用。在 Android 14(API 级别 34)及更高版本中,用户可以通过设备设置对应用应用替换项。在 Android 16(API 级别 36)及更高版本中,虚拟设备所有者可以在其管理的所选设备上应用替换。

用户按应用替换项

在 Android 14 及更高版本中,用户可以通过设置菜单更改应用的长宽比。参考设备等大屏设备会实现该菜单。

该菜单包含设备上安装的所有应用的列表。用户选择一个应用,然后将应用宽高比设置为 3:4、1:1、全屏或设备制造商配置的其他值。用户还可以将宽高比重置为应用清单中指定的应用默认宽高比。

应用可以通过设置以下 PackageManager.Property 标记来选择停用兼容性替换:

  • PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE

    如需选择不使用用户宽高比兼容性替换项,请将相应属性添加到应用清单中,并将值设置为 false

    <application>
        <property
            android:name="android.window.
            PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"
            android:value="false" />
    </application>
    

    您的应用将从设备设置中的应用列表中排除。用户将无法替换应用的宽高比。

    将该属性设置为 true 不会产生任何影响。

  • PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE

    如需选择不使用用户宽高比兼容性替换设置的全屏选项,请将该属性添加到应用清单中,并将值设置为 false

    <application>
        <property
            android:name="android.window.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE"
            android:value="false" />
    </application>
    

    从设备设置中的宽高比选项列表中移除了全屏选项。用户将无法对您的应用应用全屏覆盖。

    将此属性设置为 true 不会产生任何影响。

针对所有屏幕优化应用:请勿在应用中设置宽高比限制。使用窗口大小类别根据可用的显示空间量支持不同的布局。

设备按应用替换项

设备制造商和虚拟设备所有者(选择受信任的特权应用)在特定设备(包括平板电脑、可折叠设备、ChromeOS 设备和车载显示屏)上按应用应用替换项。参考设备可能会默认将一些替换项应用于各种应用。

应用可以选择停用大多数替换项(请参阅下文的按应用替换项表格)。

您可以使用兼容性框架在启用或停用替换项的情况下测试您的应用(请参阅兼容性框架工具)。 启用后,替换项会应用于整个应用。

您还可以使用 Android 调试桥 (adb) 启用或停用替换项,并确定哪些替换项应用于您的应用。

按如下所示启用或停用替换项:

adb shell am compat enable/disable <override name/id> <package>

对于参考设备,请检查哪些替换设置适用于您的应用:

adb shell dumpsys platform_compat | grep <package name>

下表列出了可用的替换项,以及有关如何优化应用以免应用依赖于替换项的指南。您可以将属性标志添加到应用清单中,以停用某些替换项。

按应用替换项
类型 名称 ID 说明
输入源兼容性 OVERRIDE_MOUSE_TO_TOUCH 413207127 通过在 MotionEvent 实例传递给应用时重写其来源和工具类型,将鼠标设备中的 MotionEvent 实例转换为触控事件。
尺寸可调整性 FORCE_RESIZE_APP 174042936 在发生配置更改时为应用绕过尺寸兼容模式。
FORCE_NON_RESIZE_APP 181136395 在发生配置更改时强制应用进入尺寸兼容模式。
宽高比 OVERRIDE_MIN_ASPECT_RATIO 174042980 必须启用 Gatekeeper 替换项才能应用任何其他宽高比替换项。
OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY 203647190 如果启用(默认),则会将替换范围限定为仅限纵向的 activity。
OVERRIDE_MIN_ASPECT_RATIO_SMALL 349045028 将最小宽高比更改为 4:3。
OVERRIDE_MIN_ASPECT_RATIO_MEDIUM 180326845 将最小宽高比更改为 3:2。
OVERRIDE_MIN_ASPECT_RATIO_LARGE 180326787 将最小宽高比更改为 16:9。
OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN 208648326 更改最小宽高比,使其适应显示大小(或分屏宽高比)的 50%。
OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN 218959984 停用最小宽高比替换项,以便应用在设备处于竖屏模式时全屏显示。
方向 OVERRIDE_ANY_ORIENTATION 265464455 允许替换任何屏幕方向。
OVERRIDE_ANY_ORIENTATION_TO_USER 310816437 替换屏幕方向、尺寸可调整性和宽高比限制。
OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT 265452344 当 activity 的屏幕方向未定义时,将屏幕方向替换为纵向。
OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR 265451093 当 activity 的屏幕方向未定义时,将屏幕方向替换为 nosensor(使用设备的自然屏幕方向)。
OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE 266124927 将仅限横向的应用旋转 180 度。
OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA 265456536 将屏幕方向替换范围限制为当应用连接到相机时。
OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION 255940284 当任务全屏显示时(包括进入信箱模式时),将显示屏设置为固定横向自然方向。
OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION 254631730 忽略来自应用的屏幕方向请求,以免出现旋转无限循环。
OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED 273509367 在 activity 重新启动时忽略重复的屏幕方向请求。如果 Android 检测到某个应用在一秒内发出了至少两个新屏幕方向请求,系统会将此请求视为旋转无限循环并应用此替换项。
OVERRIDE_RESPECT_REQUESTED_ORIENTATION 236283604 通过停用设备制造商忽略屏幕方向请求设置来防止进入信箱模式。
Sandbox API NEVER_SANDBOX_DISPLAY_APIS 184838306 防止更改任何 Display API 的行为。
ALWAYS_SANDBOX_DISPLAY_APIS 185004937 强制应用中的 Display API 返回应用边界。Display API 会返回逻辑显示区域边界,但有时应用会假定 Display API 会返回应用边界,从而导致界面问题。
OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS 237531167 强制应用中使用的 View API 返回应用边界。View API 会返回逻辑显示区域边界,但有时应用会假定 View API 会返回应用边界,从而导致界面问题。
相机兼容性 OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION 263959004 关闭强制旋转。默认情况下,当相机预览处于打开状态时,系统会强制旋转所有固定屏幕方向的相机应用。
OVERRIDE_CAMERA_COMPAT_DISABLE_SIMULATE_REQUESTED_ORIENTATION 398195815 关闭模拟所请求的相机兼容性方向处理。默认情况下,当相机预览处于打开状态时,系统会根据固定屏幕方向的相机应用所请求的方向调整这些应用。
OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH 264304459 移除在强制旋转相机预览时采用的默认硬刷新。
OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE 264301586 在强制旋转相机预览时将硬刷新切换为软刷新,这有助于在强制旋转期间保留状态。默认情况下,当强制旋转相机预览时,Android 会应用硬刷新。硬刷新可能会导致应用出现丢失状态或黑屏问题,具体取决于应用如何缓存之前的状态。
OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT 250678880 剪裁内部前置摄像头的图像缓冲区。如果此替换项被停用,系统会移除内部前置摄像头剪裁机制,并扩大相机预览的视野范围。在某些可折叠设备(请参阅参考设备)上,当使用内部前置摄像头时,系统会默认剪裁所有相机应用的相机预览。
其他 OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS 263259275 防止应用在分屏模式下失去焦点时黑屏。应用会等待获得焦点,之后再绘制应用内容,这可能会导致应用冻结或黑屏。此替换项使 Android 能够向应用发送虚假焦点事件,从而指示应用重新开始绘制内容。

OVERRIDE_MOUSE_TO_TOUCH

启用兼容性处理,该处理通过���鼠标或触控板��� MotionEvent 实例的 MotionEvent 来源重写为 SOURCE_TOUCHSCREEN 并将 MotionEvent 工具类型重写为 TOOL_TYPE_FINGER,将鼠标或触控板的 MotionEvent 实例转换为触摸事件(当运动事件传递到应用时)。

应用可以如何达成与替换项相同的结果

不适用。此问题应该在应用逻辑中解决。

如何优化应用

您的应用应处理来自鼠标和触控板的输入事件,包括触控板手势和鼠标滚轮滚动。请参阅键盘、鼠标和触控板

如何停用替换项

在应用清单的 <uses-feature> 元素中声明 FEATURE_PC

<uses-feature android:name="android.hardware.type.pc"
              android:required="false" />

注意:请设置 android:required="false",使 PC 功能成为可选功能,这样 Google Play 就不会在非 PC 设备上排除相应应用。

用于调整替换项的属性标志

无。

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_MOUSE_TO_TOUCH <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_MOUSE_TO_TOUCH <package>

注意:这些命令只能暂时应用或移除此替换项。

FORCE_RESIZE_APP

强制使应用此替换项的软件包可调整大小,并能够进入多窗口模式。适用于所有显示屏尺寸。

应用可以如何达成与替换项相同的结果

在应用清单中,将 android:resizeableActivity 属性设置为 true

如何优化应用

使用响应式/自适应布局,让应用能够适应所有显示大小和宽高比。请参阅支持不同的屏幕尺寸

如何停用替换项

将属性标志 PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES 设置为 false

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES"
  android:value="true|false"/>

用于测试替换项的 adb 命令

如需应用此替换项并使应用可调整大小,请使用以下命令:

adb shell am compat enable FORCE_RESIZE_APP <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable FORCE_RESIZE_APP <package>

注意:这些命令只能暂时应用或移除此替换项。

FORCE_NON_RESIZE_APP

强制使应用此替换项的软件包不可调整大小,并在发生配置更改时进入尺寸兼容模式。适用于所有显示屏尺寸。

应用可以如何达成与替换项相同的结果

在应用清单中将 android:resizeableActivity 属性和 android.supports_size_changes 元数据标志均设置为 false,并声明屏幕方向或宽高比限制。

如何优化应用

所有在调整大小后能够正常运行的应用都应该将 android:resizeableActivityandroid.supports_size_changes 设置为 true。 其他应用应该进行改进,以便在调整大小后能够正常运行。请参阅 android:resizeableActivity

如何停用替换项

将属性标志 PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES 设置为 false

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES"
  android:value="true|false"/>

用于测试替换项的 adb 命令

如需应用此替换项并使应用不可调整大小,请使用以下命令:

adb shell am compat enable FORCE_NON_RESIZE_APP <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable FORCE_NON_RESIZE_APP <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_MIN_ASPECT_RATIO

适用于会强制采用指定最小宽高比的所有替换项的 Gatekeeper。

应用可以如何达成与替换项相同的结果

在 activity 或应用级别设置 android:minAspectRatio

如何优化应用

请勿在应用中设置宽高比限制。请确保您的应用支持不同的显示屏尺寸。根据应用在屏幕上占据的空间大小,使用窗口大小类别支持不同的布局。请参阅 Compose WindowSizeClass APIView WindowSizeClass API

如何停用替换项

指定宽高比限制,或将属性标志 PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE 设置为 false

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE"
  android:value="false"/>

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_MIN_ASPECT_RATIO <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_MIN_ASPECT_RATIO <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY

限制以下应用设置:针对仅限纵向的 activity 强制采用指定最小宽高比的应用设置。默认处于启用状态,只有 OVERRIDE_MIN_ASPECT_RATIO 也处于启用状态时才会生效。

应用可以如何达成与替换项相同的结果

请参阅 OVERRIDE_MIN_ASPECT_RATIO

如何优化应用

请参阅 OVERRIDE_MIN_ASPECT_RATIO

如何停用替换项

请参阅 OVERRIDE_MIN_ASPECT_RATIO

用于调整替换项的属性标志

请参阅 OVERRIDE_MIN_ASPECT_RATIO

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_MIN_ASPECT_RATIO_SMALL

将 activity 的最小宽高比设置为较小值 (4:3)。

应用可以如何达成与替换项相同的结果

请参阅 OVERRIDE_MIN_ASPECT_RATIO

如何优化应用

请参阅 OVERRIDE_MIN_ASPECT_RATIO

如何停用替换项

请参阅 OVERRIDE_MIN_ASPECT_RATIO

用于调整替换项的属性标志

请参阅 OVERRIDE_MIN_ASPECT_RATIO

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_MIN_ASPECT_RATIO_SMALL <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_MIN_ASPECT_RATIO_SMALL <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_MIN_ASPECT_RATIO_MEDIUM

将 activity 的最小宽高比设置为中等值 (3:2)。

应用可以如何达成与替换项相同的结果

请参阅 OVERRIDE_MIN_ASPECT_RATIO

如何优化应用

请参阅 OVERRIDE_MIN_ASPECT_RATIO

如何停用替换项

请参阅 OVERRIDE_MIN_ASPECT_RATIO

用于调整替换项的属性标志

请参阅 OVERRIDE_MIN_ASPECT_RATIO

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_MIN_ASPECT_RATIO_MEDIUM <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_MIN_ASPECT_RATIO_MEDIUM <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_MIN_ASPECT_RATIO_LARGE

将 activity 的最小宽高比设为较大��� (16:9)。

应用可以如何达成与替换项相同的结果

请参阅 OVERRIDE_MIN_ASPECT_RATIO

如何优化应用

请参阅 OVERRIDE_MIN_ASPECT_RATIO

如何停用替换项

请参阅 OVERRIDE_MIN_ASPECT_RATIO

用于调整替换项的属性标志

请参阅 OVERRIDE_MIN_ASPECT_RATIO

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_MIN_ASPECT_RATIO_LARGE <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_MIN_ASPECT_RATIO_LARGE <package>`

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN

允许使用分屏宽高比。允许应用在分屏模式下使用所有可用空间,避免进入信箱模式。

应用可以如何达成与替换项相同的结果

请参阅 OVERRIDE_MIN_ASPECT_RATIO

如何优化应用

请参阅 OVERRIDE_MIN_ASPECT_RATIO

如何停用替换项

请参阅 OVERRIDE_MIN_ASPECT_RATIO

用于调整替换项的属性标志

请参阅 OVERRIDE_MIN_ASPECT_RATIO

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN

在纵向全屏模式下停用最小宽高比替换项,以便使用所有可用的屏幕空间。

应用可以如何达成与替换项相同的结果

请参阅 OVERRIDE_MIN_ASPECT_RATIO

如何优化应用

请参阅 OVERRIDE_MIN_ASPECT_RATIO

如何停用替换项

请参阅 OVERRIDE_MIN_ASPECT_RATIO

用于调整替换项的属性标志

请参阅 OVERRIDE_MIN_ASPECT_RATIO

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_ANY_ORIENTATION

启用以下替换项以替换任何屏幕方向:

应用可以如何达成与替换项相同的结果

设置 activity:screenOrientation 清单属性,或使用 Activity#setRequestedOrientation() API。

如何优化应用

您的应用应支持所有屏幕方向。屏幕方向更改属于配置更改,可通过以下两种方式之一进行处理:让系统销毁并重新创建应用,或自行管理配置更改。如果您自行管理配置更改,可以使用 ViewModel 保留应用状态。在极少数情况下,您可以决定仅在小显示屏上锁定屏幕方向,但这种做法的缩放效果可能不及允许用户根据需要旋转应用的效果。在 Android 12L 及更高版本上,固定屏幕方向可被设备配置替换。如需详细了解如何处理配置变更并支持所有方向,请参阅处理配置变更ViewModel 概览限制应用在手机上的屏幕方向,但不限制其在大屏设备上的屏幕方向

如何停用替换项

将属性标志 PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE 设置为 false

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE"
  android:value="true|false"/>

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_ANY_ORIENTATION <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_ANY_ORIENTATION <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_ANY_ORIENTATION_TO_USER

使应用能够填充可用的显示空间。替换应用清单中指定的任何屏幕方向、尺寸可��整性和宽高比限制。还会忽略对 Activity#setRequestedOrientation()Activity#getRequestedOrientation() 的任何调用。

应用可以如何达成与替换项相同的结果

  • 请勿设置 android:screenOrientation 清单属性,或将该属性设置为 "user"

  • android:resizeableActivity 清单属性设置为 true

  • 在小屏设备上,如需在将 android:resizeableActivity=false 设置为 false 的情况下支持调整应用大小,同时停用多窗口模式,请将 android.supports_size_changes 元数据标志设置为 true。请勿设置 minAspectRatiomaxAspectRatio

如何优化应用

让应用支持所有屏幕方向;请勿在应用的清单中设置 screenOrientation 规范。通过将应用清单中的 android:resizeableActivity 属性设置为 true,支持应用可调整大小、多窗口模式和所有显示屏宽高比。请参阅支持不同的屏幕尺寸

如何停用替换项

请参见OVERRIDE_ANY_ORIENTATION

用于调整替换项的属性标志

请参见OVERRIDE_ANY_ORIENTATION

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_ANY_ORIENTATION_TO_USER <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_ANY_ORIENTATION_TO_USER <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT

为软件包中的所有 activity 启用纵向屏幕方向。除非已启用 OVERRIDE_ANY_ORIENTATION,否则只有当 activity 未指定其他固定屏幕方向时,系统才会使用此替换项。

应用可以如何达成与替换项相同的结果

请参见OVERRIDE_ANY_ORIENTATION

如何优化应用

请参见OVERRIDE_ANY_ORIENTATION

如何停用替换项

请参见OVERRIDE_ANY_ORIENTATION

用于调整替换项的属性标志

请参见OVERRIDE_ANY_ORIENTATION

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR

为软件包中的所有 activity 启用 nosensor 屏幕方向。除非已启用 OVERRIDE_ANY_ORIENTATION,否则只有当 activity 未指定其他固定屏幕方向时,系统才会使用此替换项。

应用可以如何达成与替换项相同的结果

请参见OVERRIDE_ANY_ORIENTATION

如何优化应用

请参见OVERRIDE_ANY_ORIENTATION

如何停用替换项

请参见OVERRIDE_ANY_ORIENTATION

用于调整替换项的属性标志

请参见OVERRIDE_ANY_ORIENTATION

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE

为软件包中的所有 activity 启用 reverseLandscape 屏幕方向。除非已启用 OVERRIDE_ANY_ORIENTATION,否则只有当 activity 未指定其他固定屏幕方向时,系统才会使用此替换项。

应用可以如何达成与替换项相同的结果

请参见OVERRIDE_ANY_ORIENTATION

如何优化应用

请参见OVERRIDE_ANY_ORIENTATION

如何停用替换项

请参见OVERRIDE_ANY_ORIENTATION

用于调整替换项的属性标志

请参见OVERRIDE_ANY_ORIENTATION

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA

OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAITOVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOROVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE 替换项限制为仅在相机连接处于有效状态时生效。

应用可以如何达成与替换项相同的结果

请参见OVERRIDE_ANY_ORIENTATION

如何优化应用

请参见OVERRIDE_ANY_ORIENTATION

如何停用替换项

请参见OVERRIDE_ANY_ORIENTATION

用于调整替换项的属性标志

请参见OVERRIDE_ANY_ORIENTATION

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION

当满足以下条件时,将显示屏方向限制为横向自然方向:

  • activity 处于全屏模式
  • 未启用选择停用组件的属性 PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE
  • 已针对显示屏启用设备制造商忽略屏幕方向请求设置
  • 显示屏的自然屏幕方向为横向

应用可以如何达成与替换项相同的结果

不适用。此问题应该在应用逻辑中解决。

如何优化应用

请参见OVERRIDE_ANY_ORIENTATION

如何停用替换项

将属性标志 PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE 设置为 false

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE"
  android:value="true|false"/>

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION

启用以下兼容性政策:在应用重新启动或在执行相机兼容性处理时,为响应应用调用 Activity#setRequestedOrientation() 而跳过应用屏幕方向更新。

应用可以如何达成与替换项相同的结果

将属性标志 PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION 设置为 true

如何优化应用

请参见OVERRIDE_ANY_ORIENTATION

如何停用替换项

将属性标志 PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION 设置为 false

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION"
  android:value="true|false"/>

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED

启用以下兼容性政策:当 activity 未针对固定屏幕方向进入信箱模式时,忽略应用请求的屏幕方向,以响应应用在一秒内调用 Activity#setRequestedOrientation() 两次以上的情况。

应用可以如何达成与替换项相同的结果

不适用。此问题应该在应用逻辑中解决。

如何优化应用

请参见OVERRIDE_ANY_ORIENTATION

如何停用替换项

将属性标志 PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED 设置为 false

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED"
  android:value="false"/>

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_RESPECT_REQUESTED_ORIENTATION

从设备制造商可为显示区域或整个显示屏启用的忽略屏幕方向请求行为中,排除相应软件包。

应用可以如何达成与替换项相同的结果

不适用。此问题应该在应用逻辑中解决。

如何优化应用

请参见OVERRIDE_ANY_ORIENTATION

如何停用替换项

无法选择停用。如果应用与已启用设备制造商忽略屏幕方向请求设置的设备不兼容,停用此替换项可能会有危险。如需停用此替换项,请与 Android 开发者关系团队联系。

用于调整替换项的属性标志

此替换项没有属性标志。

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_RESPECT_REQUESTED_ORIENTATION <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_RESPECT_REQUESTED_ORIENTATION <package>

注意:这些命令只能暂时应用或移除此替换项。

NEVER_SANDBOX_DISPLAY_APIS

强制使软件包从不针对进入信箱模式或尺寸兼容模式的 activity 采用 Display API 沙盒。Display API 会继续提供显示区域边界。

应用可以如何达成与替换项相同的结果

android:resizeableActivity 清单属性设置为 true 或将 android.supports_size_changes 元数据标志设置为 true,以便声明 activity 可调整大小。

如何优化应用

声明完全可调整大小的应用绝不应该依赖显示大小来确定界面元素的位置。请将您的应用迁移到提供 WindowMetrics 的最新 API。如果您使用的是 Jetpack Compose,您可以利用 WindowSizeClass API,根据应用在当前显示屏上可用的屏幕区域大小来绘制界面。请参阅使用窗口大小类别

如何停用替换项

无法选择停用。从已废弃的 API 迁移。

用于调整替换项的属性标志

此替换项没有属性标志。

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable NEVER_SANDBOX_DISPLAY_APIS <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable NEVER_SANDBOX_DISPLAY_APIS <package>

注意:这些命令只能暂时应用或移除此替换项。

ALWAYS_SANDBOX_DISPLAY_APIS

强制使软件包始终应用 Display API 沙盒(无论采用哪种窗口模式)。Display API 始终提供应用边界。

应用可以如何达成与替换项相同的结果

android:resizeableActivity 属性设置为 false 或将 android.supports_size_changes 元数据标志设置为 false,以声明 activity 不可调整大小。

如何优化应用

声明完全可调整大小的应用绝不应该依赖显示大小来确定界面元素的位置。将您的应用从已废弃的 API 迁移到提供 WindowMetrics 的最新 API。请参阅 WindowMetricsCalculator

如何停用替换项

无法选择停用。从已废弃的 API 迁移。

用于调整替换项的属性标志

此替换项没有属性标志。

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable ALWAYS_SANDBOX_DISPLAY_APIS <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable ALWAYS_SANDBOX_DISPLAY_APIS <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS

针对 activity 边界,强制使软件包采用以下 View API 沙盒机制:

应用可以如何达成与替换项相同的结果

使用会提供应用窗口边界及相对于应用窗口的偏移量(而不是设备显示屏边界及相对于设备显示屏的偏移量)的 API,以便解决应用代码中的问题。

如何优化应用

应用应使用 View API,并考虑到为应用采用信箱模式和多窗口模式的可能性。请参阅 WindowMetricsCalculator

如何停用替换项

将属性标志 PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS 设置为 false

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS"
  android:value="false"/>

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION

停用强制旋转。改进某些应用的用户体验。

应用可以如何达成与替换项相同的结果

将属性标志 PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION 设置为 false

如何优化应用

请勿依赖缓存的摄像头传感器方向或设备信息。有关相机兼容性指南,请参阅相机取景器简介在相机应用中支持可调整大小的 Surface

如何停用替换项

将属性标志 PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION 设置为 true

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION"
  android:value="true|false"/>

用于测试替换项的 adb 命令

如需应用此替换项(这会移除强制旋转),请使用以下命令:

adb shell am compat enable OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION <package>

如需移除此替换项(这会允许强制旋转),请使用以下命令:

adb shell am compat disable OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_CAMERA_COMPAT_DISABLE_SIMULATE_REQUESTED_ORIENTATION

针对相机停用模拟所请求的屏幕方向处理。改进某些应用的用户体验。

应用可以如何达成与替换项相同的结果

将属性标志 PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION 设置为 false

如何优化应用

请勿依赖缓存的摄像头传感器方向或设备信息。有关相机兼容性指南,请参阅相机取景器简介在相机应用中支持可调整大小的 Surface

如何停用替换项

由于此属性会停用兼容性处理,因此您可以考虑动态显示旋转变化、设备的传感器方向以及窗口和预览大小,从而改善用户体验。

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION"
  android:value="true|false"/>

用于测试替换项的 adb 命令

如需应用此替换项(这会移除模拟请求的屏幕方向),请使用以下命令:

adb shell am compat enable OVERRIDE_CAMERA_COMPAT_DISABLE_SIMULATE_REQUESTED_ORIENTATION <package>

如需移除此替换项(这会允许模拟所请求的屏幕方向),请使用以下命令:

adb shell am compat disable OVERRIDE_CAMERA_COMPAT_DISABLE_SIMULATE_REQUESTED_ORIENTATION <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH

停用强制旋转后的 activity 刷新。改进当刷新导致应用中的状态丢失时应用中的用户体验。

应用可以如何达成与替换项相同的结果

将属性标志 PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH 设置为 false

如何优化应用

请参阅 OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION

如何停用替换项

将属性标志 PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH 设置为 true

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH"
  android:value="true|false"/>

用于测试替换项的 adb 命令

如需应用此替换项(这会移除 activity 刷新),请使用以下命令:

adb shell am compat enable OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH <package>

如需移除此替换项(这会允许 activity 刷新),请使用以下命令:

adb shell am compat disable OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE

在相机兼容性强制旋转后,让应用此替换项的软件包使用 onResume()onPause()onResume() 循环(而不是 onResume()onStop()onResume())执行 activity 刷新。

应用可以如何达成与替换项相同的结果

将属性标志 PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE 设置为 true

如何优化应用

请参阅 OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION

如何停用替换项

将属性标志 PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE 设置为 false

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE"
  android:value="true|false"/>

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT

当相机的纵向方向与设备自然屏幕方向不一致时,强制将相机输出画面剪裁为相反方向的画面。许多应用���不会处理这种情况,而是显示经过拉伸的图像。

应用可以如何达成与替换项相同的结果

将属性标志 PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT 设置为 true

如何优化应用

请参阅 OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION

如何停用替换项

将属性标志 PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT 设置为 false

用于调整替换项的属性标志

<property android:name="android.camera.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT"
  android:value="true|false"/>

用于测试替换项的 adb 命令

如需应用此替换项(这会应用内部前置摄像头画面剪裁),请使用以下命令:

adb shell am compat enable OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT <package>

如需移除此替换项(这会移除内部前置摄像头画面剪裁),请使用以下命令:

adb shell am compat disable OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION

防止应用选择不进行应用屏幕共享(请参阅媒体投影)。当应用滥用 createConfigForDefaultDisplay() API 强制进行全屏捕获,并通过公开通知内容来危害用户隐私时,系统会实施此限制。这些通知内容是通过全屏捕获(而非应用屏幕共享)捕获的,并且适用于所有应用,无论窗口模式如何。

应用可以如何达成与替换项相同的结果

允许默认媒体投影行为(在 Android 14(API 级别 34)中通过 createScreenCaptureIntent() 实现),使用户能够决定是共享全屏还是单个应用窗口,无论窗口模式如何。或者,使用从对 createConfigForUserChoice() 的调用返回的 MediaProjectionConfig 实参来调用 createScreenCaptureIntent(MediaProjectionConfig)

如何优化应用

允许用户在媒体投影期间选择是共享整个设备显示屏还是应用窗口,这是 Android 14 的默认行为。

使应用可调整大小 (resizeableActivity="true"),以支持多窗口模式。

如何停用替换项

鉴于用户隐私权的重要性,您的应用无法停用或选择不使用此替换功能。

用于调整替换项的属性标志

无。

用于测试替换项的 adb 命令

如需应用此替换项(这会取消应用对局部屏幕共享的选择退出,即启用局部屏幕共享),请使用以下命令:

adb shell am compat enable OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION <package>

如需移除此替换项(这会允许应用选择不进行部分屏幕共享),请使用以下命令:

adb shell am compat disable OVERRIDE_DISABLE_MEDIA_PROJECTION_SINGLE_APP_OPTION <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS

分屏模式下允许针对未获焦点的应用发送虚假焦点。有些游戏引擎会等待获得焦点,然后再绘制应用内容;因此,虚假焦点有助于应用在恢复运行但尚未获得焦点时避免保持黑屏状态。

应用可以如何达成与替换项相同的结果

将属性标志 PROPERTY_COMPAT_ENABLE_FAKE_FOCUS 设置为 true

如何优化应用

如果您的应用会妥善处理多个屏幕方向和配置更改,您可以避免此问题。请遵循大屏设备应用质量指南,让您的应用支持大屏设备。

如果您运行的是 Unity 游戏引擎,请升级到版本 2019.4.40 或更高版本,然后重新导出游戏。在 Android Player 设置中使可调整大小的窗口选项保持选中状态。

如何停用替换项

将属性标志 PROPERTY_COMPAT_ENABLE_FAKE_FOCUS 设置为 false

用于调整替换项的属性标志

<property android:name="android.window.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS"
  android:value="true|false"/>

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS <package>

注意:这些命令只能暂时应用或移除此替换项。

OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS

启用替换后,activity 会收到与标题栏边衬区耦合的配置。通常,标题栏边衬区与配置分离。

应用可以如何达成与替换项相同的结果

启用全屏显示或将应用的目标 SDK 更新为 API 级别 35 或更高版本。请参阅以下内容:

如何优化应用

如果您的应用启用了全屏显示或以 API 级别 35 或更高级别为目标平台,则可以避免此问题。

如何停用替换项

启用无边框显示或以 API 级别 35 或更高级别为目标平台。

用于调整替换项的属性标志

无。

用于测试替换项的 adb 命令

如需应用此替换项,请使用以下命令:

adb shell am compat enable OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS <package>

如需移除此替换项,请使用以下命令:

adb shell am compat disable OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS <package>

注意:这些命令只能暂时应用或移除此替换项。

其他资源


  1. 虚拟设备所有者是管理虚拟设备的受信任应用或特权应用。虚拟设备所有者创建虚拟设备以渲染应用,然后将应用投影到远程设备,例如个人计算机、虚拟现实设备或车载信息娱乐系统。虚拟设备所有者使用的是本地设备,例如手机。