ユーザー アカウントを実装する

Android Enterprise 登録には、managed Google Play アカウントと管理対象の Google アカウントの 2 つの主なユーザー ID タイプがあります。Managed Google Play アカウントはデバイス中心です。つまり、特定ユーザーの Google ID に関連付けられていません。一方、管理対象の Google アカウントはユーザーの企業 Google ID にリンクされているため、デバイスにログインした状態を維持することでユーザー エクスペリエンスが向上します。

以前は managed Google Play アカウントが標準でした。ただし、Google では、すべての新しい開発で改善された登録フローを使用することを推奨しています。このフローでは、デフォルトで管理対象 Google アカウントが作成されます。

古い実装に関するガイダンスは、このドキュメントの最後にコンテキストとして記載されていますが、すべての新しい開発は、ここで説明する新しい登録フローに沿って行う必要があります。

概要

デバイス登録フローの改善により、いくつかの新しいコンポーネントを活用し、カスタムの Device Policy Controller(DPC)の実装方法を変更することで、デバイスのセットアップが効率化されます。この新しいアプローチでは、デバイスの準備とユーザー登録の機能を実行するために、カスタム DPC ソリューションで Android Management API(AMAPI)SDK と Android Device Policy を統合する必要があります。

AMAPI SDK は、デバイス自体で Android デバイス ポリシーを操作するために必要な API を提供します。サーバー側では、企業向けモバイル管理(EMM)ソリューションが Play EMM API を使用して、デバイスの登録プロセスを開始するために必要な登録トークンを生成します。

Android Device Policy アプリは、デバイス側のオペレーションを処理するうえで中心的な役割を担うようになりました。AMAPI SDK は、デバイスでのインストールと必要な更新を管理するために使用されます。Android Device Policy は、ユーザー認証フローも引き継ぎ、ユーザー認証を直接処理して、ユーザーの ID を EMM に提供します。何らかの理由で Google がユーザーを認証できない場合、新しい managed Google Play アカウントが作成され、フォールバックとしてデバイスに追加されます。

この新しい登録フローの重要な部分は、Google サービスへのデバイスのアクセスを管理することです。デフォルトでは、デバイスは制限付きの状態から開始され、デバイスが準拠すると EMM がアクセスを有効にするうえで重要な役割を果たします。

API 統合

開始する前に、Play EMM API クライアントと AMAPI SDK の最新バージョンを使用していることを確認してください。

登録の実装ガイド

このガイドでは、登録を実装するために必要な手順について説明します。環境の準備、さまざまな登録方法の処理、デバイスのライフサイクルの管理について説明します。

環境を準備する

アカウント設定を開始する前に、デバイス環境を準備する必要があります。この準備では、Google Play ストアを最新バージョンに更新し、Android Device Policy(com.google.android.apps.work.clouddpc)をデバイスにサイレント インストールします。Android Device Policy のインストールは、アカウント設定プロセスの重要なコンポーネントを格納しているため、不可欠です。EMM は環境を手動で準備する必要はありません。代わりに、EnvironmentClient を使用し、ドキュメントに記載されているコード例に準拠する必要があります。

サンプルコード

AccountSetup API を使用してデバイスに仕事用アカウントを追加する前に、DPC はまずデバイス環境の準備が整っていることを確認する必要があります。

  • EnvironmentClientFactory を使用して EnvironmentClient をインスタンス化し、prepareEnvironment または prepareEnvironmentAsync を呼び出します。

    val notificationReceiverServiceName = ComponentName(context,
    NotificationReceiver::class.java)
    
    // An EMM should implement android.app.admin.DeviceAdminReceiver and use that
    // class to instantiate a ComponentName
    
    val admin = ComponentName(this, com.example.dpc.DeviceAdminReceiver::class.java)
    
    EnvironmentClientFactory.create(context)
        .prepareEnvironment(
            PrepareEnvironmentRequest.builder()
                .setRoles(
                    listOf(
                        Role.builder().setRoleType(
                            Role.RoleType.DEVICE_POLICY_CONTROLLER
                        ).build()
                    )
                )
        .setAdmin(admin)
                .build(),
              notificationReceiverServiceName,
            )
    
    [Proceed with AccountSetup]
    
    

適切な動作環境を確認するためにアプリケーションがインストールまたは更新されるため、このオペレーションには数秒または数分かかることがあります。Google は、このプロセスをバックグラウンドでできるだけ早く開始し、ユーザーが待機している間は適切な UI を表示することをおすすめします。オペレーションが完了すると、デバイスは DPC が AccountSetup API を使用できる状態になります。

登録フロー

EMM は、すべてのデバイスで users.generateAuthenticationToken()users.insert() の使用を中止する必要があります。代わりに、EMM はデバイス上の API を呼び出してエンドユーザー認証を行う必要があります。新しい API は、DPC に userIdemail を返します。Google がユーザーを認証できない場合、管理対象 Google Play アカウントが作成され、デバイスに追加されます。この場合、Google はそのアカウントの userId を返します。

Google は、認証 API に渡す必要がある登録トークンの使用を導入しました。EMM はトークンを作成するタイミングと方法を決定します。トークンは既存の登録ペイロード(QR コードやゼロタッチ構成など)の一部にすることができます。

ただし、変更を最小限に抑えるため、オンデマンドでトークンを作成し、Managed Google Play Accounts の既存の API を新しい API に置き換えることをおすすめします。

以前の API との一般的な DPC 統合
図 1. 以前の API を使用した一般的な DPC 統合
ユーザーレス デバイス用の新しい API を使用した DPC 統合の例
図 2.ユーザーレス デバイス用の新しい API を使用した DPC 統合の例
ユーザー デバイス用の新しい API を使用した DPC 統合の例
図 3. ユーザー デバイス用の新しい API を使用した DPC 統合の例

改善されたカスタム DPC 登録フローには、次の手順が含まれます。

デバイスの初期状態に関する重要な情報: カスタム DPC を使用してデバイスを登録する場合、デバイスに追加された Google アカウントは無効状態から開始されます。つまり、Google Play などの Google サービスへのアクセスが最初は制限されます。

このデフォルトの「無効」ステータスと、EMM がデバイスを準拠としてマークする(Devices.SetState を呼び出すなど)ための後続の要件は、次の条件に特に適用されます。

  1. 組織が Google でドメインの所有権を確認済みである。
  2. IT 管理者が、Google 管理コンソール内のユーザーの特定の組織部門(OU)に対してサードパーティの Android モバイル管理を明示的に有効にしている。
  1. 登録トークンを作成する: EMM は、Google Play EMM API を使用して登録トークンを作成します。
  2. 環境を準備する: カスタム DPC は、環境を準備するフローを使用して、デバイスが登録の準備ができていることを確認します。
  3. 登録を開始する: カスタム DPC が AMAPI SDK の startAccountSetup API を呼び出し、登録トークンを渡します。注: この API を呼び出す前に、DPC はデバイス オーナーまたはプロファイル オーナーのいずれかである必要があります。
  4. Google 認証アクティビティを起動する: 必要に応じて、カスタム DPC は AMAPI SDK の launchAuthenticationActivity API を呼び出し、AccountSetupAttempt を渡します。これにより、Google 認証アクティビティが開始され、認証が成功するとユーザーはカスタム DPC に戻ります。ユーザーはこのプロセスをスキップすることもできます。この場合、managed Google Play アカウントがデバイスに追加されます。このオプションは、googleAuthenticationOptions を使用して構成できます。
  5. 登録を完了する: AMAPI SDK は、登録結果をカスタム DPC に通知します。
  6. Google サービスを有効にする: カスタム DPC がデバイスのプロビジョニングを完了し、すべてのエンタープライズ ポリシーに準拠していることを確認したら、EMM サーバーは accountState パラメータを "enabled" に設定して Devices.setState() を呼び出す必要があります

    • この API 呼び出しが不可欠な理由: この API 呼び出しは、デバイスを準拠としてマークします。
    • 呼び出さない場合の結果: この Devices.setState(setStateRequest) 呼び出しがないと、アカウントは「無効」状態のままになります。ユーザーは、Google Play(アプリのインストールや更新)や、アカウント認証が必要な他の Google サービスにアクセスできなくなります。

デバイスの状態とサービス アクセスの管理

初回登録後、EMM はコンプライアンス ステータスに基づいて、デバイスの Google サービスへのアクセスを維持する責任を負います。

サービスの中断の処理: BAD_DEVICE_MANAGEMENT

デバイスの Google サービスへのアクセスがブロックされると、Google Play 開発者サービス(GMSCore)はアクション com.google.android.gms.auth.BAD_DEVICE_MANAGEMENT を含むインテントをブロードキャストします。この問題は次のような原因で発生することがあります。

  • EMM は、デバイスの登録後に Devices.setState("enabled") を呼び出していません。
  • デバイスが EMM ポリシーに準拠しなくなり、EMM がまだ再有効化していない。
  • EMM が、accountState を「disabled」に設定して Devices.setState() を呼び出し、デバイスの状態を明示的に「disabled」に設定しました。これは、セキュリティ上の懸念、管理措置、その他の理由による可能性があります。

このインテントには、"ThirdPartyDeviceManagementRequired" などのステータス コードが含まれます。

カスタム DPC は、この BAD_DEVICE_MANAGEMENT インテントをリッスンする BroadcastReceiver を実装しなければなりません。

このブロードキャストを受信すると、DPC は次の処理を行う必要があります。

  1. コンプライアンスを再評価する: デバイスが現在、EMM で設定されたすべてのポリシーを満たしているかどうかを確認します。
  2. 対応:
    • 準拠している場合: DPC は EMM サーバーに通知する必要があります。EMM サーバーは、特定のユーザー ID とデバイス ID の accountState"enabled" に設定して Devices.setState() を呼び出し、サービス アクセスの復元を試みる必要があります。
    • 準拠していない場合: 問題が解決し、デバイスが準拠したら、EMM は Devices.setState() を呼び出す必要があります。

このメカニズムにより、デバイスが Google サービスにアクセスできなくなった状況を検出し、復旧する方法が確保されます。

Enterprise Takeover の検討事項

組織のアカウントの種類(ManagedGoogleDomainType.TYPE_TEAM から ManagedGoogleDomainType.TYPE_DOMAIN など)が変更されることがあります。通常、このプロセスで EMM バインディングが解除されることはありませんが、デバイスでの Google サービスへのアクセスが中断されることがあります。

EMM は、既知の乗っ取りイベント後にユーザーがサービス アクセスの問題を報告した場合、デバイスが EMM ポリシーに準拠しているように見えても、新しい顧客構造の下でデバイスの状態を Google のバックエンドと再同期するために Devices.setState() の呼び出しが必要になる可能性があることに注意する必要があります。一般的に、引き継ぎ後のすべてのデバイスに対するプロアクティブな電話は必要ありませんが、アクセスに関する問題を解決するための重要なツールです。

アカウント設定 - サンプルコード

  1. アカウント設定の試行を開始するために、呼び出し元のアプリは AccountSetupClient を使用して、startAccountSetup() メソッドまたは startAccountSetupFuture() メソッドのいずれかを呼び出すことができます。実装例については、次のコードサンプルをご覧ください。

    // Create AccountSetupClient
    val client = AccountSetupClientFactory.create(
        this,
        activityResultRegistry
    )
    lifecycle.addObserver(client.lifecycleObserver)
    
    // Create adminComponent
    val notificationReceiver = ComponentName(this, AccountSetupNotificationReceiver::class.java)
    // Helper method to get enrollment token created with Play EMM API
    val enrollmentToken = getEnrollmentToken()
    val request =
        StartAccountSetupRequest.builder()
            .setEnrollmentToken(enteredText)
            .setNotificationReceiverServiceComponentName(notificationReceiver)
            .setAdminComponentName(
                ComponentName(this, com.example.dpc.DeviceAdminReceiver::class.java))
            .build()
    try {
        val accountSetupAttempt = client.startAccountSetup(request)
        // handle attempt
    } catch (e: Exception) {
        // handle exception
    }
    
  2. AccountSetupListener インターフェースを実装し、受信したステータス更新を処理する方法の実装を提供します。

  3. NotificationReceiverService を拡張し、getAccountSetupListener() をオーバーライドしてステップ 2 で作成した AccountSetupListener インスタンスを指定します。

    // Handles account setup changes
    class AccountSetupNotificationReceiver :
          NotificationReceiverService(),
          AccountSetupListener {
    
        override fun getAccountSetupListener(): AccountSetupListener = this
    
        override fun onAccountSetupChanged(accountSetupAttempt:
      AccountSetupAttempt) {
    
            when (accountSetupAttempt.state.kind) {
                StateCase.ADDED_ACCOUNT -> {
                    val enterpriseAccount = state.addedAccount()
                    val userId = enterpriseAccount.userId
                    val deviceId = enterpriseAccount.deviceId
                    // Handle account added state.
    
                    // IMPORTANT: The device/account is now added but *DISABLED*
                    // for Google services. Your EMM backend MUST be notified to
                    // perform policy compliance checks and then call Devices.setState()
                    // to activate Google Play and other services.
    
                }
                StateCase.AUTHENTICATION_ACTIVITY_LAUNCH_REQUIRED -> {
                    val request = LaunchAuthenticationActivityRequest.builder()
                .setAccountSetupAttempt(accountSetupAttempt)
                .build();
                    // Send the attempt to the foreground activity to call:
                    accountSetupClient.launchAuthenticationActivity(request)
                }
                StateCase.ACCOUNT_SETUP_ERROR -> {
                    // Handle error state.
                    val failureReason = state.accountSetupError().failureReason
                }
                else -> {
                    // Handle unknown account setup attempt state.
                }
            }
        }
    }
    
    
  4. 拡張された NotificationReceiverService クラスを AndroidManifest.xml に追加し、エクスポートされたことを確認します。

      <application>
        <service
            android:name = ".accountsetup.AccountSetupNotificationReceiver"
            android:exported = "true" />
      </application>
    

    アプリが SDK 30 以降をターゲットとしている場合は、ADP とやり取りすることを指定するために、AndroidManifest.xml に queries 要素が必要です。

      <queries>
        <package android:name="com.google.android.apps.work.clouddpc" />
      </queries>
    

