锁定任务模式

本开发者指南介绍了如何将专用设备锁定为 应用还是一组应用如果您提供企业移动管理 (EMM) 服务 开发者或解决方案集成商阅读本指南,了解如何向您的 解决方案。

概览

Android 能够以类似于自助服务终端的沉浸式方式(称为锁定任务)运行任务 模式。如果您要开发自助服务终端应用,可以使用锁定任务模式, 用于呈现一系列应用的启动器。当系统在锁定任务中运行时 模式,设备用户通常无法看到通知,也无法访问 应用或返回主屏幕(除非主屏幕已列入许可名单)。

只有已被设备政策控制器 (DPC) 列入许可名单的应用才能运行 当系统处于锁定任务模式时触发。应用已被列入许可名单,因为 使用设备时有时无法退出锁定任务模式。

如何将已列入锁定任务模式许可名单的应用与列入许可名单的 DPC 结合使用 具体取决于您想要解决的问题。以下是一些示例:

  • 结合自助服务终端(用于展示内容)和迷你 DPC 的单个应用软件包 (以便将自身列入许可名单,以便使用锁定任务模式)。
  • 作为企业移动管理解决方案一部分的 DPC,发布 客户的移动应用处于锁定任务模式

可用性

在 Android 5.0 或更高版本中,系统可以在锁定任务模式下运行。表 1 显示 哪些 Android 版本支持按用户将应用列入许可名单。

表 1.针对 DPC 管理模式的 Android 版本支持
Android 版本 DPC 管理者 备注
Android 5.0(API 级别 21)或更高版本 全托管式设备
Android 8.0(API 级别 26)或更高版本 关联的次要用户 次要用户必须与主要用户相关联。请参阅 多用户概览。
Android 9.0(API 级别 28)或更高版本 次要用户

在 Android 9.0 或更高版本中,DPC 可启动任何应用的 activity 进入锁定任务模式。 在早期版本中,应用必须已支持在 锁定任务模式。

将应用列入许可名单

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)或更高版本中,您可以在 锁定任务模式。如果某个 activity 已在前台运行,或 您需要重新启动 activity。致电 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 模式(通过调用 Activity.startLockTask())。要调用 方法,Activity 必须在前台运行(请参阅 Activity-lifecycle 概念),因此我们建议您调用 ActivityonResume() 方法或 Fragment。调用 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()) 启动锁定任务模式。

处于锁定任务模式的应用可以启动新的 activity,前提是该 activity 不启动新任务(启动已列入许可名单的应用的任务除外)。接收者 了解任务与活动的关系,请参阅了解任务和 返回堆栈

或者,您也可以在应用清单中声明 activity 在以下情况下的行为方式: 系统正在锁定任务模式下运行。让系统自动运行 处于锁定任务模式的 activity 中,将 android:lockTaskMode 属性将 if_whitelisted 设为 如以下示例中所示:

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

如需详细了解如何在应用清单文件中声明选项,请参阅 lockTaskMode 引用。

停止锁定任务模式

DPC 可通过从 DPC 应用软件包中移除应用软件包,远程停止锁定任务模式 许可名单。致电 DevicePolicyManager.setLockTaskPackages(),位于 Android 6.0(API 级别 23)或更高版本,并且省略了 许可名单数组。更新许可名单后,应用会恢复为之前的许可名单 一个任务。

如果一个 activity 之前调用了 startLockTask(),则该 activity 可以调用 用于停止锁定任务模式的 Activity.stopLockTask()。此方法 仅适用于启动锁定任务模式的 activity。

生命周期回调

您的 DPC 可能会发现,了解某个应用(在同一用户中运行)何时会非常有用 进入和退出锁定任务模式。如需接收回调,请替换以下内容 DPC 的 DeviceAdminReceiver 子类中的回调方法:

onLockTaskModeEntering()
在应用进入锁定任务模式后调用。您可以获取 从 pkg 参数调用 app bundle。
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 ...
}

自定义界面

当应用在锁定任务模式下运行时, 方法:

  • 状态栏空白,并隐藏通知和系统信息。
  • “主页”和“概览”按钮处于隐藏状态。
  • 其他应用无法启动新活动。
  • 锁定屏幕(如果已设置)处于停用状态。

在 Android 9.0 或更高版本中,启用锁定任务模式后,您的 DPC 可以启用 设备上的某些系统界面功能,这对于创建自定义 启动器。致电 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 参数中的所有功能。通过 启用的界面功能在启动到锁定任务模式之间会保留。如果设备 已处于锁定任务模式,则您对锁定任务功能所做的任何更改 立即展示。表 2 介绍了您可以自定义的界面功能。

表 2.锁定任务模式下的可自定义系统界面功能
系统界面功能 说明
LOCK_TASK_FEATURE_HOME 显示“主页”按钮。为自定义启动器启用 - 点按已启用的 除非您将默认 Android 设备列入许可名单,否则主屏幕按钮不会执行任何操作 启动器。
LOCK_TASK_FEATURE_OVERVIEW 显示“概览”按钮(点按此按钮可打开 最近屏幕)。如果您 启用此按钮,还必须启用“主页”按钮。
LOCK_TASK_FEATURE_GLOBAL_ACTIONS 启用全局操作对话框,长按 电源按钮。选中该复选框后 setLockTaskFeatures() 尚未调用。在以下情况下,用户通常无法将设备关机: 停用此对话框。
LOCK_TASK_FEATURE_NOTIFICATIONS 为所有应用启用通知。这会在 状态栏、浮动通知和可展开的通知栏。 如果要启用此按钮,则还必须启用“主页”按钮。点按 用于打开新面板的通知操作和按钮在锁定状态下不起作用 任务模式。
LOCK_TASK_FEATURE_SYSTEM_INFO 启用状态栏的系统信息区域,其中包含 例如连接、电池、声音和振动选项。
LOCK_TASK_FEATURE_KEYGUARD 启用设备上可能已设置的任何锁定屏幕。通常不需要 设备(如信息亭或 数字标牌。
LOCK_TASK_FEATURE_NONE 停用上面列出的所有系统界面功能。

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 可移除用户限制。

其他资源

如需详细了解专用设备,请参阅以下文档: