직장 프로필

Android 플랫폼에서는 기기에 직장 프로필 (관리 프로필이라고도 함)을 보유할 수 있습니다. 직장 프로필은 IT 관리자가 제어하며 직장 프로필에 사용할 수 있는 기능은 사용자 기본 프로필의 기능과 별도로 설정됩니다. 이 접근 방식을 사용하면 조직에서는 사용자의 기기에서 회사별 앱과 데이터가 실행되는 환경을 제어하면서 사용자가 개인 앱과 프로필을 사용하도록 허용할 수 있습니다.

이 과정에서는 직장 프로필이 있는 기기에서 안정적으로 작동하도록 애플리케이션을 수정하는 방법을 보여줍니다. 일반적인 앱 개발 권장사항 외에 별도의 조치를 취할 필요는 없습니다. 그러나 이러한 권장사항 중 일부는 직장 프로필이 있는 기기에서 특히 중요합니다. 이 문서에서는 알고 있어야 하는 문제를 중점적으로 설명합니다.

개요

사용자는 기업 환경에서 개인 기기를 사용하는 경우가 많습니다. 이러한 상황은 조직에 딜레마를 일으킬 수 있습니다. 사용자가 자신의 기기를 사용할 수 있는 경우 조직은 조직에서 관리하지 않는 기기에 기밀 정보 (예: 직원 이메일, 연락처)가 있는지 걱정해야 합니다.

이 문제를 해결하기 위해 Android 5.0 (API 수준 21)에서는 조직에서 직장 프로필을 설정할 수 있습니다. 기기에 직장 프로필이 있으면 프로필 설정은 IT 관리자가 제어합니다. IT 관리자는 해당 프로필에 허용되는 앱을 선택하고 프로필에서 사용할 수 있는 기기 기능만 제어할 수 있습니다.

기기에 직장 프로필이 있으면 앱이 어떤 프로필에서 실행되든 상관없이 기기에서 실행되는 앱에 영향을 미칩니다.

  • 기본적으로 대부분의 인텐트는 한 프로필에서 다른 프로필로 교차하지 않습니다. 프로필에서 실행 중인 앱이 인텐트를 실행하면 해당 프로필의 인텐트에 관한 핸들러가 없고 프로필 제한으로 인해 인텐트가 다른 프로필로 이동할 수 없으면 요청이 실패하고 앱이 예기치 않게 종료될 수 있습니다.
  • 프로필 IT 관리자는 직장 프로필에서 사용 가능한 시스템 앱을 제한할 수 있습니다. 이 제한으로 인해 직장 프로필에 일부 일반적인 인텐트의 핸들러가 없을 수도 있습니다.
  • 개인 프로필과 직장 프로필에는 별도의 저장소 영역이 있으므로 한 프로필에서 유효한 파일 URI는 다른 프로필에서 유효하지 않습니다. 한 프로필에서 실행된 인텐트는 프로필 설정에 따라 다른 프로필에서 처리될 수 있으므로 파일 URI를 인텐트에 연결하는 것은 안전하지 않습니다.

실패한 인텐트 방지

직장 프로필이 있는 기기에는 인텐트가 한 프로필에서 다른 프로필로 교차할 수 있는지에 제한이 있습니다. 대부분의 경우 인텐트가 실행되면 인텐트가 실행된 동일한 프로필에서 처리됩니다. 해당 프로필에 인텐트의 핸들러가 없으면 인텐트가 처리되지 않으며 이를 실행한 앱이 예기치 않게 종료될 수 있습니다. 이는 다른 프로필에 인텐트의 핸들러가 있더라도 마찬가지입니다.

프로필 관리자는 한 프로필에서 다른 프로필로 교차할 수 있는 인텐트를 선택할 수 있습니다. IT 관리자가 이 결정을 내리므로 이 경계를 통과할 수 있는 어떤 인텐트가 허용되는지 미리 알 수 있는 방법은 없습니다. IT 관리자는 이 정책을 설정하며 언제든지 자유롭게 변경할 수 있습니다.

앱에서 활동을 시작하기 전에 적절한 해결 방법이 있는지 확인해야 합니다. Intent.resolveActivity()를 호출하여 허용되는 해결 방법이 있는지 확인할 수 있습니다. 인텐트를 확인할 방법이 없으면 메서드는 null를 반환합니다. 메서드가 null이 아닌 값을 반환하는 경우 인텐트를 해결할 방법이 하나 이상 있으므로 인텐트를 실행하는 것이 안전합니다. 이 경우 현재 프로필에 핸들러가 있거나 인텐트가 다른 프로필의 핸들러로 교차할 수 있기 때문에 인텐트를 확인할 수 있습니다. 인텐트 해결에 관한 자세한 내용은 일반 인텐트를 참고하세요.

예를 들어 앱에서 타이머를 설정해야 한다면 ACTION_SET_TIMER 인텐트에 유효한 핸들러가 있는지 확인해야 합니다. 앱이 인텐트를 확인할 수 없으면 적절한 조치를 취해야 합니다 (예: 오류 메시지 표시).

Kotlin

fun startTimer(message: String, seconds: Int) {

    // Build the "set timer" intent
    val timerIntent = Intent(AlarmClock.ACTION_SET_TIMER).apply {
        putExtra(AlarmClock.EXTRA_MESSAGE, message)
        putExtra(AlarmClock.EXTRA_LENGTH, seconds)
        putExtra(AlarmClock.EXTRA_SKIP_UI, true)
    }

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(packageManager) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent)

    }
}

Java

public void startTimer(String message, int seconds) {

    // Build the "set timer" intent
    Intent timerIntent = new Intent(AlarmClock.ACTION_SET_TIMER)
            .putExtra(AlarmClock.EXTRA_MESSAGE, message)
            .putExtra(AlarmClock.EXTRA_LENGTH, seconds)
            .putExtra(AlarmClock.EXTRA_SKIP_UI, true);

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(getPackageManager()) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent);

    }
}

프로필 간 파일 공유

앱이 자체 파일에 액세스할 수 있는 권한을 다른 앱에 제공해야 하는 경우도 있습니다. 예를 들어 이미지 갤러리 앱은 이미지 편집기와 이미지를 공유해야 할 수 있습니다. 일반적으로 파일을 공유하는 방법에는 파일 URI 또는 콘텐츠 URI를 사용하는 두 가지 방법이 있습니다.

파일 URI는 file: 접두사로 시작하고 그 뒤에 기기 저장소에 있는 파일의 절대 경로가 옵니다. 그러나 직장 프로필과 개인 프로필은 별도의 저장소 영역을 사용하므로 한 프로필에서 유효한 파일 URI는 다른 프로필에서 유효하지 않습니다. 즉, 파일 URI를 인텐트에 연결하고 인텐트가 다른 프로필에서 처리되는 경우 핸들러가 파일에 액세스할 수 없습니다.

대신 콘텐츠 URI와 파일을 공유해야 합니다. 콘텐츠 URI는 더 안전하고 공유 가능한 방식으로 파일을 식별합니다. 콘텐츠 URI에는 파일 경로뿐 아니라 파일을 제공하는 권한과 파일을 식별하는 ID 번호가 포함됩니다. FileProvider를 사용하여 모든 파일의 콘텐츠 ID를 생성할 수 있습니다. 그런 다음 해당 콘텐츠 ID를 다른 앱과 공유할 수 있습니다 (다른 프로필에도 가능). 수신자는 콘텐츠 ID를 사용하여 실제 파일에 액세스할 수 있습니다.

예를 들어 특정 파일 URI의 콘텐츠 URI를 가져오는 방법은 다음과 같습니다.

Kotlin

// Open File object from its file URI
val fileToShare = File(fileUriToShare)

val contentUriToShare: Uri = FileProvider.getUriForFile(
        context,
        "com.example.myapp.fileprovider",
        fileToShare
)

Java

// Open File object from its file URI
File fileToShare = new File(fileUriToShare);

Uri contentUriToShare = FileProvider.getUriForFile(getContext(),
        "com.example.myapp.fileprovider", fileToShare);

getUriForFile() 메서드를 호출할 때는 파일 제공자의 권한 (이 예에서는 "com.example.myapp.fileprovider")을 포함해야 합니다. 이 권한은 앱 매니페스트의 <provider> 요소에 지정됩니다. 콘텐츠 URI를 사용하여 파일을 공유하는 방법에 관한 자세한 내용은 파일 공유를 참고하세요.

알림 수신 대기

일반적으로 앱은 NotificationListenerService 서브클래스를 제공하여 시스템에서 알림 변경에 관한 콜백을 수신합니다. 직장 프로필이 있는 기기는 NotificationListenerService이 앱에서 작동하는 방식에 영향을 줄 수 있습니다.

직장 프로필의 경우

직장 프로필에서 실행되는 앱에서는 NotificationListenerService를 사용할 수 없습니다. 앱이 직장 프로필에서 실행 중이면 시스템은 앱의 NotificationListenerService를 무시합니다. 그러나 개인 프로필에서 실행되는 앱은 알림을 수신 대기할 수 있습니다.

개인 프로필

앱이 개인 프로필에서 실행될 때 직장 프로필에서 실행되는 앱의 알림을 받지 못할 수 있습니다. 기본적으로 모든 개인 프로필 앱은 콜백을 수신하지만, IT 관리자는 알림 변경사항을 수신 대기하도록 허용한 하나 이상의 개인 프로필 앱을 허용 목록에 추가할 수 있습니다. 그러면 시스템은 허용 목록에 없는 앱을 차단합니다. Android 8.0 (API 수준 26) 이상에서는 직장 프로필을 관리하는 기기 정책 컨트롤러 (DPC)가 DevicePolicyManager 메서드 setPermittedCrossProfileNotificationListeners()를 사용하여 앱이 직장 프로필의 알림을 수신 대기하지 못하도록 차단할 수 있습니다. 앱은 개인 프로필에 게시된 알림에 관한 콜백을 계속 수신합니다.

앱과 직장 프로필의 호환성 테스트

직장 프로필 환경에서 앱을 테스트하여 직장 프로필이 있는 기기에서 앱 장애가 발생하는 문제를 포착해야 합니다. 특히 직장 프로필 기기에서 테스트는 앱이 인텐트를 제대로 처리하는지 확인하는 좋은 방법입니다. 처리할 수 없는 인텐트를 실행하지 않거나 교차 프로필에서 작동하지 않는 URI를 연결하지 않는 등의 방법이 있습니다.

Google에서는 Android 5.0 (API 수준 21) 이상을 실행하는 Android 기기에서 직장 프로필을 설정하는 데 사용할 수 있는 샘플 앱 TestDPC를 제공합니다. 이 앱은 직장 프로필 환경에서 앱을 테스트하는 간단한 방법을 제공합니다. 이 앱을 사용하여 다음과 같이 직장 프로필을 구성할 수도 있습니다.

  • 관리 프로필에서 사용할 수 있는 기본 앱 지정
  • 한 프로필에서 다른 프로필로 교차할 수 있는 인텐트 구성

직장 프로필이 있는 기기에 USB 케이블을 통해 앱을 수동으로 설치하면 앱이 개인 프로필과 직장 프로필 모두에 설치됩니다. 앱을 설치하고 나면 다음 조건에서 앱을 테스트할 수 있습니다.

  • 인텐트가 일반적으로 기본 앱 (예: 카메라 앱)에서 처리되는 경우 직장 프로필에서 기본 앱을 사용 중지하고 앱에서 이를 적절하게 처리하는지 확인합니다.
  • 다른 앱에서 처리할 것으로 예상하는 인텐트를 실행하는 경우 한 프로필에서 다른 프로필로 이동할 수 있도록 인텐트의 권한을 사용 설정하거나 사용 중지해 보세요. 앱이 두 상황에서 모두 제대로 작동하는지 확인합니다. 인텐트가 프로필 간을 교차할 수 없는 경우 앱 프로필에 적절한 핸들러가 있는 경우와 없는 경우 모두 앱의 동작을 확인합니다. 예를 들어 앱에서 지도 관련 인텐트를 실행하면 다음 각 시나리오를 시도해 보세요.
    • 기기를 사용하면 지도 인텐트가 한 프로필에서 다른 프로필로 교차할 수 있으며 다른 프로필 (앱이 실행되지 않는 프로필)에 적합한 핸들러가 있습니다.
    • 기기에서 지도 인텐트가 프로필 간에 교차하는 것을 허용하지 않지만 앱 프로필에 적절한 핸들러가 있습니다.
    • 기기에서 지도 인텐트가 프로필 간에 교차하는 것을 허용하지 않고 기기 프로필의 지도 인텐트에 적합한 핸들러가 없습니다.
  • 인텐트에 콘텐츠를 첨부하는 경우 인텐트가 앱 프로필에서 처리될 때와 프로필 사이를 지날 때 모두 제대로 동작하는지 확인합니다.

직장 프로필에서 테스트: 도움말 및 유용한 정보

직장 프로필 기기에서 테스트할 때 유용한 몇 가지 유용한 방법이 있습니다.

  • 앞서 언급했듯이 직장 프로필 기기에서 앱을 사이드로드하면 앱이 두 프로필에 모두 설치됩니다. 원한다면 한 프로필에서 앱을 삭제하고 다른 프로필에는 그대로 둘 수 있습니다.
  • Android 디버그 브리지 (adb) 셸에서 사용 가능한 대부분의 활동 관리자 명령어는 실행할 사용자를 지정할 수 있는 --user 플래그를 지원합니다. 사용자를 지정하면 관리되지 않는 기본 사용자로 실행할지 아니면 직장 프로필로 실행할지 선택할 수 있습니다. 자세한 내용은 ADB 셸 명령어를 참고하세요.
  • 기기에서 활성 사용자를 찾으려면 adb 패키지 관리자의 list users 명령어를 사용합니다. 출력 문자열의 첫 번째 숫자는 사용자 ID이며, --user 플래그와 함께 사용할 수 있습니다. 자세한 내용은 ADB 셸 명령어를 참고하세요.

예를 들어 기기에서 사용자를 찾으려면 다음 명령어를 실행합니다.

$ adb shell pm list users
UserInfo{0:Drew:13} running
UserInfo{10:Work profile:30} running

이 경우 기본 사용자('드루')의 사용자 ID는 0이고 직장 프로필의 사용자 ID는 10입니다. 직장 프로필에서 앱을 실행하려면 다음과 같은 명령어를 사용합니다.

$ adb shell am start --user 10 \
-n "com.example.myapp/com.example.myapp.testactivity" \
-a android.intent.action.MAIN -c android.intent.category.LAUNCHER