2025년 3월 27일부터 AOSP를 빌드하고 기여하려면 aosp-main
대신 android-latest-release
를 사용하는 것이 좋습니다. 자세한 내용은 AOSP 변경사항을 참고하세요.
멀티 사용자 인식 앱 빌드
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
기기에서 여러 사용자를 지원하는 경우 앱에서는 이 사용자들을 개별적으로 인식해야합니다.
일부 앱은 싱글톤으로 실행되는 일부 구성요소를 포함해야 하며 어떤 사용자의 요청이든 수락할 수 있습니다. 현재 시스템 앱에서만 이 기능을 사용할 수 있습니다.
이 기능의 특징은 다음과 같습니다.
- 리소스를 절약합니다.
- 사용자 간의 공유 리소스를 하나 이상 조정합니다.
- 단일 서버 연결을 사용하여 네트워크 오버헤드를 줄입니다.
아래의 다이어그램은 여러 사용자와 관련된 권한 흐름을 보여줍니다.
그림 1. 여러 사용자의 권한
싱글톤 구성요소 사용 설정
앱을 싱글톤으로 식별하려면 Android 매니페스트에서 android:singleUser="true"
를 서비스, 받는 사람 또는 공급자에 추가합니다.
시스템은 사용자 0으로만 실행 중인 프로세스에서 이 구성요소를 인스턴스화합니다. 공급자 또는 서비스에 연결하거나 받는 사람에게 브로드캐스트하려는 모든 사용자의 모든 요청은 사용자 0의 프로세스로 라우팅됩니다. 앱의 유일한 구성요소인 경우 앱 인스턴스는 하나만 실행됩니다.
패키지의 활동은 각 사용자의 개별 프로세스에서 사용자의 UID 범위에 속하는 UID (예: 1010034)를 사용하여 시작됩니다.
사용자와 상호작용
권한 설정
다음 권한이 필요합니다.
INTERACT_ACROSS_USERS (signature|system)
INTERACT_ACROSS_USERS_FULL (signature)
API 사용
다음 API를 사용하여 앱에서 여러 사용자를 인식하도록 합니다.
- 수신되는 바인더 호출에서 사용자 핸들을 추출합니다.
int userHandle = UserHandle.getCallingUserId()
- 보호되는 새 API를 사용하여 특정 사용자에 관해 서비스, 활동, 브로드캐스트를 시작합니다.
Context.startActivityAsUser(Intent, UserHandle)
Context.bindServiceAsUser(Intent, …, UserHandle)
Context.sendBroadcastAsUser(Intent, … , UserHandle)
Context.startServiceAsUser(Intent, …, UserHandle)
UserHandle
은 명시적 사용자 또는 특수 핸들 중 하나(UserHandle.CURRENT
또는 UserHandle.ALL
)일 수 있습니다. CURRENT
는 현재 포그라운드에 있는 사용자를 나타냅니다. 모든 사용자에게 브로드캐스트를 보내려면 ALL
을 사용합니다.
- 자체 앱의 구성요소와 통신합니다(
(INTERACT_ACROSS_USERS)
). 아니면 다른 앱의 구성요소와 통신합니다((INTERACT_ACROSS_USERS_FULL)
).
- 사용자 프로세스에서 실행되고 사용자 0의
singleUser
구성요소에 액세스하는 프록시 구성요소를 만들어야 할 수 있습니다.
- 새
UserManager
시스템 서비스로 사용자 및 그 핸들을 쿼리합니다.UserManager.getUsers()
UserManager.getUserInfo()
UserManager.supportsMultipleUsers()
UserManager.getUserSerialNumber(int userHandle)
- 사용자 핸들에 상응하는 재활용되지 않은 숫자입니다.
UserManager.getUserHandle(int serialNumber)
UserManager.getUserProfiles()
- 자체 및 관리 프로필의 컬렉션이 있는 경우 이를 반환합니다.
- 콜백을 일으킨 사용자에 관한 추가 정보를 제공하는 ContentObserver, PackageMonitor, BroadcastReceiver의 새 API를 사용하여 모든 또는 특정한 사용자와 콜백을 수신하도록 등록합니다.
여러 사용자 또는 프로필의 서비스
모든 서비스가 다른 사용자 또는 직장 프로필에서 인스턴스를 실행해야 하는 것은 아닙니다. 시스템 서비스가 사용자 0으로만 실행해야 하는 경우, 다른 사용자로 실행할 때는 서비스 구성요소를 사용 중지하여 리소스를 보존합니다. 다음 예는 서비스 진입점에서 이를 실행할 방법을 보여줍니다.
// Add on all entry points such as boot_completed or other manifest-listed receivers and providers
if (!UserManager.isSystemUser()) {
// Disable the service
ComponentName targetServiceName = new ComponentName(this, TargetService.class);
context.getPackageManager().setComponentEnabledSetting(
targetServiceName, COMPONENT_ENABLED_STATE_DISABLED, 0);
}
이 예에서는 PackageManager.setApplicationEnabledSetting()
을 사용하여 전체 앱을 사용 중지할 수도 있습니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 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,["# Build multiuser-aware apps\n\nWhen a device supports [multiple users](/docs/devices/admin/multi-user), its apps must be\nmade aware of these distinct users.\n\nCertain apps need to have some components run as singletons and can accept\nrequests from any user. Only system apps can currently use this feature.\n\nThis facility:\n\n- Conserves resources\n- Arbitrates one or more shared resources across users\n- Reduces network overhead by using a single server connection\n\nSee the diagram below for a depiction of permissions flow with multiple users.\n\n\n**Figure 1.** Multiple users permissions\n\nEnable a singleton component\n----------------------------\n\nTo identify an app as a singleton, add `android:singleUser=\"true\"` to your service,\nreceiver, or provider in the Android manifest.\n\nThe system instantiates that component in the process running as user 0\nonly. Any requests to connect to that provider or service, or to broadcast to that receiver, from\nany user is routed to the process in user 0. If this is the only component in your app,\nonly one instance of your app runs.\n\nActivities in your package are still launched in a separate process for\neach user, with the UID being in the UID range for that user (such as 1010034).\n\nInteract with users\n-------------------\n\n### Set permissions\n\nThese permissions are required: \n\n```\nINTERACT_ACROSS_USERS (signature|system)\nINTERACT_ACROSS_USERS_FULL (signature)\n```\n\n### Employ APIs\n\nUse the following APIs to make apps aware of multiple users.\n\n1. Extract the user handle from incoming Binder calls:\n - `int userHandle = UserHandle.getCallingUserId()`\n2. Use new, protected APIs to start services, activities, broadcasts on a specific user:\n - `Context.startActivityAsUser(Intent, UserHandle)`\n - `Context.bindServiceAsUser(Intent, ..., UserHandle)`\n - `Context.sendBroadcastAsUser(Intent, ... , UserHandle)`\n - `Context.startServiceAsUser(Intent, ..., UserHandle)`\n\n `UserHandle` can be an explicit user or one of the special handles: `UserHandle.CURRENT` or `UserHandle.ALL`. `CURRENT` indicates the user that is currently in the foreground. Use `ALL` when you want to send a broadcast to all users.\n3. Communicate with components in your own app: `(INTERACT_ACROSS_USERS)` Or with components in other apps: `(INTERACT_ACROSS_USERS_FULL)`\n4. You might need to create proxy components that run in the user's process that then access the `singleUser` component in user 0.\n5. Query users and their handles with the new `UserManager` system service:\n - `UserManager.getUsers()`\n - `UserManager.getUserInfo()`\n - `UserManager.supportsMultipleUsers()`\n - `UserManager.getUserSerialNumber(int userHandle)` - a nonrecycled number that corresponds to a user handle.\n - `UserManager.getUserHandle(int serialNumber)`\n - `UserManager.getUserProfiles()` - returns the collection of self and managed profiles, if any.\n6. Register to listen to specific or all users and the callbacks with new APIs on ContentObserver, PackageMonitor, BroadcastReceiver that provide additional information about which user has caused the callback.\n\n### Services in multiple users or profiles\n\nNot all services need to run an instance in another user or work profile. If your system service\nonly needs to run as user 0, disable the service's components when running under other users to\nhelp preserve resources. The following example shows how you might do this at your service's entry\npoints: \n\n```\n// Add on all entry points such as boot_completed or other manifest-listed receivers and providers\nif (!UserManager.isSystemUser()) {\n // Disable the service\n ComponentName targetServiceName = new ComponentName(this, TargetService.class);\n context.getPackageManager().setComponentEnabledSetting(\n targetServiceName, COMPONENT_ENABLED_STATE_DISABLED, 0);\n}\n```\n\nThe example could also use `PackageManager.setApplicationEnabledSetting()` to disable\nthe entire app."]]