Mehrere Nutzer testen

Auf dieser Seite werden wichtige Aspekte des Testens von Apps mit mehreren Nutzern auf der Android-Plattform beschrieben. Informationen zur Implementierung der Unterstützung mehrerer Nutzer finden Sie unter Mehrere Nutzer unterstützen.

Gerätepfade

In der folgenden Tabelle sind einige der Gerätepfade und die Art ihrer Auflösung aufgeführt. Alle Werte in der Spalte Pfad sind ein nutzerspezifischer Sandbox-Speicher. Die Speichersituation unter Android hat sich im Laufe der Zeit geändert. Weitere Informationen finden Sie in der Dokumentation zum Thema Speicher.

Pfad Systempfad (optional) Zweck
/data/user/{userId}/{app.path} /data/data App-Speicher
/storage/emulated/{userId} /sdcard Gemeinsam genutzter interner Speicher
/data/media/{userId} Keine Nutzer-Medieninhalte (z. B. Musik, Videos)
/data/system/users/{userId} Keine Systemkonfiguration/Status pro Nutzer

Nur für System-Apps zugänglich

Hier ein Beispiel für die Verwendung eines nutzerspezifischen Pfads:

# to access user 10's private application data for app com.bar.foo:
$ adb shell ls /data/user/10/com.bar.foo/

adb-Interaktionen zwischen Nutzern

Mehrere adb-Befehle sind nützlich, wenn Sie es mit mehreren Nutzern zu tun haben. Einige dieser Befehle werden nur unter Android 9 und höher unterstützt:

  • adb shell am instrument --user <userId> führt einen Instrumentierungstest für einen bestimmten Nutzer aus. Standardmäßig wird der aktuelle Nutzer verwendet.
  • Mit adb install --user <userId> wird ein Paket für einen bestimmten Nutzer installiert. Damit ein Paket für alle Nutzer installiert wird, müssen Sie diese Funktion für jeden Nutzer aufrufen.
  • Mit adb uninstall --user <userId> wird ein Paket für einen bestimmten Nutzer deinstalliert. Rufen Sie die Funktion ohne das Flag --user auf, um die App für alle Nutzer zu deinstallieren.
  • adb shell am get-current-user ruft die aktuelle (Vordergrund-)Nutzer-ID ab.
  • adb shell pm list users ruft eine Liste aller vorhandenen Nutzer ab.
  • Mit adb shell pm create-user wird ein neuer Nutzer erstellt und die ID zurückgegeben.
  • Mit adb shell pm remove-user wird ein bestimmter Nutzer anhand der ID entfernt.
  • Mit adb shell pm disable --user <userId> wird ein Paket für einen bestimmten Nutzer deaktiviert.
  • Mit adb shell pm enable --user <userId> wird ein Paket für einen bestimmten Nutzer aktiviert.
  • adb shell pm list packages --user <userId> listet Pakete (-e für aktiviert, -d für deaktiviert) für einen bestimmten Nutzer auf. Standardmäßig werden immer Listen für den Systemnutzer angezeigt.

Die folgenden Informationen helfen Ihnen, das Verhalten von adb bei mehreren Nutzern zu verstehen:

  • adb (oder genauer gesagt der adbd-Daemon) wird immer als Systemnutzer (Nutzer-ID = 0) ausgeführt, unabhängig davon, welcher Nutzer gerade aktiv ist. Daher werden gerätebezogene Pfade, die nutzerabhängig sind (z. B. /sdcard/), immer als Systemnutzer aufgelöst. Weitere Informationen finden Sie unter Gerätepfade.

  • Wenn kein Standardnutzer angegeben ist, hat jeder adb-Unterbefehl einen anderen Nutzer. Es hat sich bewährt, die Nutzer-ID mit am get-current-user abzurufen und dann --user <userId> explizit für alle Befehle zu verwenden, die sie unterstützen. Bis Android 9 wurden explizite Nutzer-Flags nicht für alle Befehle unterstützt.

  • Ab Android 9 wird der Zugriff auf /sdcard-Pfade von sekundären Nutzern verweigert. Weitere Informationen zum Abrufen von Dateien während des Testens finden Sie unter Contentanbieter für Daten für mehrere Nutzer.

Contentanbieter für Daten von mehreren Nutzern

