ロックタスク モード

このデベロッパー ガイドでは、専用デバイスを単一のアプリまたはアプリセットにロックする方法について説明します。企業向けモバイル管理(EMM)のデベロッパーやソリューション インテグレータの方は、このガイドをお読みになり、ソリューションにロックタスク モードを追加してください。

概要

Android では、ロックタスク モードと呼ばれる没入感のあるキオスク型の方法でタスクを実行できます。ロックタスク モードは、アプリのコレクションを表示するためのキオスクアプリやランチャーを開発している場合に使用できます。システムがロックタスク モードで実行されている場合、デバイス ユーザーは通常、通知を表示すること、許可リストに登録されていないアプリにアクセスすること、ホーム画面に戻ることはできません(ホーム画面が許可リストに登録されている場合を除きます)。

システムがロックタスク モードのときは、Device Policy Controller(DPC)によって許可リストに登録されたアプリのみを実行できます。デバイスを使用しているユーザーは常にロックタスク モードを終了できないため、アプリは許可リストに登録されています。

ロックタスク モードの許可リストに登録されたアプリと許可リストへの登録 DPC を組み合わせる方法は、解決したい問題によって異なります。以下の例をご参照ください。

  • キオスク(コンテンツの表示用)とミニ DPC(ロックタスク モードの許可リストへの登録用)を組み合わせた単一のアプリ パッケージ。
  • 企業向けモバイル管理ソリューションの一部である DPC で、お客様のモバイルアプリをロックタスク モードで起動します。

提供状況

Android 5.0 以降では、システムはロックタスク モードで実行できます。表 1 に、ユーザーによるアプリの許可リスト登録に対応している Android のバージョンを示します。

表 1. DPC 管理モードの Android バージョンのサポート
Android バージョン DPC が管理する Notes
Android 5.0(API レベル 21)以降 完全管理対象端末
Android 8.0(API レベル 26)以降 関連付けられているセカンダリ ユーザー セカンダリ ユーザーは、プライマリ ユーザーと関連付けられている必要があります。マルチユーザーの概要をご覧ください。
Android 9.0(API レベル 28)以降 セカンダリ ユーザー

Android 9.0 以降では、DPC はアプリのアクティビティをロックタスク モードで開始できます。以前のバージョンでは、アプリはロックタスク モードで独自のアクティビティを開始することをすでにサポートしている必要があります。

アプリを許可リストに登録

DPC をロックタスク モードで使用するには、アプリを許可リストに登録する必要があります。次のサンプルに示すように、DevicePolicyManager.setLockTaskPackages() を呼び出してロックタスク モードのアプリを許可リストに登録します。

Kotlin

// Allowlist two apps.
private val KIOSK_PACKAGE = "com.example.kiosk"
private val PLAYER_PACKAGE = "com.example.player"
private val APP_PACKAGES = arrayOf(KIOSK_PACKAGE, PLAYER_PACKAGE)

// ...

val context = context
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE)
        as DevicePolicyManager
val adminName = getComponentName(context)
dpm.setLockTaskPackages(adminName, APP_PACKAGES)

Java

// Allowlist two apps.
private static final String KIOSK_PACKAGE = "com.example.kiosk";
private static final String PLAYER_PACKAGE = "com.example.player";
private static final String[] APP_PACKAGES = {KIOSK_PACKAGE, PLAYER_PACKAGE};

// ...

