앱 배포

Google Play EMM API는 공개 앱과 비공개 앱에 다음과 같은 배포 방법을 지원합니다.

관리 Google Play 스토어에서 앱 수동 설치

Devicepolicy에서 사용자가 설치할 수 있는 앱을 정의하고 Devices.update를 호출하여 설정할 수 있습니다. 새 기기를 프로비저닝할 때는 관리 Google Play 계정을 기기에 추가하기 전에 정책을 설정해야 합니다. 그러지 않으면 계정을 기기에 추가한 후 잠시 동안 정책이 적용되지 않습니다.

관리 Play 스토어 동작은 policy.productAvailabilityPolicy 값에 따라 정의됩니다.

  • all: Play 스토어의 모든 공개 앱을 사용할 수 있습니다.
  • whitelist: policy.productPolicy에 나열된 앱만 사용할 수 있습니다.

두 경우 모두 policy.productPolicy의 모든 앱이 기본적으로 기업의 스토어 레이아웃에 추가됩니다. 기업의 스토어 레이아웃은 whitelist이 선택된 경우 관리 Play 스토어의 홈페이지이며 all이 선택된 경우 '직장 앱' 탭에서 액세스할 수 있습니다. 관리 Google Play iframe을 삽입하여 고객이 기업의 스토어 레이아웃을 맞춤설정하도록 허용할 수 있습니다 (관리 Google Play iframe으로 앱 정리 참고).

사용자 기기에 앱 원격 설치

사용자 기기에 앱을 원격으로 설치 (푸시 설치라고도 함)하려면 Devicepolicy에서 policy.productPolicy.autoInstallPolicy를 설정합니다. 새 기기를 프로비저닝할 때는 관리 Google Play 계정을 기기에 추가하기 전에 정책을 설정해야 합니다. 그러지 않으면 계정을 기기에 추가한 후 잠시 동안 정책이 적용되지 않습니다.

autoInstallMode는 다음과 같이 설정할 수 있습니다.

  • doNotAutoInstall: 앱이 자동으로 설치되지 않습니다.
  • autoInstallOnce: 앱은 한 번 자동으로 설치되며 사용자가 앱을 제거하면 다시 설치되지 않습니다.
  • forceAutoInstall: 앱이 자동으로 설치되며 사용자가 앱을 제거하면 다시 설치됩니다. 관리 기기에서 DPC는 DevicePolicyManager.setUninstallBlocked를 사용하여 제거를 차단해야 합니다.

실패 (연결 끊김, 저장용량 부족 등)가 발생하면 설치가 성공할 때까지 자동으로 재시도됩니다. 복구 불가능한 오류가 발생할 경우 배터리와 데이터가 낭비되지 않도록 지수 백오프 재시도 전략이 적용됩니다.

설치 우선순위

autoInstallPriority를 설정하여 설치 순서를 선택할 수 있습니다. 우선순위는 부호 없는 정수여야 하며 기본값은 0입니다. 앱은 우선순위 순으로 설치되므로 우선순위 값이 낮은 앱이 먼저 설치됩니다.

제약 조건 설치

autoInstallConstraint를 설정하여 각 앱에 설치 제약 조건을 설정하면 설치 중에 기기의 필수 상태를 제어할 수 있습니다.

  • 기기가 Wi-Fi 네트워크에 연결되어 있어야 하는지 여부
  • 기기가 충전 중인지 여부
  • 기기가 유휴 상태여야 하는지 (사용자가 적극적으로 사용하지 않음) 여부입니다.

제약조건이 즉시 충족되지 않으면 제약조건이 충족될 때까지 영향을 받는 설치가 대기열에 추가됩니다.

autoInstallConstraint에서는 필드 간에 AND 규칙이 적용됩니다. 예를 들어 다음 autoInstallConstraint를 사용하면 기기가 충전 중이고 무제한 네트워크 (예: Wi-Fi)에 연결되어 있어야 앱이 설치됩니다.

"autoInstallConstraint": [
  "chargingStateConstraint" : "chargingRequired",
  "networkTypeConstraint" : "unmeteredNetwork"
]

새로 프로비저닝된 기기에 앱 자동 설치

Google Play EMM API는 기기가 처음 프로비저닝될 때 NewDeviceEvent 알림을 전송합니다. 새로 프로비저닝된 기기에 앱을 자동으로 푸시 설치하려면 NewDeviceEvent 알림을 리슨하세요. 각 NewDeviceEvent에서 userIddeviceId를 가져온 다음 Devices.update를 호출하여 해당 기기의 정책을 설정합니다.

EMM 알림을 구독하는 방법을 알아보려면 EMM 알림 설정을 참고하세요.

앱 자동 설치 오류 의견

앱 설치와 관련된 오류는 앱 의견을 통해 보고되며 DPC는 KeyedAppStatesService를 통해 전송된 EnterprisePolicyStatus 메시지를 모니터링할 수 있습니다.

Base64로 인코딩된 데이터를 디코딩하려면 DPC가 EnterprisePolicyStatus의 프로토 정의에 따라 클래스를 생성해야 합니다. proto 클래스를 생성하는 방법에 관한 안내는 프로토콜 버퍼 문서를 참고하세요.

생성된 클래스를 사용하여 DPC는 EnterprisePolicyStatus 객체를 디코딩할 수 있습니다.

EnterprisePolicyStatus enterprisePolicyStatus = EnterprisePolicyStatus.parseFrom(
    BaseEncoding.base64().decode(base64EncodedString)
);

이제 기기 정책에 새로운 선택적 필드 PolicyId가 포함됩니다. 정책을 만들거나 업데이트할 때 EMM은 특정 기기 정책 버전을 식별하기 위해 PolicyId를 문자열 값으로 설정할 수 있습니다.

가능한 경우 앱 설치 의견은 DPC가 수신된 오류를 특정 정책과 일치시킬 수 있도록 PolicyId를 보고합니다.

EnterprisePolicyStatus

message EnterprisePolicyStatus {
  // Individual status for an app in the policy
  repeated ApplicationStatus app_status = 1;

  // Version of the policy for which this status applies.
  PolicyVersion version = 2;
}

ApplicationStatus

// Individual status for an app.
message ApplicationStatus {
  // The package name for the app.
  string package_name = 1;

  // The install status for the app. Only includes status for apps scheduled
  // to be auto-installed via the policy resource.
  AutoInstallStatus install_status = 2;
}

AutoInstallStatus

// Auto-install status for an app.
message AutoInstallStatus {
  // The error causing the install to fail if state is INSTALL_ERROR.
  EnterpriseAutoInstallError error = 1;

  // The current install state of the app.
  EnterpriseAutoInstallState state = 2;
}

PolicyVersion

// The version of the policy which these install states apply to.
message PolicyVersion {
  // A policy id which may be optionally set by the EMM.
  string policy_id = 1;
}

EnterpriseAutoInstallError

// Install errors resulting in failure to install an app.
enum EnterpriseAutoInstallError {
  // Catch-all for unrecognized enum values.
  ENTERPRISE_AUTO_INSTALL_ERROR_UNKNOWN = 0;

  // The app could not be found.
  ENTERPRISE_AUTO_INSTALL_ERROR_NOT_FOUND = 1;

  // The app is not available in the user's country.
  ENTERPRISE_AUTO_INSTALL_ERROR_UNAVAILABLE_COUNTRY = 2;

  // The app is not compatible with the device hardware.
  ENTERPRISE_AUTO_INSTALL_ERROR_NOT_COMPATIBLE_WITH_DEVICE = 3;

  // No license remained to grant ownership of the app, and the user did not
  // already own the app.
  ENTERPRISE_AUTO_INSTALL_ERROR_NO_LICENSES_REMAINING = 4;

  // Required permissions for the app have not been accepted.
  ENTERPRISE_AUTO_INSTALL_ERROR_MISSING_PERMISSION = 5;

  // The app is not available based on the enterprise availability policy.
  ENTERPRISE_AUTO_INSTALL_ERROR_NOT_APPROVED_OR_UNAVAILABLE = 6;

  // The app is not available to the user or device.
  ENTERPRISE_AUTO_INSTALL_ERROR_APP_UNAVAILABLE = 7;

  // Failed to grant license because the user already has ownership.
  ENTERPRISE_AUTO_INSTALL_ERROR_INCOMPATIBLE_OWNERSHIP = 8;

  // The admin has not accepted the terms of service.
  ENTERPRISE_AUTO_INSTALL_ERROR_TOS_NOT_ACCEPTED = 9;

  // The device does not have enough RAM.
  ENTERPRISE_AUTO_INSTALL_ERROR_INSUFFICIENT_RAM = 10;

  // The app is incompatible with the device carrier.
  ENTERPRISE_AUTO_INSTALL_ERROR_NOT_COMPATIBLE_WITH_DEVICE_CARRIER = 11;

  // The app is incompatible with the country or carrier.
  ENTERPRISE_AUTO_INSTALL_ERROR_NOT_COMPATIBLE_WITH_DEVICE_COUNTRY_OR_CARRIER = 12;

  // The app is incompatible with the safe search level.
  ENTERPRISE_AUTO_INSTALL_ERROR_NOT_COMPATIBLE_WITH_DEVICE_SAFE_SEARCH_LEVEL = 13;

  // The app could not be installed due to an installer error.
  ENTERPRISE_AUTO_INSTALL_ERROR_INSTALL_FAILED = 14;

  // The app could not be installed due to network errors.
  ENTERPRISE_AUTO_INSTALL_ERROR_NETWORK_FAILED = 15;

  // The device does not have enough storage.
  ENTERPRISE_AUTO_INSTALL_ERROR_INSUFFICIENT_STORAGE = 16;
}

EnterpriseAutoInstallState

// The current install state for an app.
enum EnterpriseAutoInstallState {
  // Catch-all for unrecognized enum values.
  INSTALL_STATE_UNKNOWN = 0;

  // The app has been received by Play but an install attempt has not completed
  // yet.
  INSTALL_STATE_PENDING = 1;

  // The latest install attempt failed and will be retried automatically.
  INSTALL_STATE_ERROR = 2;

  // The app has been installed.
  INSTALL_STATE_INSTALLED = 3;
}

비공개 테스트용 앱 배포

비공개 테스트를 통해 앱 개발자는 신뢰할 수 있는 사용자로부터 앱의 초기 버전에 관한 의견을 수렴할 수 있습니다. 개발자는 Google Play Console에서 비공개 테스트를 설정할 수 있습니다. Play EMM API를 사용하면 IT 관리자가 앱의 비공개 버전 (트랙이라고도 함)을 특정 사용자에게 배포할 수 있습니다. 기업 고객은 이 기능을 사용하여 서드 파티 앱을 테스트할 뿐만 아니라 자체 개발한 비공개 앱도 테스트할 수 있습니다.

요건을 충족하는 앱

개발자가 앱의 비공개 테스터 목록에 기업을 추가하려면 앱이 다음 기준을 충족해야 합니다.

  • 앱의 프로덕션 버전이 Google Play에 게시됩니다.
  • Google Play Console의 앱 고급 설정 페이지에서 관리 Google Play가 사용 설정되어 있습니다.
  • 앱의 비공개 버전은 버전 코드 요구사항을 충족합니다.

비공개 테스트에 기업 추가

앱 개발자는 비공개 알파 테스트 또는 Google 그룹스를 사용하는 알파 테스트 방법을 사용하는 테스트에 기업을 추가할 수 있습니다. 자세한 내용은 공개, 비공개, 내부 테스트 설정 방법에 관한 가이드를 참고하세요. 개발자는 참여하는 각 기업의 조직 ID (기업 ID라고도 함)를 입력해야 합니다. IT 관리자는 다음 단계에 따라 서드 파티 앱 개발자에게 조직의 ID를 제공할 수 있습니다.

  1. Managed Google Play 스토어에 로그인합니다.
  2. 관리자 설정을 클릭합니다.
  3. 조직 정보 상자에서 조직 ID 문자열을 복사하여 개발자에게 보냅니다.

비공개 앱의 추가 요구사항

비공개 앱의 경우 개발자는 앱의 고급 설정 페이지에 있는 관리 Google Play 탭에 참여하는 각 기업의 조직 ID도 추가해야 합니다. 자세한 내용은 비공개 앱 게시하기를 참고하세요.

사용자에게 비공개 트랙 배포

지정된 앱에 대해 기업에서 사용할 수 있는 트랙 목록을 가져오려면 Products.get를 호출합니다. 응답에 포함된 appTracks[] 목록에는 각 앱에 사용할 수 있는 트랙이 포함됩니다. appTracks[].trackAlias는 EMM 콘솔에 표시할 수 있는 사용자가 읽을 수 있는 트랙 이름이고 appTracks[].trackId는 트랙의 기계가 읽을 수 있는 ID입니다.

사용자에게 앱의 비공개 트랙에 대한 공개 상태를 부여하려면 Devicepolicy에서 policy.productPolicy[].trackIds[]를 설정합니다. 기기에 여러 트랙을 사용할 수 있는 경우 버전 코드가 가장 높은 사용 가능한 버전이 설치됩니다.

다음과 같은 특정 시나리오에서는 trackIds가 Products.get 호출에서 자동으로 삭제됩니다.

  • 트랙의 앱 버전이 다른 트랙 또는 프로덕션으로 승격됩니다.
  • 프로덕션 버전이 트랙보다 높은 버전으로 업데이트됩니다.
  • 개발자가 트랙을 중지합니다.

유료 앱 라이선스 추적

유료 앱의 경우 Grouplicenses 객체는 기업이 소유한 라이선스 수와 사용 중인 라이선스 수를 추적합니다. Grouplicenses.get를 호출하여 앱의 라이선스 세부정보를 가져올 수 있습니다.

기기에 유료 앱을 설치하려면 먼저 기업에 해당 앱을 사용할 수 있는 라이선스가 있어야 합니다. 라이선스를 사용할 수 있으면 앱이 기기에 설치되고 Entitlements 객체가 생성됩니다. Entitlements 객체는 라이선스를 사용자와 연결하고 앱에 사용 가능한 라이선스 수를 감소시킵니다. 사용 가능한 라이선스가 없으면 앱 설치가 실패하고 Entitlements 객체가 생성되지 않습니다.

GrouplicensesEntitlements 객체는 무료로 배포되는 애플리케이션에서 사용되지 않습니다.