本页介绍了在 Android 平台上测试多用户的一些重要方面。如需了解如何实现多用户支持,请参阅支持多用户。
设备路径
下表列出了几条设备路径及其解析方式。路径列中的所有值都是用户专用的沙盒化存储空间。Android 的存储方案多年间历有变化;如需了解详情,请阅读存储文档。
路径 | 系统路径(可选) | 用途 |
---|---|---|
/data/user/{userId}/{app.path}
|
/data/data
|
应用存储空间 |
/storage/emulated/{userId}
|
/sdcard
|
共享内部存储空间 |
/data/media/{userId}
|
无 | 用户媒体数据(例如,音乐和视频) |
/data/system/users/{userId}
|
无 | 每个用户的系统配置/状态
只能由系统应用访问 |
下面是一个使用用户专用路径的示例:
# to access user 10's private application data for app com.bar.foo:
$ adb shell ls /data/user/10/com.bar.foo/
跨用户的 adb 互动
在处理多用户时,有几个 adb
命令很有用。但其中部分命令仅 Android 9 及更高版本才支持:
adb shell am instrument --user <userId>
可针对特定用户运行插桩测试。默认情况下,此命令使用当前用户。adb install --user <userId>
可为特定用户安装软件包。要确保为所有用户安装软件包,您必须为每个用户调用此命令。adb uninstall --user <userId>
可为特定用户卸载软件包。如果调用此命令时不带--user
标记,可为所有用户卸载软件包。adb shell am get-current-user
可获取当前(前台)用户 ID。adb shell pm list users
可获取所有现有用户的列表。adb shell pm create-user
可创建新用户并返回 ID。adb shell pm remove-user
可按 ID 移除特定用户。adb shell pm disable --user <userId>
可为特定用户停用软件包。adb shell pm enable --user <userId>
可为特定用户启用软件包。adb shell pm list packages --user <userId>
可为特定用户列出软件包(-e
可列出已启用的软件包,-d
可列出已停用的软件包)。默认情况下,此命令始终为系统用户列出软件包。
以下信息有助于说明 adb
在多用户条件下的行为方式:
adb
(或者更准确地说,是adbd
守护程序)始终以系统用户(用户 ID = 0)身份运行,而不管当前用户是哪个用户。因此,取决于用户的设备路径(如/sdcard/
)始终会被解析为系统用户的路径。如需了解详情,请参阅设备路径。如果未指定默认用户,则每个
adb
子命令都有一个不同的用户。最佳做法是使用am get-current-user
检索用户 ID,然后明确地对支持--user <userId>
的所有命令使用该标记。在 Android 9 之前,并非所有命令都支持显式用户标记。从 Android 9 开始,访问次要用户的
/sdcard
路径的请求会被拒。如需详细了解如何在测试期间检索文件,请参阅多用户数据的内容提供程序。
多用户数据的 content provider
由于 adb
以系统用户身份运行且数据在 Android 9 及更高版本中进行了沙盒化处理,因此您必须使用 content provider,才能向非系统用户推送测试数据或从此类用户处提取测试数据。但在以下情况下,没有必要这样做:
adbd
正在以 root 用户身份运行(通过adb root
),这只有使用userdebug
或usereng
build 才能做到。您正在使用 Trade Federation (Tradefed) 的
ITestDevice
来推送或提取文件,在这种情况下,会在您的测试配置中使用/sdcard/
路径(如需查看示例,请参阅NativeDevice.java
中pushFile
的源代码)。
当 content provider 正在由次要用户运行时,您可以使用 adb shell content
命令(指定了适当的 user
、uri
及其他参数)对其进行访问。
应用开发者可用的权宜解决方案
使用 adb content
和 ContentProvider
实例(而不是 push
或 pull
命令)与测试文件互动。
- 创建由应用托管的
ContentProvider
实例,该实例可在需要时提供和存储文件。使用应用的内部存储空间。 - 使用
adb shell content
read
或write
命令来推送或提取文件。
针对媒体文件的权宜解决方案
如需将媒体文件推送到 SD 卡的 media 分区,请使用 MediaStore
公共 API。例如:
# push MVIMG_20190129_142956.jpg to /storage/emulated/10/Pictures
# step 1
$ adb shell content insert --user 10 --uri content://media/external/images/media/ --bind _display_name:s:foo.jpg
# step 2
$ adb shell content query --user 10 --projection _id --uri content://media/external/images/media/ --where "_display_name=\'foo.jpg\'"
# step 3
$ adb shell content write --user 10 --uri content://media/external/images/media/8022 < MVIMG_20190129_142956.jpg
安装通用 content provider
安装并使用可从用户专用 /sdcard
路径读取文件并向其中写入文件的现有 content provider。
使用 make TradefedContentProvider
根据源代码构建 TradefedContentProvider.apk
:
```
# install content provider apk
$ adb install --user 10 -g TradefedContentProvider.apk
# pull some_file.txt
$ adb shell content read --user 10 --uri content://android.tradefed.contentprovider/sdcard/some_file.txt > local_file.txt
# push local_file.txt
$ adb shell content write --user 10 --uri content://android.tradefed.contentprovider/sdcard/some_file.txt < local_file.txt
```
Trade Federation 多用户支持
Tradefed 是官方的 Android 自动化测试框架。本部分总结了 Tradefed 针对多用户测试场景提供的一些内置支持。
状态检查器
系统状态检查器 (SSC) 在目标准备器之前运行,而其清理任务在这些准备器之后运行。
明确定义了 UserChecker
,以便在测试多用户时协助开发者。它会跟踪测试是否改变了设备上用户的状态(例如,创建了用户而未在拆解阶段将其移除)。此外,如果设置了 user-cleanup
,它会在测试后自动尝试清理,同时仍提供有用的错误消息,以便您修复测试。
<system_checker class="com.android.tradefed.suite.checker.UserChecker" >
<option name="user-cleanup" value="true" />
</system_checker>
目标准备器
目标准备器通常用于设置具有特定配置的设备。对于多用户测试,准备器可用于创建特定类型的用户以及切换到其他用户。
对于没有次要用户的设备类型,您可以在 AndroidTest.xml
中使用 CreateUserPreparer
创建并切换到次要用户。在测试结束时,准备器会切换回系统用户并删除次要用户。
<target_preparer
class="com.google.android.tradefed.targetprep.CreateUserPreparer" >
</target_preparer>
如果设备上已存在您想要的用户类型,请使用 SwitchUserTargetPreparer
切换到现有用户。user-type
的常见值包括 system
或 secondary
。
<target_preparer
class="com.android.tradefed.targetprep.SwitchUserTargetPreparer">
<option name="user-type" value="secondary" />
</target_preparer>
主机驱动的测试
在某些情况下,测试需要在测试过程中切换用户。请不要在设备端测试框架(如 UI Automator)中进行切换,因为测试过程可能会随时终止。应使用主机端测试框架(如 Tradefed 的主机驱动型测试框架),通过此类框架可访问 ITestDevice
,从而能够进行所需的任何用户操控。
对于会改变用户状态的主机驱动型测试,应使用 UserChecker
(在状态检查器中做了介绍),因为它可确保测试在结束后正确地自行清理。