工作资料

Android 平台允许设备 工作 个人资料(有时也称为受管理的个人资料)。工作资料受控 且可用的功能与 用户主要资料的功能这种方法可让组织控制 用户设备上运行公司专用应用和数据的环境; 同时仍允许用户使用自己的个人应用和个人资料。

本课将介绍如何修改应用以使其正常运行 在具有工作资料的设备上可靠地工作。您无需执行任何操作 除了普通的应用开发最佳实践之外,不过,其中一些 做法在具有工作资料的设备上尤为重要。这个 文档突出显示了您需要注意的问题。

概览

用户通常希望在企业环境中使用个人设备。这个 情况可能会给组织带来困境。如果用户可以使用自己的 组织必须担心机密信息(比如员工 电子邮件地址和联系人)的设备均不归单位控制。

为解决这一问题,Android 5.0(API 级别 21)允许组织 设置工作资料。如果设备设置了工作资料,则该资料的 设置均由 IT 管理员控制。通过 IT 管理员可以选择允许哪些应用使用该资料, 仅控制对个人资料可用的设备功能。

如果设备装有工作资料,则会对应用产生影响 无论应用在哪个配置文件下运行:

  • 默认情况下,大多数 intent 都不会从一个个人资料交叉到另一个个人资料。如果 在个人资料上运行的应用会触发 intent,但是 该个人资料,并且不允许传递至另一个人资料的 intent 由于配置文件限制,请求失败,应用可能会关闭 。
  • 个人资料的 IT 管理员可以限制 工作资料。此限制还可能导致没有适用于 工作资料的一些常见 intent。
  • 由于个人资料和工作资料具有单独的存储区域, 在一个个人资料中有效的文件 URI 在另一个个人资料中无效。不限 针对一个配置文件触发的 intent 可能会在另一个配置文件上处理(具体取决于配置文件 设置),因此将文件 URI 附加到 intent 并不安全。

防止失败的 intent

在具有工作资料的设备上,对 intent 是否 可以跨不同配置文件。在大多数情况下,当 intent 触发时 关闭,则系统会在触发该函数的同一配置文件中进行处理。如果没有处理程序 对于该个人资料上的 intent,系统不会处理该 intent,并且应用 但触发它的处理程序可能会意外关闭,即使 intent。

个人资料管理员可以选择要将哪些 intent 允许从一个配置文件跨越到另一个配置文件。由于 IT 管理员 就没有办法 以便事先了解允许哪些 intent 跨越此边界。通过 IT 管理员会设置此政策,并可随时更改它。

在您的应用启动 activity 之前,您应该验证是否存在 合适的分辨率。您 可通过调用 Intent.resolveActivity() 来验证是否有可接受的解决方案。如果没有 解析 intent 的方法,该方法会返回 null。如果该方法返回非 null 值,则至少有一种方法可以 就可以安全地触发 intent。在这种情况下, 意图也是可以解决的 因为当前个人资料上有一个处理程序,或者 intent 是 可以传递到另一配置文件上的处理程序。(如需详细了解 解析 intent,请参阅常见 intent)。

例如,如果您的应用需要设置计时器,则需要检查 存在 ACTION_SET_TIMER intent 的有效处理程序。如果应用无法解析 应执行适当的操作(例如显示错误), 消息)。

Kotlin

fun startTimer(message: String, seconds: Int) {

    // Build the "set timer" intent
    val timerIntent = Intent(AlarmClock.ACTION_SET_TIMER).apply {
        putExtra(AlarmClock.EXTRA_MESSAGE, message)
        putExtra(AlarmClock.EXTRA_LENGTH, seconds)
        putExtra(AlarmClock.EXTRA_SKIP_UI, true)
    }

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(packageManager) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent)

    }
}

Java

public void startTimer(String message, int seconds) {

    // Build the "set timer" intent
    Intent timerIntent = new Intent(AlarmClock.ACTION_SET_TIMER)
            .putExtra(AlarmClock.EXTRA_MESSAGE, message)
            .putExtra(AlarmClock.EXTRA_LENGTH, seconds)
            .putExtra(AlarmClock.EXTRA_SKIP_UI, true);

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(getPackageManager()) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent);

    }
}

跨资料共享文件

有时,应用需要向其他应用提供对自己文件的访问权限。 例如,图库应用可能希望分享其包含图片的图片 编辑。通常,您可以通过两种方式共享文件:与文件共享 URI内容 URI

文件 URI 以 file: 前缀开头,后跟 设备存储空间中的文件的绝对路径。不过,由于 工作资料和个人资料使用单独的存储区域,即一个文件 URI, 一项个人资料中有效的一项在另一个个人资料中无效。这种情况 这表示 将文件 URI 附加到 intent,系统将在另一个个人资料上处理该 intent, 处理程序无法访问该文件。

您应改用内容 URI 共享文件。内容 URI 更安全、可共享的方式识别文件。内容 URI 包含 文件路径,以及提供文件的授权方以及 ID 号 来标识文件您可以使用 FileProvider。然后,您可以将这些内容 ID 与其他应用的 ID(即使是在其他资料中)。接收者可以使用 内容 ID 来获取对实际文件的访问权限。

例如,以下代码段展示了如何获取特定文件的内容 URI URI:

Kotlin

// Open File object from its file URI
val fileToShare = File(fileUriToShare)

val contentUriToShare: Uri = FileProvider.getUriForFile(
        context,
        "com.example.myapp.fileprovider",
        fileToShare
)

Java

// Open File object from its file URI
File fileToShare = new File(fileUriToShare);

Uri contentUriToShare = FileProvider.getUriForFile(getContext(),
        "com.example.myapp.fileprovider", fileToShare);

当您调用 getUriForFile() 方法时, 您必须添加文件提供者的授权(在此示例中, "com.example.myapp.fileprovider"),后者是在 <provider> 元素。 如需详细了解如何共享带有内容 URI 的文件,请参阅 共享 文件

监听通知

应用通常提供 NotificationListenerService 子类 从系统接收有关通知更改的回调。符合以下条件的设备: 工作资料可能会影响“NotificationListenerService”的运作方式 应用互动情况

在工作资料中

您无法通过应用使用NotificationListenerService 正在通过工作资料运行当您的应用在工作资料中运行时, 系统将忽略应用的 NotificationListenerService。不过, 在个人资料中运行的应用可以监听通知。

在个人资料中

当应用在个人资料中运行时,您可能不会收到任何通知 (针对在工作资料中运行的应用)。默认情况下,所有个人资料应用 接收回电,但 IT 管理员可以将一份或多份个人资料列入许可名单 并允许其监听通知更改的应用。然后,系统会阻止 未列入许可名单的应用。在 Android 8.0(API 级别 26)或更高版本中,设备政策 管理工作资料的控制器 (DPC) 可能会阻止您的应用监听 使用 DevicePolicyManager 来获取工作资料的通知 方法 setPermittedCrossProfileNotificationListeners()。 您的应用仍会收到有关个人 个人资料。

测试您的应用与工作资料的兼容性

您应在工作资料环境中测试您的应用, 利用 工作资料。特别是,在装有工作资料的设备上进行测试 确保应用正确处理 intent 的方法: 不附加无法跨资料工作的 URI,等等 。

我们提供了一个示例应用 TestDPC, 可用于在运行 Android 5.0(API 级别 21)及更高版本。此应用提供了一种简单的测试方法, 在工作资料环境中使用您的应用您还可以使用此应用执行以下操作: 按如下方式配置工作资料:

  • 指定在受管理的设备上提供哪些默认应用 个人资料
  • 配置允许从一个配置文件跨越哪些 intent 另一个

如果您通过 USB 线将应用程序手动安装到配备 工作资料,则应用会同时安装到个人和工作 个人资料。安装应用后,您可以在 以下条件:

  • 如果 intent 通常由默认应用(例如, 相机应用),尝试在工作资料中停用默认应用,然后 验证应用会妥善处理这种情况。
  • 如果您触发一个预期会由其他应用处理的 intent,请尝试 启用和禁用该 intent 的权限,以从一个配置文件跨越到另一个配置文件 另一个。验证应用在这两种情况下是否都正常运行。如果 intent 不得跨个人资料,请验证应用的行为 当应用的配置文件上是否有合适的处理程序时以及何时没有合适的处理程序。 例如,如果您的应用触发与地图相关的 intent,请尝试以下各项操作: 场景: <ph type="x-smartling-placeholder">
      </ph>
    • 设备允许映射 intent 从一个个人资料交叉到另一个个人资料,并且 另一个个人资料(应用不是该个人资料的个人资料)上存在合适的处理程序 运行组件)
    • 设备不允许地图 intent 跨个人资料跨越,但存在 是应用配置文件的合适处理程序
    • 设备不允许在个人资料之间跨越地图 intent,并且 不是设备资料上的地图 intent 的合适处理程序
  • 如果您将内容附加到 intent,请验证 intent 行为是否正常 无论是在应用配置文件上处理,还是在 个人资料。

在工作资料上测试:提示和技巧

有一些技巧可能有助于您在 工作资料设备

  • 如上所述,在装有工作资料的设备上旁加载应用时 两个资料中都安装了此 SDK。如果需要,您可以从一份个人资料中删除应用程序 并将其留在另一台上
  • Android 调试桥 (adb) shell 中提供的大多数 activity 管理器命令 支持 --user 标志,该标志可让您指定要运行哪个用户 名称。通过指定用户,您可以选择是否以非受管主要用户的身份运行 或工作资料有关详情,请参阅 ADB Shell 命令
  • 要查找设备上的活跃用户,请使用 adb 软件包管理器的 list users 命令。输出字符串中的第一个数字是 用户 ID,可与 --user 标志搭配使用。有关 相关信息,请参阅 ADB Shell 命令

例如,如需查找某个设备上的用户,您可以运行以下命令:

$ adb shell pm list users
UserInfo{0:Drew:13} running
UserInfo{10:Work profile:30} running

在这种情况下,主要用户(“Drew”)的用户 ID 为 0,而 工作资料的用户 ID 为 10。如需在工作资料中运行应用,您需要 将使用如下命令:

$ adb shell am start --user 10 \
-n "com.example.myapp/com.example.myapp.testactivity" \
-a android.intent.action.MAIN -c android.intent.category.LAUNCHER