На этой странице описаны важные аспекты тестирования многопользовательского режима на платформе 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получает идентификатор текущего (активного) пользователя. -
adb shell pm list usersполучает список всех существующих пользователей. -
adb shell pm create-userсоздает нового пользователя, возвращая его идентификатор. -
adb shell pm remove-userудаляет конкретного пользователя по идентификатору. -
adb shell pm disable --user <userId>отключает пакет для конкретного пользователя. -
adb shell pm enable --user <userId>включает пакет для конкретного пользователя. -
adb shell pm list packages --user <userId>выводит список пакетов (-eдля включенных,-dдля отключенных) для конкретного пользователя. По умолчанию она всегда выводит список для системного пользователя.
Следующая информация поможет объяснить, как adb работает с несколькими пользователями:
adb(точнее, демонadbd) всегда запускается от имени системного пользователя (идентификатор пользователя = 0) независимо от того, какой пользователь является текущим . Поэтому пути к устройствам, зависящие от пользователя (например/sdcard/), всегда разрешаются от имени системного пользователя. Дополнительные сведения см. в разделе «Пути к устройствам» .Если пользователь по умолчанию не указан, каждая подкоманда
adbбудет использовать своего пользователя. Рекомендуется получать идентификатор пользователя с помощьюam get-current-user, а затем явно указывать--user <userId>для любой команды, которая его поддерживает. Явное указание пользовательских флагов стало поддерживаться не для всех команд до Android 9.Начиная с Android 9, доступ к путям
/sdcardдополнительных пользователей запрещен. Подробную информацию о том, как получить доступ к файлам во время тестирования, см. в разделе «Поставщик контента для многопользовательских данных» .
Поставщик контента для многопользовательских данных
Поскольку adb запускается от имени системного пользователя, а данные хранятся в изолированной среде в Android 9 и выше, для отправки или получения тестовых данных от пользователя, не являющегося системным, необходимо использовать поставщиков контента. Это не требуется, если:
adbdзапускается от имени root (черезadb root), что возможно только при использовании сборокuserdebugилиusereng.Вы используете
ITestDeviceот Trade Federation (Tradefed) для отправки или получения файлов, в этом случае используйте пути/sdcard/в конфигурации теста (например, см. исходный код функцииpushFileвNativeDevice.java).
Если поставщик контента запущен от имени вторичного пользователя, вы можете получить к нему доступ, используя команду adb shell content с указанием соответствующего user , uri и других параметров.
Временное решение для разработчиков приложений
Взаимодействуйте с тестовыми файлами, используя adb content и экземпляр ContentProvider , вместо команд push или pull .
- Создайте экземпляр
ContentProvider, размещенный в приложении, который сможет предоставлять доступ к файлам и хранить их там, где это необходимо. Используйте внутреннее хранилище приложения. - Используйте команды
adb shell contentreadилиwriteдля отправки или получения файлов.
Временное решение для медиафайлов
Для записи медиафайлов в медиараздел SD-карты используйте общедоступные API MediaStore . Например:
# 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
Установите универсальный поставщик контента.
Установите и используйте существующий поставщик контента, который читает и записывает файлы в указанный пользователем путь /sdcard .
Соберите файл TradefedContentProvider.apk из исходного кода, используя make TradefedContentProvider :
```
# 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
```
Поддержка нескольких пользователей Торговой федерации
Tradefed — это официальная тестовая платформа для Android. В этом разделе кратко описаны некоторые встроенные функции Tradefed для многопользовательских тестовых сценариев.
Проверки статуса
Перед подготовкой целевых объектов запускаются средства проверки состояния системы (SSC) , а после них выполняется очистка.
UserChecker специально разработан для помощи разработчикам при тестировании нескольких пользователей. Он отслеживает, изменил ли тест состояние пользователей на устройстве (например, создал пользователей, не удалив их при завершении работы). Кроме того, если задан параметр user-cleanup , он автоматически пытается выполнить очистку после теста, при этом предоставляя полезные сообщения об ошибках, чтобы тест можно было исправить.
<system_checker class="com.android.tradefed.suite.checker.UserChecker" >
<option name="user-cleanup" value="true" />
</system_checker>
Подготовка мишеней
Инструменты подготовки целевых устройств обычно используются для настройки устройства с определенной конфигурацией. В случае многопользовательского тестирования инструменты подготовки могут использоваться для создания пользователей определенного типа, а также для переключения на других пользователей.
Для типов устройств, не имеющих дополнительного пользователя, можно использовать CreateUserPreparer для создания и переключения на дополнительного пользователя в AndroidTest.xml . По завершении теста подготовитель переключается обратно на дополнительного пользователя и удаляет его.
<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 , поскольку процесс тестирования может быть завершен в любой момент. Вместо этого используйте фреймворк для тестирования на стороне хоста, например, Host-driven test framework от Tradefed, который предоставляет доступ к ITestDevice , позволяя выполнять любые необходимые манипуляции с пользователями.
Используйте UserChecker (описано в разделе «Проверка состояния ») для управляемых хостом тестов, изменяющих состояние пользователя, поскольку он гарантирует, что тест должным образом завершит очистку после себя.