1. 始める前に
仕事用プロファイルとは
仕事用プロファイルとは、従業員が個人所有のデバイスを業務に使用することを会社が許可している場合に、個人所有のデバイスで有効にできるセカンダリ プロファイルです。
仕事用プロファイルは、IT 管理者が管理でき、その機能はユーザーのメイン プロファイルの機能とは別に設定できます。このアプローチにより、組織はユーザーのデバイスで会社固有のアプリとデータが実行および使用される環境を制御し、同時にユーザーは個人のアプリとプロファイルを使用し続けることができます。
アプリにはどのような影響があるでしょうか。どのアプリも仕事用プロファイルでインストールできますが、実行時の制限や動作変更の影響を受ける場合があります。また、仕事で使用するアプリであれば、セキュリティを確保する必要もあります。アプリが個人用プロファイルで動作している場合でも、仕事用プロファイルが動作に影響を及ぼす場合があります。
前提条件
この Codelab は、初級から中級のスキルを持つ Android デベロッパーを対象としています。
アプリの作成、Android Studio の使用、デバイスまたはエミュレータでのアプリのテストを経験していることが前提です。
演習内容
この Codelab では、仕事用プロファイルを使ってデバイスにインストールされたときのユーザー エクスペリエンスが最大限に高まるようにアプリを変更します。次のようなアプリの作成方法を学びます。
- 個人用と仕事用の両方の連絡先を同時に処理する。
- アプリ内から仕事用プロファイルと個人用プロファイルを切り替える。
必要なもの
- 管理対象外の Android デバイス(組織が所有または管理していないもの)
2. 設定する
テストデバイスをセットアップする
この Codelab には実機を使用することをおすすめしますが、Google Play ストアを含むイメージを使用して、エミュレータでも同じセットアップを行うことができます。
TestDPC
Google が作成する TestDPC アプリを使用して、ご自身のデバイスで管理対象環境をシミュレートしてテストできます。このアプリを使用することにより、仕事用プロファイルがセットアップされ、IT 管理者が行うのと同じように、デバイスで特定の機能の有効化と無効化を管理できるようになります。
TestDPC アプリをインストールする
デバイスから Google Play ストアを開き、TestDPC アプリをダウンロードします。
仕事用プロファイルをセットアップする
TestDPC アプリをインストールすると、デバイスに 2 つのアイコン(セットアップ アイコンと TestDPC アプリのアイコン)が表示されます。セットアップ アイコンをタップし、手順に沿って操作します。
これで、個人用アプリと仕事用アプリのために別々の 2 つのプロファイルができました。切り替えるにはアプリリストの上部にあるタブを使用します。
それぞれのプロファイルには専用の Google Play ストア アプリがあります。仕事用アプリを見つけるには、ランチャー アイコンの上部にある小さなブリーフケースのアイコンを使用します。
アプリは Google Play ストアから通常どおりにインストール可能で、起動した Google Play ストアに応じて(個人用か仕事用か)対応するプロファイルのみにインストールされます。アプリを両方の Google Play ストアからインストールして、両方のプロファイルに存在させることもできます。その場合、両方のアプリの間でストレージと設定の空間が完全に分離されます。
特定のプロファイルにアプリをインストールする方法
下記では、CrossProfileApps クラスを使用してデフォルトのプロファイルと仕事用プロファイルを切り替える方法について確認します。この動作を確認するため、アプリを両方のプロファイルにインストールする必要があります。
プロファイルの ID 番号を確認するには、下記の adb コマンドを使用します。
$ adb shell pm list users
指定のプロファイルにアプリをインストールするには、下記の adb コマンドを使用します。
$ adb install --user [id number of profile] [path of apk file]
プロジェクトの [Run/Debug Configuration] で [Install for all users] オプションを選択すると、同じ結果を得ることができます。
Android Studio から実行してアプリを更新すると、両方のプロファイルにインストールされます。
3. 連絡先を読み込む
デモアプリで使用するテスト用の連絡先を設定します。
- 個人用プロファイルからデバイスの連絡帳アプリを起動します。
- 個人用の連絡先だとわかるテスト用の連絡先を追加します。
- 仕事用プロファイルから連絡帳アプリを起動します(さきほど追加した個人用の連絡先は表示されません)。
- 仕事用の連絡先だとわかるテスト用の連絡先を追加します。
設定した連絡先に問題がなければ、デモアプリのスターター コードを試してください。
4. スターター コードを取得する
- 次のいずれかの方法でサンプルアプリを入手できます。
- GitHub からリポジトリのクローンを作成します。
$ git clone https://github.com/android/enterprise-samples.git $ cd enterprise-samples/Work-profile-codelab
- または、下記のリンクからプロジェクトをダウンロードします。
- Android Studio でアプリを開いて実行します。
アプリを初めて起動したときには次のように表示されます。
試してみる
この Codelab の終わりには、個人用プロファイルで実行したアプリに仕事用の連絡先と個人用の連絡先がいっしょに表示されるようになります。また、アプリ内からもう一方のプロファイルでアプリの別のインスタンスを起動して、プロファイルを切り替えることもできるようになります。
5. 仕事用と個人用の両方の連絡先を表示する
ContactsContract.Contacts.CONTENT_URI
を使用して連絡先を読み込む場合、アプリはどちらのプロファイルで実行中かに応じて、表示する連絡先を決定します。しかし、アプリに両方の連絡先リストを同時に読み込みたい場合も多々あります。たとえば、個人用のデータ(写真、ドキュメント)を同僚と共有する場合などです。そのためには、両方の連絡先リストを取得する必要があります。
MainActivity.kt を開く
メソッド onCreateLoader()
は、連絡先の取得と読み込みを行うカーソルローダを作成する役割を担います。現在、このメソッドはデフォルトの ContentURI を使用する CursorLoader のみを返します。このメソッドは 2 回呼び出します。1 回は個人用の連絡先のため、もう 1 回は仕事用の連絡先のためです。両者を区別できるように、それぞれの場合で別々の ID を onCreateLoader()
に渡します。このメソッドで受け取る ID を確認して、使用する ContentURI を決定する必要があります。
まず、メソッドに渡される ID の値に応じて ContentURI 変数の値を変更します。PERSONAL_CONTACTS_LOADER_ID の場合は、デフォルトの ContactsContract.Contacts.CONTENT_URI
を代入します。それ以外の場合は、こちらで説明されているように ENTERPRISE_CONTENT_FILTER_URI
を構築します。
ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI
.buildUpon()
.appendPath(nameFilter)
.appendQueryParameter(
ContactsContract.DIRECTORY_PARAM_KEY,
ContactsContract.Directory.ENTERPRISE_DEFAULT.toString()
)
.build()
これはコンテンツ フィルタ URI であるため、ビルダーには連絡先の検索または読み込みを行うときに使用する検索フィルタ(検索フレーズ)が必要です。
差し当たり、検索フレーズをハードコードして文字「a」で始まる名前にしてください。
val nameFilter = Uri.encode("a") // names that start with a
検索する連絡先ディレクトリを指定する必要もあります。ENTERPRISE_DEFAULT
ディレクトリを使用します。これを使用すると、デバイスにローカルに保存されている連絡先が検索されます。
onCreateLoader()
メソッドは次のようになります。
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> {
val nameFilter = Uri.encode("a") // names that start with a
val contentURI = when (id) {
PERSONAL_CONTACTS_LOADER_ID -> ContactsContract.Contacts.CONTENT_URI
else -> {
ContactsContract.Contacts.ENTERPRISE_CONTENT_FILTER_URI
.buildUpon()
.appendPath(nameFilter)
.appendQueryParameter(
ContactsContract.DIRECTORY_PARAM_KEY,
ContactsContract.Directory.ENTERPRISE_DEFAULT.toString()
)
.build()
}
}
return CursorLoader(
this, contentURI, arrayOf(
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
), null, null, null
)
}
ここで、上記のメソッドをトリガーするために、新しい ID 値で別の Loader
を初期化する必要があります。
まず、MainActivity
の上部に仕事用の連絡先のための新しい定数の ID 値を作成します。
const val WORK_CONTACTS_LOADER_ID = 1
次に、initLoaders()
で LoaderManager
を使用して、上記で作成した新しい ID で新しい Loader
を初期化します。
private fun initLoaders() {
LoaderManager.getInstance(this).
initLoader(PERSONAL_CONTACTS_LOADER_ID, null, this)
LoaderManager.getInstance(this).
initLoader(WORK_CONTACTS_LOADER_ID, null, this)
}
両方の Loader からのデータ Cursor の構造は同じであるため、他のすべてのメソッドでも同じように機能します。
試してみる
個人用プロファイルでアプリを実行すると、仕事用と個人用の両方の連絡先が表示されます。
仕事用プロファイルの場合
仕事用プロファイルでアプリを実行すると、仕事用の連絡先のみが表示され、個人用の連絡先は表示されません。これは、仕事用プロファイルの主な目的がユーザーのプライバシーを保護することであるためで、仕事用アプリでは通常、個人用プロファイルの個人情報にアクセスできません。
6. アプリ内でプロファイルを切り替える
Android には、異なるプロファイルでアプリの別のインスタンスを起動するための API があるため、ユーザーがアカウントを切り替えやすくなっています。たとえば、メールアプリで、ユーザーが個人用プロファイルと仕事用プロファイルを切り替えて 2 つのメール アカウントにアクセスするための UI を用意できます。
すべてのアプリは、すでに他のプロファイルにインストールされていれば、これらの API を呼び出して、同じアプリのメイン アクティビティを起動できます。
クロスプロファイル アカウントの切り替えをアプリに追加するには、まず、メインのアクティビティ レイアウトにボタンを追加して、ユーザーがプロファイルを切り替えられるようにする必要があります。
activity_main.xml
を開き、recycler-view ウィジェットの下にボタン ウィジェットを追加します。
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/button"
app:layout_constraintTop_toBottomOf="@+id/contacts_rv"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
MainActivity.kt
に戻り、onCreate
メソッドでプロファイルを切り替えるボタンのクリック イベントを設定します。
それには、まず CrossProfileApps
システム サービスを取得します。
val crossProfileApps = getSystemService(CrossProfileApps::class.java)
このクラスは、プロファイル切り替えの機能を実装するのに必要なすべての API を提供します。このアプリがインストールされている他のプロファイルをすべて返す targetUserProfiles
を呼び出すと、ユーザー プロファイルのリストを取得できます。
val userHandles = crossProfileApps.targetUserProfiles
返された userHandle の最初の項目を使用して、他のプロファイルでアプリを起動できるようになりました。
crossProfileApps.startMainActivity(
componentName,
userHandles.first()
)
ユーザーにプロファイルの切り替えを促すローカライズ済みのテキストを取得し、それを使用してボタンのテキスト値を設定できます。
val label = crossProfileApps.getProfileSwitchingLabel(userHandles.first())
以上の要素をすべてまとめて、MainActivity.kt の onCreate メソッドの最後に、以下のとおり追加します。
override fun onCreate(savedInstanceState: Bundle?) {
...
val crossProfileApps = getSystemService(CrossProfileApps::class.java)
val userHandles = crossProfileApps.targetUserProfiles
val label = crossProfileApps.getProfileSwitchingLabel(userHandles.first())
binding.button.apply {
text = label
setOnClickListener {
crossProfileApps.startMainActivity(
componentName,
userHandles.first()
)
}
}
}
試してみる
アプリを実行すると、どちらのプロファイルからアプリを起動したかに応じて、仕事用プロファイルまたは個人用プロファイルの切り替えができることを示すボタンが下部に表示されます。
このボタンをクリックすると、他方のプロファイルでアプリが開きます。
7. 完了
個人用プロファイルと仕事用プロファイルの両方で動作するアプリの変更ができました。このアプリは、仕事用プロファイルがインストールされていることを認識して、個人用モードで動作していても仕事用の連絡先を取得します。
また、アプリの実行中に同じアプリの仕事用プロファイルと個人用プロファイルを切り替える手段も実装しました。アプリを閉じたり、該当するプロファイルから再起動したりする必要はありません。プロファイルごとにアプリの使い方が異なるユーザーにも対応することをおすすめします。