テストのガイダンス

このセクションでは、実装をテストするためのガイドラインとベスト プラクティスについて説明します。

PrepareEnvironment のテスト

  1. デバイスの現在の状態を取得する: EMM が

    adb shell dumpsys package com.google.android.apps.work.clouddpc | grep versionName
    

    デバイスに存在する Android Device Policy のバージョンを取得します。Android Device Policy がインストールされていない場合、出力は空になります。

  2. PrepareEnvironment を統合する: カスタム DPC は AMAPI SDK の prepareEnvironment API を呼び出し、正しいリクエストを渡します。

  3. PrepareEnvironment の結果を待機: カスタム DPC は prepareEnvironment の完了を待機します。

  4. PrepareEnvironment の成功を確認する: 完了すると、EMM が再度実行されます

    adb shell dumpsys package com.google.android.apps.work.clouddpc | grep versionName
    

    このとき、Android Device Policy のバージョンはステップ 1 のバージョンよりも高い必要があります。

Google アカウントの認証をテストする

  1. テスト エンタープライズを作成する: EMM は、テスト EMM にリンクされたテスト ドメインの Google エンタープライズを enterprises.generateSignupUrl で作成します。
  2. Google 認証を有効にする: EMM は、Google 管理コンソールのこちらの手順に沿って、テスト エンタープライズの Google 認証を有効にします。
  3. 登録トークンを作成する: EMM は、タイプ userDevice の Play EMM API を使用して登録トークンを作成します。
  4. 登録を開始する: カスタム DPC が AMAPI SDK の startAccountSetup API を呼び出し、登録トークンを渡します。
  5. アクティビティの起動が必要: AMAPI SDK は、ユーザーを認証するためにアクティビティを起動する必要があることをカスタム DPC に通知します。
  6. ユーザーを認証する: カスタム DPC は launchAuthenticationActivity を呼び出してアクティビティを開始します。ユーザーは、管理対象の Google アカウント(ステップ 1 で作成したエンタープライズの一部)で認証します。
  7. 登録を完了する: AMAPI SDK は、登録結果をカスタム DPC に通知します。

Google 認証のスキップをテストする

ここでは、前述の設定を使用します。

今回は、ステップ 7 で、ユーザーは Google アカウントで認証する代わりに [スキップ] を押します。登録が正常に完了し、デバイスにサービス アカウントがある(つまり、AuthenticationType が匿名である)。

ユーザーのいないデバイスをテストする

改善されたカスタム DPC 登録フローでは、Google 認証が無効になっている場合、次の手順が使用されます。

  1. テスト用エンタープライズを作成する: これは、以前に作成したエンタープライズと同じでもかまいません。
  2. 登録トークンを作成する: EMM は、タイプ userlessDevice の Play EMM API を使用して登録トークンを作成します。
  3. 登録を開始する: カスタム DPC が AMAPI SDK の startAccountSetup API を呼び出し、登録トークンを渡します。
  4. 登録を完了する: AMAPI SDK は、登録結果をカスタム DPC に通知します。