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

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

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

В этом случае 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 используется для идентификации отображения в атрибуте имени, который для имитируемого отображения имеет 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>

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

Для получения дополнительной информации см.: