여러 사용자 관리하기

이 개발자 가이드에서는 기기 정책 컨트롤러 (DPC)가 어떻게 작동하는지 설명합니다. 전용 기기에서 여러 Android 사용자를 관리합니다.

개요

DPC를 통해 여러 사용자가 하나의 전용 기기를 공유할 수 있습니다. DPC 완전 관리형 기기에서 실행하는 경우 두 가지 유형의 사용자를 생성하고 관리할 수 있습니다.

  • 보조 사용자는 별도의 앱과 데이터가 저장된 Android 사용자입니다. 세션 간 관리자는 관리자 구성요소를 사용하여 사용자를 관리합니다. 이러한 사용자는 교대 근무 시작 시 기기를 픽업하는 경우에 유용합니다 배달 기사나 보안 인력이 필요할 수 있습니다
  • 임시 사용자는 사용자가 작업을 수행할 때 시스템에서 삭제하는 보조 사용자입니다. 기기가 중지되거나 스위치가 꺼지거나 기기가 재부팅될 수 있습니다. 이러한 사용자는 케이스가 세션이 완료된 후 데이터를 삭제할 수 있는 위치(예: 공개 액세스) 인터넷 키오스크 등입니다.
를 통해 개인정보처리방침을 정의할 수 있습니다.

기존 DPC를 사용하여 전용 기기와 보조 기기를 관리합니다. 있습니다. DPC의 관리자 구성요소가 새 보조의 관리자로 자체적으로 설정됨 사용자를 만들 때 액세스할 수 있어야 합니다

기본 사용자 및 보조 사용자 2명
그림 1. 관리자가 관리하는 기본 및 보조 사용자 동일한 DPC
를 통해 개인정보처리방침을 정의할 수 있습니다.

보조 사용자의 관리자는 완전 관리형 기기입니다 개발을 간소화하려면 관리자를 공유하는 것이 좋습니다. 통신합니다.

전용 기기에서 여러 사용자를 관리하려면 일반적으로 Android 9.0 이 개발자 가이드에 사용된 방법 중 일부는 최신 버전의 Android를 사용할 수 있습니다

보조 사용자

보조 사용자는 Wi-Fi에 연결하고 새 네트워크를 구성할 수 있습니다. 그러나 네트워크를 수정하거나 삭제할 수는 없습니다.

사용자 만들기

DPC는 백그라운드에서 추가 사용자를 생성한 다음 전환할 수 있습니다. 포그라운드로 전환할 수 있습니다 이 프로세스는 보조 및 학습 과정 모두에서 거의 동일합니다. 액세스할 수 있습니다 전체 권한의 관리자에서 다음 단계를 구현합니다. 관리 기기 및 보조 사용자:

  1. DevicePolicyManager.createAndManageUser()을 호출합니다. 임시 사용자를 만들려면 다음을 포함합니다. 플래그 인수의 MAKE_USER_EPHEMERAL
  2. 전화걸기 DevicePolicyManager.startUserInBackground()(으)로 백그라운드에서 사용자를 시작할 수 있습니다. 사용자가 달리기를 시작하지만 설정을 마치고 사용자를 포그라운드로 옮기고 개인 정보를 공유할 수 있습니다.
  3. 보조 사용자의 관리자에서 다음을 호출합니다. DevicePolicyManager.setAffiliationIds()(으)로 신규 사용자를 기본 사용자와 연결합니다. 자세한 내용은 DPC 조정을 참조하세요.
  4. 완전 관리형 기기의 관리자로 돌아가서 다음을 호출합니다. DevicePolicyManager.switchUser(): 사용자를 다음으로 전환합니다. 있습니다.

다음 샘플은 DPC에 1단계를 추가하는 방법을 보여줍니다.

Kotlin

val dpm = getContext().getSystemService(Context.DEVICE_POLICY_SERVICE)
        as DevicePolicyManager

// If possible, reuse an existing affiliation ID across the
// primary user and (later) the ephemeral user.
val identifiers = dpm.getAffiliationIds(adminName)
if (identifiers.isEmpty()) {
    identifiers.add(UUID.randomUUID().toString())
    dpm.setAffiliationIds(adminName, identifiers)
}

// Pass an affiliation ID to the ephemeral user in the admin extras.
val adminExtras = PersistableBundle()
adminExtras.putString(AFFILIATION_ID_KEY, identifiers.first())
// Include any other config for the new user here ...

// Create the ephemeral user, using this component as the admin.
try {
    val ephemeralUser = dpm.createAndManageUser(
            adminName,
            "tmp_user",
            adminName,
            adminExtras,
            DevicePolicyManager.MAKE_USER_EPHEMERAL or
                    DevicePolicyManager.SKIP_SETUP_WIZARD)

} catch (e: UserManager.UserOperationException) {
    if (e.userOperationResult ==
            UserManager.USER_OPERATION_ERROR_MAX_USERS) {
        // Find a way to free up users...
    }
}

자바

DevicePolicyManager dpm = (DevicePolicyManager)
    getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);

// If possible, reuse an existing affiliation ID across the
// primary user and (later) the ephemeral user.
Set<String> identifiers = dpm.getAffiliationIds(adminName);
if (identifiers.isEmpty()) {
  identifiers.add(UUID.randomUUID().toString());
  dpm.setAffiliationIds(adminName, identifiers);
}

// Pass an affiliation ID to the ephemeral user in the admin extras.
PersistableBundle adminExtras = new PersistableBundle();
adminExtras.putString(AFFILIATION_ID_KEY, identifiers.iterator().next());
// Include any other config for the new user here ...

// Create the ephemeral user, using this component as the admin.
try {
  UserHandle ephemeralUser = dpm.createAndManageUser(
      adminName,
      "tmp_user",
      adminName,
      adminExtras,
      DevicePolicyManager.MAKE_USER_EPHEMERAL |
          DevicePolicyManager.SKIP_SETUP_WIZARD);

} catch (UserManager.UserOperationException e) {
  if (e.getUserOperationResult() ==
      UserManager.USER_OPERATION_ERROR_MAX_USERS) {
    // Find a way to free up users...
  }
}

새 사용자를 만들거나 시작할 때 실패 원인을 확인할 수 있습니다. UserOperationException 예외를 포착하고 다음을 호출하여 getUserOperationResult() 사용자 수 초과 한도는 일반적인 실패 원인입니다.

를 통해 개인정보처리방침을 정의할 수 있습니다.

사용자를 만드는 데 다소 시간이 걸릴 수 있습니다. 사용자를 자주 만드는 경우 백그라운드에서 바로 사용자를 준비시켜 사용자 경험을 개선합니다. 즉각적으로 반응하는 사용자의 장점과 기기에서 허용되는 사용자 수

정체성

새 사용자를 만든 후에는 영구 일련번호로 사용자를 안내해야 합니다. 있습니다. UserHandle를 유지하지 않음 사용자를 생성하고 삭제할 수 있습니다 다음을 호출하여 일련번호를 확인 UserManager.getSerialNumberForUser():

Kotlin

// After calling createAndManageUser() use a device-unique serial number
// (that isn’t recycled) to identify the new user.
secondaryUser?.let {
    val userManager = getContext().getSystemService(UserManager::class.java)
    val ephemeralUserId = userManager!!.getSerialNumberForUser(it)
    // Save the serial number to storage  ...
}

자바

// After calling createAndManageUser() use a device-unique serial number
// (that isn’t recycled) to identify the new user.
if (secondaryUser != null) {
  UserManager userManager = getContext().getSystemService(UserManager.class);
  long ephemeralUserId = userManager.getSerialNumberForUser(secondaryUser);
  // Save the serial number to storage  ...
}

사용자 구성

사용자의 필요에 따라 보조 이메일 주소와 있습니다. createAndManageUser()를 호출할 때 다음 플래그를 포함할 수 있습니다.

SKIP_SETUP_WIZARD
업데이트를 확인하고 설치하는 신규 사용자 설정 마법사 실행을 건너뜁니다. 사용자에게 Google 서비스와 함께 Google 계정을 추가하라는 메시지를 표시하고 화면 잠금 다소 시간이 걸릴 수 있으며 일부 사용자에게만 적용될 수 있습니다. 공개 인터넷 키오스크 등을 예로 들 수 있습니다
LEAVE_ALL_SYSTEM_APPS_ENABLED
신규 사용자의 모든 시스템 앱을 사용 설정된 상태로 둡니다. 이 플래그를 설정하지 않으면 새 사용자에게는 휴대전화가 운영합니다. 일반적으로 파일 브라우저, 전화 다이얼러, 연락처 및 SMS 메시지가 있습니다.

사용자 수명 주기 따르기

DPC (완전 관리형 기기의 관리자)가 보조 사용자가 변경되는 시점을 알 수 있습니다. 변경 후 후속 작업을 실행하려면 재정의하세요. DPC의 DeviceAdminReceiver 서브클래스에서 다음 콜백 메서드를 호출합니다.

onUserStarted()
시스템이 사용자를 시작한 후 호출됩니다. 이 사용자가 아직 설정 중이거나 백그라운드에서 실행 중이어야 합니다 startedUser에서 사용자를 가져올 수 있습니다. 인수입니다.
onUserSwitched()
시스템이 다른 사용자로 전환한 후 호출됩니다. 새로운 사용자를 현재 switchedUser 인수의 포그라운드에서 실행되고 있습니다.
onUserStopped()
사용자가 로그아웃했거나 신규 사용자 (사용자가 임시 사용자인 경우)를 확인하거나 DPC가 사용자를 중지했습니다. 얻을 수 있는 혜택 stoppedUser 인수의 사용자.
onUserAdded()
시스템이 신규 사용자를 추가할 때 호출됩니다. 일반적으로 보조 사용자는 DPC가 콜백을 받으면 완전히 설정됩니다. 다음 위치에서 사용자를 가져올 수 있습니다. newUser 인수.
onUserRemoved()
시스템에서 사용자를 삭제한 후 호출됩니다. 사용자가 이미 삭제되었으므로 removedUser 인수로 표시되는 사용자에게 액세스할 수 없습니다.

시스템이 사용자를 포그라운드로 옮기거나 사용자를 백그라운드에서 앱이 실행될 때 ACTION_USER_FOREGROUNDACTION_USER_BACKGROUND 브로드캐스트를 전송합니다.

사용자 찾기

모든 보조 사용자를 가져오려면 완전 관리형 기기의 관리자가 DevicePolicyManager.getSecondaryUsers() 결과 관리자가 만든 모든 보조 또는 임시 사용자가 포함됩니다. 또한 기기 사용자가 사용할 수 있는 보조 사용자 (또는 게스트 사용자)를 포함합니다. 확인할 수 있습니다 직장 프로필은 직장 프로필이 아니므로 검색 결과에 포함되지 않습니다. 설정할 수 있습니다 다음 샘플은 이 메서드를 사용하는 방법을 보여줍니다.

Kotlin

// The device is stored for the night. Stop all running secondary users.
dpm.getSecondaryUsers(adminName).forEach {
    dpm.stopUser(adminName, it)
}

자바

// The device is stored for the night. Stop all running secondary users.
for (UserHandle user : dpm.getSecondaryUsers(adminName)) {
  dpm.stopUser(adminName, user);
}

다음은 보조 사용자의 상태를 확인하기 위해 호출할 수 있는 다른 메서드입니다.

DevicePolicyManager.isEphemeralUser()
보조 사용자의 관리자로부터 이 메서드를 호출하여 사용할 수 있습니다
DevicePolicyManager.isAffiliatedUser()
보조 사용자의 관리자에게 이 메서드를 호출하여 이 사용자가 다음에 해당하는지 확인합니다. 기본 사용자와 연결되어 있습니다 제휴에 관해 자세히 알아보려면 DPC를 참조하세요. 조정을 참조하세요.

사용자 관리

사용자 수명 주기를 완전히 관리하려면 기기가 사용자를 변경하는 시기와 방법을 세밀하게 제어합니다. 예를 들어 사용자가 특정 기간 동안 사용하지 않은 사용자를 삭제하거나 교대 근무가 끝나기 전에 보내지 않은 주문을 서버로 전송

로그아웃

Android 9.0에서는 잠금 화면에 로그아웃 버튼을 추가하여 세션을 종료할 수 있습니다. 버튼을 누르면 시스템이 보조 사용자, 임시 사용자인 경우 해당 사용자를 삭제하고 기본 사용자가 돌아옵니다. 포그라운드로 전환할 수 있습니다 Android에서는 기본 사용자가 기본 사용자가 로그아웃할 수 없기 때문에 포그라운드 상태가 됩니다.

Android에는 기본적으로 종료 세션 버튼이 표시되지 않지만 완전 관리형 기기)을 사용하면 DevicePolicyManager.setLogoutEnabled() 필요한 경우 버튼의 현재 상태를 확인하고 DevicePolicyManager.isLogoutEnabled()

보조 사용자의 관리자는 프로그래매틱 방식으로 사용자를 로그아웃하고 돌아올 수 있습니다. 기본 사용자에게 할당하게 됩니다 먼저 보조 사용자와 기본 사용자가 그런 다음 DevicePolicyManager.logoutUser()를 호출합니다. 만약 로그아웃한 사용자가 임시 사용자인 경우 시스템에서 있습니다.

사용자 전환

다른 보조 사용자로 전환하려면 완전 관리형 기기의 관리자가 다음을 수행할 수 있습니다. DevicePolicyManager.switchUser()를 호출합니다. 편의를 위해 null를 전달하여 기본 사용자로 전환할 수 있습니다.

사용자 중지

완전 관리형 기기를 소유한 DPC는 보조 사용자를 중지하기 위해 다음을 호출할 수 있습니다. DevicePolicyManager.stopUser() 중지된 사용자가 임시 사용자가 사용 중지되면 사용자가 중지되었다가 삭제됩니다.

기기 사용을 유지할 수 있도록 가능한 한 사용자를 차단하는 것이 좋습니다. 지정할 수 있습니다

사용자 삭제

보조 사용자를 영구적으로 삭제하기 위해 DPC는 다음 중 하나를 호출할 수 있습니다. DevicePolicyManager 메서드:

  • 완전 관리형 기기의 관리자는 removeUser()를 호출할 수 있습니다.
  • 보조 사용자의 관리자는 wipeData()를 호출할 수 있습니다.

임시 사용자가 로그아웃, 중지 또는 전환되면 시스템에서 임시 사용자를 삭제합니다. 있습니다.

기본 UI 사용 중지

DPC가 사용자 관리를 위한 UI를 제공하는 경우, Android의 내장 멀티 사용자 인터페이스를 기반으로 빌드되었습니다 이렇게 하려면 DevicePolicyManager.setLogoutEnabled()를 사용하고 DISALLOW_USER_SWITCH 제한사항을 참조하세요. 다음 예를 참고하세요.

Kotlin

// Explicitly disallow logging out using Android UI (disabled by default).
dpm.setLogoutEnabled(adminName, false)

// Disallow switching users in Android's UI. This DPC can still
// call switchUser() to manage users.
dpm.addUserRestriction(adminName, UserManager.DISALLOW_USER_SWITCH)

자바

// Explicitly disallow logging out using Android UI (disabled by default).
dpm.setLogoutEnabled(adminName, false);

// Disallow switching users in Android's UI. This DPC can still
// call switchUser() to manage users.
dpm.addUserRestriction(adminName, UserManager.DISALLOW_USER_SWITCH);

기기 사용자는 Android 내장 UI로 보조 사용자를 추가할 수 없습니다. 완전 관리형 기기의 관리자가 자동으로 DISALLOW_ADD_USER 사용자 제한입니다.

세션 메시지

기기 사용자가 새 사용자로 전환하면 Android는 스위치를 강조 표시합니다. Android에서는 다음 메시지를 표시합니다.

  • 기기가 보조 세션으로 전환될 때 표시되는 시작-사용자 세션 메시지 사용자를 삭제할 수 있습니다
  • 기기가 기본 사용자에게 반환될 때 표시되는 최종 사용자 세션 메시지 액세스하려고 할 때 발생합니다.

두 보조 사용자 간에 전환할 때 시스템에서 메시지를 표시하지 않습니다.

메시지가 일부 상황에 적합하지 않을 수 있으므로 확인할 수 있습니다 예를 들어 솔루션에서 임시 사용자를 사용하는 경우 다음과 같은 메시지에 이를 반영할 수 있습니다. 브라우저 중지 중 세션 및 개인 정보 삭제 중...

시스템은 메시지를 몇 초 동안만 표시하므로 각 메시지는 짧고 명확한 어구여야 합니다 메시지를 맞춤설정하기 위해 관리자는 다음을 호출할 수 있습니다. DevicePolicyManager 메서드 setStartUserSessionMessage()setEndUserSessionMessage() 다음 예를 참고하세요.

Kotlin

// Short, easy-to-read messages shown at the start and end of a session.
// In your app, store these strings in a localizable resource.
internal val START_USER_SESSION_MESSAGE = "Starting guest session"
internal val END_USER_SESSION_MESSAGE = "Stopping & clearing data"

// ...
dpm.setStartUserSessionMessage(adminName, START_USER_SESSION_MESSAGE)
dpm.setEndUserSessionMessage(adminName, END_USER_SESSION_MESSAGE)

자바

// Short, easy-to-read messages shown at the start and end of a session.
// In your app, store these strings in a localizable resource.
private static final String START_USER_SESSION_MESSAGE = "Starting guest session";
private static final String END_USER_SESSION_MESSAGE = "Stopping & clearing data";

// ...
dpm.setStartUserSessionMessage(adminName, START_USER_SESSION_MESSAGE);
dpm.setEndUserSessionMessage(adminName, END_USER_SESSION_MESSAGE);

맞춤 메시지를 삭제하고 Android 기본값으로 돌아가려면 null를 전달합니다. 메시지를 보낼 수 있습니다 현재 메시지 내용을 확인해야 하는 경우 getStartUserSessionMessage() 또는 getEndUserSessionMessage()

DPC에서는 현지화된 메시지를 설정해야 합니다. 사용자의 현재 언어로 변경합니다. 또한 사용자의 언어 변경:

Kotlin

override fun onReceive(context: Context?, intent: Intent?) {
    // Added the <action android:name="android.intent.action.LOCALE_CHANGED" />
    // intent filter for our DeviceAdminReceiver subclass in the app manifest file.
    if (intent?.action === ACTION_LOCALE_CHANGED) {

        // Android's resources return a string suitable for the new locale.
        getManager(context).setStartUserSessionMessage(
                getWho(context),
                context?.getString(R.string.start_user_session_message))

        getManager(context).setEndUserSessionMessage(
                getWho(context),
                context?.getString(R.string.end_user_session_message))
    }
    super.onReceive(context, intent)
}

자바

public void onReceive(Context context, Intent intent) {
  // Added the <action android:name="android.intent.action.LOCALE_CHANGED" />
  // intent filter for our DeviceAdminReceiver subclass in the app manifest file.
  if (intent.getAction().equals(ACTION_LOCALE_CHANGED)) {

    // Android's resources return a string suitable for the new locale.
    getManager(context).setStartUserSessionMessage(
        getWho(context),
        context.getString(R.string.start_user_session_message));

    getManager(context).setEndUserSessionMessage(
        getWho(context),
        context.getString(R.string.end_user_session_message));
  }
  super.onReceive(context, intent);
}

DPC 조정

보조 사용자를 관리하려면 일반적으로 DPC의 두 인스턴스, 즉 완전히 관리되는 기기이고 다른 사용자는 보조 사용자를 소유합니다. 생성 시 완전 관리형 기기의 관리자가 새로운 사용자 인스턴스를 새 사용자의 관리자 역할을 맡습니다

연결된 사용자

이 개발자 가이드의 일부 API는 보조 사용자가 제휴 상태입니다. Android에서 일부 기능을 사용할 수 없기 때문에 (예: 네트워크 로깅), 연결되지 않은 새 보조 사용자를 가능한 한 빨리 사용자를 연결해야 합니다. 다음 예제를 참조하세요. 아래에서 설정을 참조하세요.

설정

이전에 보조 사용자를 소유한 DPC에서 새 보조 사용자를 설정합니다. 사용할 수 있게 하는 것입니다. 이 설정은 DeviceAdminReceiver.onEnabled() 콜백에 전달됩니다. 이전에 호출에서 관리자 추가 권한을 createAndManageUser()로 설정하면 intent 인수의 값을 반환합니다. 다음 예는 다음과 같이 콜백에 새 보조 사용자를 추가합니다.

Kotlin

