Рекомендации

Приложения для складных и многоэкранных устройств

Как правило, приложения не должны полагаться на статические идентификаторы или логику, зависящую от некоторых идентификаторов дисплеев. В большинстве случаев приложения должны изменять размер и работать на разных дисплеях, а система должна контролировать расположение приложений. Например, для создания нового уникального опыта работы со складными устройствами и запуска специального приложения на внешнем экране при складывании устройства.

В этом случае SystemUI (или другой системный компонент) должен обнаружить свёртку, определить, целесообразно ли выполнить действие, а затем запустить целевое действие и указать идентификатор внешнего дисплея в качестве цели запуска. Приложения не должны обнаруживать это действие или выполнять какие-либо ответные действия, а затем запускать приложение на определённом дисплее. Другими словами, не следует предполагать, что то, что работает на одном устройстве, будет работать и на других. Короче говоря, код, специфичный для устройства, увеличивает фрагментацию.

Ограничить доступ к дисплеям

Если конфигурация устройства требует ограничения доступа к одному или нескольким дисплеям, рекомендуется использовать флаг Display#FLAG_PRIVATE для обозначения таких дисплеев как закрытых . Это запрещает всем, кроме владельца, добавлять контент на дисплей. Любая попытка запустить действие или добавить окно кем-либо, кроме владельца, приводит к исключению SecurityException . Если дисплей принадлежит системе, она может добавлять окна и запускать действия.

Кроме того, сущности, размещённые на дисплее, всегда имеют к нему доступ. Если владелец запускает действие на дисплее, это действие может запустить другие действия на этом дисплее. В результате владелец несёт ответственность за ограничение доступа и разрешение доступа только доверенным приложениям.

Кроме того, на виртуальные дисплеи накладываются дополнительные ограничения, поскольку любое приложение может создать виртуальный дисплей, не делая его видимым для пользователя. Если виртуальный дисплей не принадлежит системе, разрешены только действия с allowEmbedded , а вызывающий должен иметь разрешение ACTIVITY_EMBEDDING .

Более подробную информацию см.:

  • ActivityStackSupervisor#isCallerAllowedToLaunchOnDisplay()
  • ActivityDisplay#isUidPresent()
  • DisplayManagerService#isUidPresentOnDisplay()

Для условного управления запуском активности используйте LaunchParamsController , который перехватывает все запуски активности и позволяет системному компоненту изменять параметры, используемые для запуска. Эта функция доступна в system_server .

Настройте параметры отображения окон и системные украшения

Системные настройки можно настроить для каждого дисплея в DisplayWindowSettings . Реализация устройства может предоставить конфигурацию по умолчанию в /data/system/display_settings.xml .

Это значение определяет, отображаются ли на дисплее системные элементы оформления (панель запуска, обои, панель навигации и другие элементы оформления окон), а также редактор метода ввода (IME). Подробнее см. в разделах DisplayWindowSettings#shouldShowSystemDecorsLocked() и DisplayWindowSettings#shouldShowImeLocked() .

Для идентификации дисплея используйте уникальный идентификатор (по умолчанию используется DisplayInfo#uniqueId ) или идентификатор физического порта для аппаратных дисплеев (см. 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>

Подробности см. в разделе Статические идентификаторы отображения .

Более подробную информацию см.: