适用于可折叠设备和多屏幕设备的应用
一般来说,应用不应依赖静态标识符或依赖于某些显示屏 ID 的逻辑。在大多数情况下,应用应调整大小并在不同的显示屏上运行,而系统应控制应用的位置。例如,为可折叠设备构建全新的独特体验,并在设备折叠时在外屏上启动特殊应用。
在这种情况下,SystemUI(或其他系统组件)应检测折叠,确定是否适合执行操作,然后启动目标 Activity 并将外屏显示屏 ID 指定为启动目标。应用不应检测到此操作或做出任何响应,然后执行在特定显示屏上启动的操作。换句话说,不要假设在一个设备上有效的功能在其他设备上也能有效。简而言之,设备专用代码会增加碎片化。
限制对显示屏的访问权限
如果设备配置要求限制对一个或多个显示屏的访问权限,建议使用 Display#FLAG_PRIVATE
标志将此类显示屏指定为专用。这样做会限制除所有者之外的所有人向显示屏添加内容。除所有者之外的任何人尝试启动 Activity 或添加窗口都会导致 SecurityException
。如果系统拥有显示屏,则系统可以添加窗口和启动 Activity。
此外,放置在显示屏上的实体始终可以访问该显示屏。如果所有者在显示屏上启动一个 Activity,则该 Activity 可以在此显示屏上启动其他 Activity。因此,所有者有责任限制访问权限,并且仅允许受信任的应用。
此外,虚拟显示屏添加了更多限制,因为任何应用都可以在不向用户显示的情况下创建一个虚拟显示屏。如果虚拟显示屏不归系统所有,则只允许使用 allowEmbedded
的 Activity,并且调用者应具有 ACTIVITY_EMBEDDING
权限。
有关详细信息,请参阅
ActivityStackSupervisor#isCallerAllowedToLaunchOnDisplay()
ActivityDisplay#isUidPresent()
DisplayManagerService#isUidPresentOnDisplay()
要有条件地控制 Activity 启动,请使用 LaunchParamsController
,它会拦截所有 Activity 启动,并允许系统组件修改用于启动的参数。这在 system_server
中可用。
配置显示窗口设置和系统装饰
系统装饰 可以在 DisplayWindowSettings
中按显示屏配置。设备实现可以在 /data/system/display_settings.xml
中提供默认配置。
此值确定系统装饰(启动器、壁纸、导航栏和其他装饰窗口)和 IME 是否显示在显示屏上。有关详细信息,请参阅 DisplayWindowSettings#shouldShowSystemDecorsLocked()
和 DisplayWindowSettings#shouldShowImeLocked()
。
要标识显示屏,请使用唯一 ID(此默认值使用 DisplayInfo#uniqueId
)或硬件显示屏的物理端口 ID(请参阅 DisplayInfo#address
)。
例如,以下显示配置示例在模拟显示屏上启用系统装饰和 IME
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <display-settings> <config identifier="0" /> <display name="overlay:1" shouldShowSystemDecors="true" shouldShowIme="true" /> </display-settings>
在上面的示例中,uniqueId
用于 name 属性中的显示屏标识,对于模拟显示屏,它是 overlay:1
。对于内置显示屏,示例值可能是 "local:45354385242535243453"
。另一种选择是使用硬件端口信息并将 identifier="1"
设置为对应于 DisplayWindowSettings#IDENTIFIER_PORT
,然后更新名称以使用 "port:<port_id>"
格式
<?xmlversion='1.0' encoding='utf-8' standalone='yes' ?> <display-settings> <config identifier="1" /> <display name="port:12345" shouldShowSystemDecors="true" shouldShowIme="true" /> </display-settings>
有关详细信息,请参阅 静态显示屏标识符。
有关详细信息,请参阅