Da adb als Systemnutzer ausgeführt wird und Daten in Android 9 und höher in einer Sandbox gespeichert werden, müssen Sie Content-Provider verwenden, um Testdaten von einem Nicht-Systemnutzer zu übertragen. Dies ist nicht erforderlich, wenn:

  • adbd wird als Root ausgeführt (über adb root), was nur mit userdebug- oder usereng-Builds möglich ist.

  • Sie verwenden ITestDevice von Trade Federation (Tradefed), um die Dateien zu übertragen. In diesem Fall verwenden Sie /sdcard/-Pfade in Ihrer Testkonfiguration (siehe z. B. den Quellcode für pushFile in NativeDevice.java).

Wenn ein Contentanbieter im sekundären Nutzer ausgeführt wird, können Sie darauf zugreifen, indem Sie den Befehl adb shell content mit den entsprechenden Parametern user, uri und anderen Parametern ausführen.

Problemumgehung für App-Entwickler

Verwenden Sie für die Interaktion mit Testdateien adb content und eine Instanz von ContentProvider anstelle des Befehls push oder pull.

  1. Erstellen Sie eine Instanz von ContentProvider, die von der App gehostet wird und Dateien bei Bedarf bereitstellen und speichern kann. Den internen Speicher der App verwenden
  2. Verwenden Sie die Befehle adb shell content read oder write, um die Dateien zu übertragen.

Problemumgehung für Mediendateien

Wenn Sie Mediendateien auf die Medienpartition der SD-Karte übertragen möchten, verwenden Sie die öffentlichen APIs von MediaStore. Beispiel:

# 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

Allgemeinen Contentanbieter installieren

Installieren und verwenden Sie einen vorhandenen Contentanbieter, der Dateien in den nutzerspezifischen Pfad /sdcard liest und schreibt.

Erstellen Sie TradefedContentProvider.apk aus der Quelle mit 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
```

Unterstützung mehrerer Nutzer in Trade Federation

Tradefed ist das offizielle Android-Test-Framework. In diesem Abschnitt wird die integrierte Unterstützung von Tradefed für Testläufe mit mehreren Nutzern zusammengefasst.

Statusprüfer

Systemstatusprüfungen (System Status Checkers, SSCs) werden vor den Zielvorbereitern ausgeführt und ihre Bereinigung erfolgt nach diesen Vorbereitern.

UserChecker wird explizit definiert, um Entwicklern beim Testen mehrerer Nutzer zu helfen. Es wird erfasst, ob durch einen Test der Status der Nutzer auf dem Gerät geändert wurde (z. B. ob Nutzer erstellt wurden, ohne sie im Teardown zu entfernen). Wenn user-cleanup festgelegt ist, wird außerdem automatisch versucht, nach dem Test aufzuräumen. Gleichzeitig werden hilfreiche Fehler ausgegeben, damit der Test behoben werden kann.

<system_checker class="com.android.tradefed.suite.checker.UserChecker" >
    <option name="user-cleanup" value="true" />
</system_checker>

Zielvorbereiter

Zielvorbereiter werden in der Regel verwendet, um ein Gerät mit einer bestimmten Konfiguration einzurichten. Bei Tests mit mehreren Nutzern können mit Preparers Nutzer eines bestimmten Typs erstellt und zu anderen Nutzern gewechselt werden.

Bei Gerätetypen, die keinen sekundären Nutzer haben, können Sie mit CreateUserPreparer einen sekundären Nutzer in AndroidTest.xml erstellen und zu ihm wechseln. Am Ende des Tests wechselt der Vorbereiter zurück und löscht den sekundären Nutzer.

<target_preparer
  class="com.google.android.tradefed.targetprep.CreateUserPreparer" >
</target_preparer>

Wenn der gewünschte Nutzertyp bereits auf dem Gerät vorhanden ist, verwenden Sie SwitchUserTargetPreparer, um zum vorhandenen Nutzer zu wechseln. Häufige Werte für user-type sind system oder secondary.

<target_preparer
  class="com.android.tradefed.targetprep.SwitchUserTargetPreparer">
    <option name="user-type" value="secondary" />
</target_preparer>

Hostgesteuerte Tests

In einigen Fällen muss bei einem Test innerhalb des Tests der Nutzer gewechselt werden. Nehmen Sie den Wechsel nicht über ein geräteseitiges Testframework wie UI Automator vor, da der Testprozess jederzeit beendet werden kann. Verwenden Sie stattdessen ein hostseitiges Test-Framework wie das Host-driven test framework von Tradefed, das Zugriff auf ITestDevice bietet und alle erforderlichen Nutzermanipulationen ermöglicht.

Verwenden Sie UserChecker (siehe Statusprüfungen) für hostgesteuerte Tests, bei denen sich der Nutzerstatus ändert, da so sichergestellt wird, dass der Test nach Abschluss ordnungsgemäß bereinigt wird.