override fun onEnabled(context: Context?, intent: Intent?) {
    super.onEnabled(context, intent)

    // Get the affiliation ID (our DPC previously put in the extras) and
    // set the ID for this new secondary user.
    intent?.getStringExtra(AFFILIATION_ID_KEY)?.let {
        val dpm = getManager(context)
        dpm.setAffiliationIds(getWho(context), setOf(it))
    }
    // Continue setup of the new secondary user ...
}

자바

public void onEnabled(Context context, Intent intent) {
  // Get the affiliation ID (our DPC previously put in the extras) and
  // set the ID for this new secondary user.
  String affiliationId = intent.getStringExtra(AFFILIATION_ID_KEY);
  if (affiliationId != null) {
    DevicePolicyManager dpm = getManager(context);
    dpm.setAffiliationIds(getWho(context),
        new HashSet<String>(Arrays.asList(affiliationId)));
  }
  // Continue setup of the new secondary user ...
}

DPC 간 RPC

두 DPC 인스턴스는 별도의 사용자에서 실행 중이지만 DPC는 서로 통신할 수 있다는 것을 의미합니다. 다른 DPC의 서비스를 호출하는 것은 사용자 경계를 초과하기 때문에 DPC는 평소와 같이 bindService()를 호출합니다. Android 다음에서 실행 중인 서비스에 바인딩 다른 사용자가 DevicePolicyManager.bindDeviceAdminServiceAsUser()

기본 사용자와 RPC를 호출하는 연결된 보조 사용자 2명
그림 2. 연결된 기본 및 보조 사용자의 관리자 서비스 메서드 호출
를 통해 개인정보처리방침을 정의할 수 있습니다.

DPC는 DevicePolicyManager.getBindDeviceAdminTargetUsers() 다음 예시는 관리자에 대한 보조 사용자 바인딩의 관리자를 보여줍니다. 다음과 같은 이점을 누릴 수 있습니다.

Kotlin

// From a secondary user, the list contains just the primary user.
dpm.getBindDeviceAdminTargetUsers(adminName).forEach {

    // Set up the callbacks for the service connection.
    val intent = Intent(mContext, FullyManagedDeviceService::class.java)
    val serviceconnection = object : ServiceConnection {
        override fun onServiceConnected(componentName: ComponentName,
                                        iBinder: IBinder) {
            // Call methods on service ...
        }
        override fun onServiceDisconnected(componentName: ComponentName) {
            // Clean up or reconnect if needed ...
        }
    }

    // Bind to the service as the primary user [it].
    val bindSuccessful = dpm.bindDeviceAdminServiceAsUser(adminName,
            intent,
            serviceconnection,
            Context.BIND_AUTO_CREATE,
            it)
}

Java

// From a secondary user, the list contains just the primary user.
List<UserHandle> targetUsers = dpm.getBindDeviceAdminTargetUsers(adminName);
if (targetUsers.isEmpty()) {
  // If the users aren't affiliated, the list doesn't contain any users.
  return;
}

// Set up the callbacks for the service connection.
Intent intent = new Intent(mContext, FullyManagedDeviceService.class);
ServiceConnection serviceconnection = new ServiceConnection() {
  @Override
  public void onServiceConnected(
      ComponentName componentName, IBinder iBinder) {
    // Call methods on service ...
  }

  @Override
  public void onServiceDisconnected(ComponentName componentName) {
    // Clean up or reconnect if needed ...
  }
};

// Bind to the service as the primary user.
UserHandle primaryUser = targetUsers.get(0);
boolean bindSuccessful = dpm.bindDeviceAdminServiceAsUser(
    adminName,
    intent,
    serviceconnection,
    Context.BIND_AUTO_CREATE,
    primaryUser);

추가 리소스

전용 기기에 관해 자세히 알아보려면 다음 문서를 참고하세요.

  • 전용 기기 개요는 다음에 대한 개요입니다. 전용 기기입니다.
  • 작업 잠금 모드에서 다음 방법을 설명합니다. 전용 기기를 단일 앱 또는 여러 앱에 고정할 수 있습니다.
  • 다음 항목이 포함된 전용 기기 설명서 전용 기기를 제한하고 사용자 환경을 개선하기 위한 추가 예시 경험해 볼 수 있습니다