일반적으로 앱은 일부 디스플레이 ID에 종속되는 정적 식별자나 논리에 의존하면 안 됩니다. 대부분의 경우 앱은 크기가 변경되어야 하고 여러 디스플레이에서 작동해야 하며 시스템은 앱을 어디서 찾아야 할지 제어해야 합니다. 폴더블 기기를 위한 새롭고 고유한 환경을 빌드하고 기기가 접혔을 때 외부 화면에 특수 앱을 실행해야 하는 경우를 예로 들 수 있습니다.
이 경우 SystemUI 또는 다른 시스템 구성요소는 접힘을 감지하고 작업을 수행해도 괜찮은지 판단한 다음 타겟 활동을 실행하고 외부 디스플레이 ID를 실행 타겟으로 지정해야 합니다.
앱은 이에 대한 반응으로 이 작업을 감지하거나 어떠한 작업도 수행하면 안 되며, 이어서 구체적인 디스플레이에서 실행 작업을 수행해도 안 됩니다. 즉, 기기에서 작동하는 작업이 다른 기기에서도 작동할 것이라고 가정하면 안 됩니다. 간단히 말해 기기별 코드는 세분화 증가로 이어집니다.
디스플레이에 대한 액세스 제한
기기 구성에서 1개 이상의 디스플레이에 대한 액세스 제한을 요구하는 경우에는 Display#FLAG_PRIVATE 플래그를 사용하여 이러한 디스플레이를 비공개로 지정하는 것이 좋습니다. 이렇게 하면 소유자를 제외한 누구도 디스플레이에 콘텐츠를 추가할 수 없도록 제한됩니다. 소유자를 제외한 누군가가 활동을 실행하거나 창을 추가하려고 시도할 경우 SecurityException이 발생합니다.
시스템에서 디스플레이를 소유한 경우 시스템은 창을 추가하고 활동을 실행할 수 있습니다.
또한 디스플레이에 삽입된 항목은 항상 해당 디스플레이에 액세스할 수 있습니다.
소유자가 디스플레이에서 활동을 실행하면 활동은 이 디스플레이에서 다른 활동을 실행할 수 있습니다. 결과적으로는 소유자가 액세스를 제한하고 신뢰할 수 있는 앱만 허용해야 합니다.
또한 모든 앱에서 사용자에게 표시되지 않는 제한사항을 생성할 수 있으므로 가상 디스플레이에 추가적인 제한사항을 더해야 합니다. 가상 디스플레이에서 시스템을 소유하지 않는 경우에는 allowEmbedded를 포함하는 활동만 허용되며, 호출자는 ACTIVITY_EMBEDDING 권한을 보유해야 합니다.
활동 실행을 조건부로 제어하려면 모든 활동 실행을 가로채고 시스템 구성요소가 실행에 사용된 매개변수를 수정할 수 있도록 허용하는 LaunchParamsController를 사용해야 합니다. 이는 system_server에서 사용할 수 있습니다.
디스플레이 창 지정 설정 및 시스템 장식
시스템 장식은 DisplayWindowSettings의 디스플레이마다 구성할 수 있습니다. 기기 구현은 /data/system/display_settings.xml에서 기본 구성을 제공할 수 있습니다.
이 값은 시스템 장식(런처, 배경화면, 탐색 메뉴 및 기타 장식 창)과 IME를 디스플레이에 표시할지 결정합니다.
자세한 내용은 DisplayWindowSettings#shouldShowSystemDecorsLocked() 및 DisplayWindowSettings#shouldShowImeLocked()를 참조하세요.
디스플레이를 식별하려면 고유 ID(기본적으로 DisplayInfo#uniqueId를 사용) 또는 하드웨어 디스플레이의 실제 ID를 사용하세요(DisplayInfo#address 참조).
예를 들어 다음 디스플레이 구성 예시는 시스템 장식 및 IME를 시뮬레이션된 디스플레이에 사용 설정합니다.
위의 예시에서는 이름 속성의 디스플레이 식별을 위해 uniqueId이 사용되었으며, 시뮬레이션된 디스플레이에서는 overlay:1입니다.
내장형 디스플레이의 경우에는 샘플 값이 "local:45354385242535243453"일 수 있습니다.
또 다른 옵션은 하드웨어 포트 정보를 사용하고 identifier="1"이 DisplayWindowSettings#IDENTIFIER_PORT와 일치하도록 설정한 다음 이름이 "port:<port_id>" 형식을 사용하도록 업데이트하는 것입니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-07-27(UTC)"],[],[],null,["# Recommended practices\n\nApps for foldable and multi-screen devices\n------------------------------------------\n\nGenerally, apps should not rely on static identifiers or logic that depends on\nsome display IDs. In most cases, apps should resize and work on different displays\nand the system should control where to locate apps. For example, to build a\nnew and unique experience for foldable devices and launch a special app on the\nexternal screen when the device is folded.\n\nIn this case, SystemUI (or another system component) should detect the\nfold, determine if it's appropriate to perform an action, and then launch the\ntarget activity and specify an external display ID as the launch target.\n\nApps shouldn't detect this action or perform any action in response and then\nperform the launch on a specific display. In other words, do not assume that\nwhat works on one device will work on other devices. In short, device-specific\ncode increases fragmentation.\n\nRestrict access to displays\n---------------------------\n\nIf the device configuration requires the restriction of access to one or more\ndisplays, the recommendation is to use the `Display#FLAG_PRIVATE` flag\nto designate such displays as *private* . Doing so restricts all but the\nowner from adding content to the display. Any attempt to launch an activity or to\nadd a window by anyone but the owner results in a `SecurityException`.\nIf the system owns the display, the system can add windows and launch activities.\n\nIn addition, entities placed on a display can always access that display.\nIf the owner launches an activity on a display, then the activity can launch other\nactivities on this display. As a result, the owner is responsible for restricting\naccess and allowing trusted apps *only*.\n\nIn addition, more restrictions are added to virtual displays because any app can\ncreate one without making it visible to the user. If the virtual display isn't\nowned by the system, then only activities with\n[allowEmbedded](https://developer.android.com/guide/topics/manifest/activity-element#embedded)\nare permitted and the caller should have the `ACTIVITY_EMBEDDING`\npermission.\n\nFor more information, see:\n\n- `ActivityStackSupervisor#isCallerAllowedToLaunchOnDisplay()`\n- `ActivityDisplay#isUidPresent()`\n- `DisplayManagerService#isUidPresentOnDisplay()`\n\nTo conditionally control activity launches, use `LaunchParamsController`,\nwhich intercepts all activity launches and allows a system component to modify the\nparameters used for launch. This is available in `system_server`.\n\nConfigure display windowing settings and system decorations\n-----------------------------------------------------------\n\n[System decorations](/docs/core/display/multi_display/system-decorations#decorations) can\nbe configured per display in `DisplayWindowSettings`. A device\nimplementation can provide a default configuration in\n`/data/system/display_settings.xml`.\n\nThis value determines whether system decorations (launcher, wallpaper,\nnavigation bar, and other decor windows) and the IME appear on a display.\nFor details, see `DisplayWindowSettings#shouldShowSystemDecorsLocked()`\nand `DisplayWindowSettings#shouldShowImeLocked()`.\n\nTo identify the display, use either a unique ID (this default uses\n`DisplayInfo#uniqueId`) or a physical port ID for hardware\ndisplays (see `DisplayInfo#address`).\n\nFor example, the following display config example enables system decorations and the\nIME on a simulated display: \n\n```text\n\u003c?xml version='1.0' encoding='utf-8' standalone='yes' ?\u003e\n\u003cdisplay-settings\u003e\n\u003cconfig identifier=\"0\" /\u003e\n\u003cdisplay\n name=\"overlay:1\"\n shouldShowSystemDecors=\"true\"\n shouldShowIme=\"true\" /\u003e\n\u003c/display-settings\u003e\n```\n\nIn the example above, `uniqueId` is used for display identification\nin the name attribute, which for a simulated display is `overlay:1`.\nFor a built-in display, a sample value may be `\"local:45354385242535243453\"`.\nAnother option is to use hardware port information and set `identifier=\"1\"`\nto correspond to `DisplayWindowSettings#IDENTIFIER_PORT` and then update the\nname to use the `\"port:\u003cport_id\u003e\"` format: \n\n```text\n\u003c?xmlversion='1.0' encoding='utf-8' standalone='yes' ?\u003e\n\u003cdisplay-settings\u003e\n\u003cconfig identifier=\"1\" /\u003e\n\u003cdisplay\n name=\"port:12345\"\n shouldShowSystemDecors=\"true\"\n shouldShowIme=\"true\" /\u003e\n\u003c/display-settings\u003e\n```\n\nFor details, see [Static display identifiers](/docs/core/display/multi_display/displays#static).\n| **Key Point:** Because some settings are read once per system boot, updating a value at runtime may not take effect until the system is next rebooted. `display_settings.xml` is persisted in the `/data/` directory. A factory wipe can erase this file. Therefore, if a device implementation provides a default configuration in `display_settings.xml`, be sure to provide the configuration before WindowManager is initialized.\n\nFor more information, see:\n\n- [Display window settings](/docs/core/display/multi_display/displays#windows)\n- [Static display identifiers](/docs/core/display/multi_display/displays#static)\n- [System decorations support](/docs/core/display/multi_display/system-decorations)"]]