Context context = getContext();
DevicePolicyManager dpm =
    (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminName = getComponentName(context);
dpm.setLockTaskPackages(adminName, APP_PACKAGES);

以前にロックタスク モードの許可リストに登録されたアプリを確認するには、DPC で DevicePolicyManager.getLockTaskPackages() を呼び出します。他のアプリは DevicePolicyManager.isLockTaskPermitted() を呼び出すことで、アプリ パッケージがロックタスク モードをサポートしていることを確認できます。

ロックタスク モードを開始する

Android 9.0(API レベル 28)以降では、別のアプリのアクティビティをロックタスク モードで開始できます。アクティビティがすでにフォアグラウンドまたはバックグラウンドで実行されている場合は、アクティビティを再起動する必要があります。ActivityOptions.setLockTaskEnabled() を呼び出し、アクティビティの起動時にこれらのオプションを指定します。次のスニペットは、これを行う方法の一例です。

Kotlin

// Set an option to turn on lock task mode when starting the activity.
val options = ActivityOptions.makeBasic()
options.setLockTaskEnabled(true)

// Start our kiosk app's main activity with our lock task mode option.
val packageManager = context.packageManager
val launchIntent = packageManager.getLaunchIntentForPackage(KIOSK_PACKAGE)
if (launchIntent != null) {
    context.startActivity(launchIntent, options.toBundle())
}

Java

// Set an option to turn on lock task mode when starting the activity.
ActivityOptions options = ActivityOptions.makeBasic();
options.setLockTaskEnabled(true);

// Start our kiosk app's main activity with our lock task mode option.
PackageManager packageManager = context.getPackageManager();
Intent launchIntent = packageManager.getLaunchIntentForPackage(KIOSK_PACKAGE);
if (launchIntent != null) {
  context.startActivity(launchIntent, options.toBundle());
}

9.0 より前のバージョンの Android では、アプリは Activity.startLockTask() を呼び出すことで、ロックタスク モードで独自のアクティビティを開始します。このメソッドを呼び出すには、アクティビティがフォアグラウンドで実行されている必要があります(アクティビティのライフサイクルのコンセプトを参照)。Activity または FragmentonResume() メソッドを呼び出すことをおすすめします。startLockTask() を呼び出す方法は次のとおりです。

Kotlin

// In our Fragment subclass.
override fun onResume() {
    super.onResume()
    // First, confirm that this package is allowlisted to run in lock task mode.
    if (dpm.isLockTaskPermitted(context.packageName)) {
        activity.startLockTask()
    } else {
        // Because the package isn't allowlisted, calling startLockTask() here
        // would put the activity into screen pinning mode.
    }
}

Java

// In our Fragment subclass.
@Override
public void onResume() {
  super.onResume();

  // First, confirm that this package is allowlisted to run in lock task mode.
  if (dpm.isLockTaskPermitted(context.getPackageName())) {
    getActivity().startLockTask();
  } else {
    // Because the package isn't allowlisted, calling startLockTask() here
    // would put the activity into screen pinning mode.
  }
}

ユーザーがデバイスのロックを解除できない可能性があるため、デバイスがロックされているときにロックタスク モードを開始しないでください。KeyguardManager メソッドを呼び出してデバイスがロックされているかどうかを確認し、Activity ライフサイクル コールバック(ロック解除後に呼び出される onResume() など)を使用してロックタスク モードを開始できます。

ロックタスク モードのアプリは、そのアクティビティが新しいタスクを開始しない限り、新しいアクティビティを開始できます(許可リストに登録されたアプリを起動するタスクを除く)。タスクとアクティビティの関係については、タスクとバックスタックについてをご覧ください。

または、アプリ マニフェスト ファイルで、システムがロックタスク モードで実行されているときのアクティビティの動作を宣言することもできます。アクティビティをロックタスク モードで自動的に実行するには、次の例に示すように android:lockTaskMode 属性を if_whitelisted に設定します。

<activity
    android:name=".MainActivity"
    android:lockTaskMode="if_whitelisted">
    <!-- ... -->
</activity>

アプリ マニフェスト ファイルでのオプションの宣言について詳しくは、lockTaskMode リファレンスをご覧ください。

ロックタスク モードを停止する

DPC は、許可リストからアプリ パッケージを削除することで、ロックタスク モードをリモートで停止できます。Android 6.0(API レベル 23)以降では、DevicePolicyManager.setLockTaskPackages() を呼び出し、許可リストの配列からパッケージ名を省略します。許可リストを更新すると、アプリはスタック内の前のタスクに戻ります。

アクティビティが以前に startLockTask() を呼び出していた場合、アクティビティは Activity.stopLockTask() を呼び出してロックタスク モードを停止できます。このメソッドは、ロックタスク モードを開始したアクティビティに対してのみ機能します。

ライフサイクル コールバック

DPC は、(同じユーザーで実行されている)アプリがロックタスク モードを開始、終了するタイミングを把握できると便利です。コールバックを受信するには、DPC の DeviceAdminReceiver サブクラスで次のコールバック メソッドをオーバーライドします。

onLockTaskModeEntering()
アプリがロックタスク モードになった後に呼び出されます。アプリのパッケージ名は pkg 引数から取得できます。
onLockTaskModeExiting()
アプリがロックタスク モードを終了した後に呼び出されます。このコールバックは、アプリに関する情報を受け取りません。

別のアプリをロックタスク モードで起動する場合は、自身のアプリで実行ステータスを追跡する必要があります。現在のアプリがロックタスク モードで実行されているかどうかを確認するには、次の例に示すように ActivityManager のメソッドを使用します。

Kotlin

// Check if this app is in lock task mode. Screen pinning doesn't count.
var isLockTaskModeRunning = false

val activityManager = context
        .getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    isLockTaskModeRunning =
            activityManager.lockTaskModeState ==
            ActivityManager.LOCK_TASK_MODE_LOCKED
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Deprecated in API level 23.
    isLockTaskModeRunning = activityManager.isInLockTaskMode
}

if (isLockTaskModeRunning) {
    // Show the exit button ...
}

Java

// Check if this app is in lock task mode. Screen pinning doesn't count.
boolean isLockTaskModeRunning = false;

ActivityManager activityManager = (ActivityManager)
    getContext().getSystemService(Context.ACTIVITY_SERVICE);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  isLockTaskModeRunning = activityManager.getLockTaskModeState()
      == ActivityManager.LOCK_TASK_MODE_LOCKED;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  // Deprecated in API level 23.
  isLockTaskModeRunning = activityManager.isInLockTaskMode();
}

if (isLockTaskModeRunning) {
  // Show the exit button ...
}

UI をカスタマイズする

アプリがロックタスク モードで実行されると、システム ユーザー インターフェース(UI)が次のように変化します。

  • ステータスバーが空白で、通知とシステム情報が非表示になる。
  • [ホーム] ボタンと [最近] ボタンは表示されません。
  • 他のアプリは新しいアクティビティを起動できません。
  • ロック画面(設定されている場合)は無効になります。

Android 9.0 以降では、ロックタスク モードが有効になっている場合、DPC はデバイスの特定のシステム UI 機能を有効にできます。これは、デベロッパーがカスタム ランチャーを作成する場合に便利です。次のスニペットに示すように DevicePolicyManager.setLockTaskFeatures() を呼び出します。

Kotlin

// Enable the Home and Overview buttons so that our custom launcher can respond
// using our custom activities. Implicitly disables all other features.
dpm.setLockTaskFeatures(
        adminName,
        DevicePolicyManager.LOCK_TASK_FEATURE_HOME or
              DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW)

Java

// Enable the Home and Overview buttons so that our custom launcher can respond
// using our custom activities. Implicitly disables all other features.
dpm.setLockTaskFeatures(adminName,
    DevicePolicyManager.LOCK_TASK_FEATURE_HOME |
          DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW);

flags 引数に含めない機能はすべて無効になります。有効になっている UI 機能は、ロックタスク モードで起動されるまでの間も維持されます。デバイスがすでにロックタスク モードになっている場合、ロックタスク機能に加えた変更はすぐに表示されます。表 2 に、カスタマイズできる UI 機能を示します。

表 2. ロックタスク モードでのカスタマイズ可能なシステム UI 機能
システム UI 機能 説明
LOCK_TASK_FEATURE_HOME ホームボタンを表示します。カスタム ランチャーで有効にする - 有効なホームボタンをタップしても、デフォルトの Android ランチャーを許可リストに登録しない限り、アクションは発生しません。
LOCK_TASK_FEATURE_OVERVIEW [Overview] ボタンを表示します(このボタンをタップすると、[最近] 画面が開きます)。このボタンを有効にする場合は、ホームボタンも有効にする必要があります。
LOCK_TASK_FEATURE_GLOBAL_ACTIONS 電源ボタンの長押しで表示されるグローバル アクション ダイアログを有効にします。setLockTaskFeatures() が呼び出されていないときに有効になる唯一の機能。このダイアログを無効にした場合、ユーザーは通常、デバイスの電源をオフにできません。
LOCK_TASK_FEATURE_NOTIFICATIONS すべてのアプリの通知を有効にします。これにより、ステータスバー、ヘッドアップ通知、展開可能な通知シェードに通知アイコンが表示されるようになります。 このボタンを有効にする場合は、ホームボタンも有効にする必要があります。通知アクションや、新しいパネルを開くボタンをタップしても、ロックタスク モードでは機能しません。
LOCK_TASK_FEATURE_SYSTEM_INFO 接続、バッテリー、音やバイブレーションのオプションなどのインジケーターを含む、ステータスバーのシステム情報領域を有効にします。
LOCK_TASK_FEATURE_KEYGUARD デバイスに設定されているロック画面を有効にします。通常、情報キオスクやデジタル サイネージなど、一般ユーザーが使用するデバイスには適していません。
LOCK_TASK_FEATURE_NONE 上記のシステム UI 機能をすべて無効にします。

DPC は、ロックタスク モードが有効になっているときにデバイスで使用できる機能のリストを取得するために、DevicePolicyManager.getLockTaskFeatures() を呼び出すことができます。デバイスがロックタスク モードを終了すると、ユーザー インターフェースは既存のデバイス ポリシーで定められた状態に戻ります。

ウィンドウとオーバーレイをブロックする

アプリがロックタスク モードで実行されている場合、他のアプリやバックグラウンド サービスは新しいウィンドウを作成し、ロックタスク モードでアプリの前に Android に表示されます。アプリやサービスがこのウィンドウを作成し、デバイスを使用しているユーザーにトースト、ダイアログ、オーバーレイを表示します。DPC は、DISALLOW_CREATE_WINDOWS ユーザー制限を追加することで、このような問題を防止できます。次の例は、onLockTaskModeEntering() コールバックでこれを行う方法を示しています。

Kotlin

// Called just after entering lock task mode.
override fun onLockTaskModeEntering(context: Context, intent: Intent) {
    val dpm = getManager(context)
    val admin = getWho(context)

    dpm.addUserRestriction(admin, UserManager.DISALLOW_CREATE_WINDOWS)
}

Java

// Called just after entering lock task mode.
public void onLockTaskModeEntering(Context context, Intent intent) {
  DevicePolicyManager dpm = getManager(context);
  ComponentName admin = getWho(context);

  dpm.addUserRestriction(admin, UserManager.DISALLOW_CREATE_WINDOWS);
}

DPC は、デバイスがロックタスク モードを終了したときにユーザー制限を解除できます。

参考情報

専用デバイスの詳細については、以下のドキュメントをご覧ください。