Codelab zur Activity Recognition Transition API

1. Einführung

Wir haben unsere Smartphones immer dabei. Bisher war es jedoch schwierig für Apps, ihre Funktionen an die sich ständig ändernden Umgebungen und Aktivitäten der Nutzer anzupassen.

Bisher mussten Entwickler dafür wertvolle Zeit aufwenden, um verschiedene Signale (Standort,Sensor usw.) zu kombinieren und so zu ermitteln, wann eine Aktivität wie Gehen oder Autofahren begonnen oder geendet hat. Noch schlimmer ist es, wenn Apps unabhängig voneinander und kontinuierlich nach Änderungen der Nutzeraktivität suchen. Das kann sich negativ auf die Akkulaufzeit auswirken.

Die Activity Recognition Transition API löst diese Probleme, indem sie eine einfache API bereitstellt, die die gesamte Verarbeitung für Sie übernimmt und Ihnen nur das mitteilt, was Sie wirklich interessiert: wenn sich die Aktivität eines Nutzers geändert hat. Ihre App abonniert einfach einen Übergang bei Aktivitäten, die Sie interessieren, und die API benachrichtigt Sie über die Änderungen.

Eine Messaging-App kann beispielsweise fragen: „Informiere mich, wenn der Nutzer in ein Fahrzeug ein- oder aus einem Fahrzeug aussteigt“, um den Status des Nutzers auf „Beschäftigt“ zu setzen. Eine App zur Parkerkennung kann beispielsweise fragen: „Benachrichtige mich, wenn der Nutzer ein Fahrzeug verlassen hat und losgelaufen ist“, um den Parkplatz des Nutzers zu speichern.

In diesem Codelab erfahren Sie, wie Sie mit der Activity Recognition Transition API (API zur Erkennung von Aktivitätsübergängen) ermitteln, wann ein Nutzer eine Aktivität wie Gehen oder Laufen beginnt oder beendet.

Voraussetzungen

Vertrautheit mit der Android-Entwicklung und mit Callbacks.

Lerninhalte

  • Registrieren für Aktivitätsübergänge
  • Diese Ereignisse verarbeiten
  • Registrierung für Aktivitätsübergänge aufheben, wenn sie nicht mehr benötigt werden

Voraussetzungen

  • Android Studio Bumblebee
  • Ein Android-Gerät oder ein Emulator

2. Erste Schritte

Repository des Starterprojekts klonen

Damit Sie so schnell wie möglich loslegen können, haben wir ein Starterprojekt für Sie vorbereitet. Wenn Sie Git installiert haben, können Sie einfach den folgenden Befehl ausführen. Sie können das überprüfen, indem Sie git --version in das Terminal bzw. die Befehlszeile eingeben und prüfen, ob der Befehl korrekt ausgeführt wird.

 git clone https://github.com/android/codelab-activity_transitionapi

Wenn Sie Git nicht haben, können Sie das Projekt als ZIP-Datei herunterladen:

Projekt importieren

Starten Sie Android Studio, wählen Sie auf dem Begrüßungsbildschirm „Open an existing Android Studio project“ (Vorhandenes Android Studio-Projekt öffnen) aus und öffnen Sie das Projektverzeichnis.

Nachdem das Projekt geladen wurde, wird möglicherweise eine Warnung angezeigt, dass Git nicht alle lokalen Änderungen verfolgt. Sie können oben rechts auf Ignorieren oder auf das X klicken. Sie übertragen keine Änderungen zurück an das Git-Repository.

Wenn Sie sich in der Ansicht Android befinden, sollte links oben im Projektfenster etwas wie im Bild unten zu sehen sein. Wenn Sie sich in der Ansicht Projekt befinden, müssen Sie das Projekt maximieren, um dasselbe zu sehen.

d2363db913d8e5ad.png

Es gibt zwei Ordnersymbole (base und complete), die jeweils als „Modul“ bezeichnet werden.

Beachten Sie, dass es einige Sekunden dauern kann, bis Android Studio das Projekt zum ersten Mal im Hintergrund kompiliert hat. Während dieser Zeit wird in der Statusleiste unten in Android Studio ein rotierendes Ladesymbol angezeigt:

c9f23d5336be3cfe.png

Wir empfehlen, mit Codeänderungen zu warten, bis dieser Vorgang abgeschlossen ist. Dadurch kann Android Studio alle erforderlichen Komponenten abrufen.

Wenn Sie außerdem eine Aufforderung wie „Neu laden, damit die Sprachänderungen wirksam werden?“ erhalten, wählen Sie „Ja“ aus.

Startprojekt kennenlernen

Sie haben alles eingerichtet und können jetzt die Aktivitätserkennung hinzufügen. Wir verwenden das Modul base, das den Ausgangspunkt für dieses Codelab bildet. Das bedeutet, dass Sie base Code aus jedem Schritt hinzufügen.

Das complete-Modul kann verwendet werden, um Ihre Arbeit zu überprüfen oder als Referenz, wenn Sie auf Probleme stoßen.

Übersicht über die wichtigsten Komponenten:

  • MainActivity: Enthält den gesamten Code, der für die Aktivitätserkennung erforderlich ist.

Einrichtung des Emulators

Wenn Sie Hilfe beim Einrichten eines Android-Emulators benötigen, lesen Sie den Artikel App ausführen.

Startprojekt ausführen

Führen wir die App aus.

  • Verbinden Sie Ihr Android-Gerät mit dem Computer oder starten Sie einen Emulator.
  • Wählen Sie in der Symbolleiste die base-Konfiguration aus dem Drop-down-Menü aus und klicken Sie daneben auf das grüne Dreieck (Ausführen):

a640a291ffaf62ad.png

  • Die Anwendung sollte unten angezeigt werden:

f58d4bb92ee77f41.png

  • Die App gibt jetzt nur noch eine Meldung aus. Wir fügen jetzt die Aktivitätserkennung hinzu.

Zusammenfassung

In diesem Schritt haben Sie Folgendes gelernt:

  • Allgemeine Einrichtung für das Codelab.
  • Die Grundlagen unserer App
  • So stellen Sie Ihre App bereit.

3. Bibliothek prüfen und Berechtigung zum Manifest hinzufügen

Wenn Sie die Transition API in Ihrer App verwenden möchten, müssen Sie eine Abhängigkeit von der Google Location and Activity Recognition API deklarieren und die Berechtigung „com.google.android.gms.permission.ACTIVITY_RECOGNITION“ im App-Manifest angeben.

  1. Suchen Sie in der Datei „build.gradle“ nach TODO: Review play services library required for activity recognition. Für diesen Schritt (Schritt 1) ist keine Aktion erforderlich. Sie müssen lediglich die deklarierte Abhängigkeit prüfen, die wir benötigen. Das sollte so aussehen:
    // TODO: Review play services library required for activity recognition.
    implementation 'com.google.android.gms:play-services-location:19.0.1'
  1. Suchen Sie im Modul base im AndroidManifest.xml nach TODO: Add both activity recognition permissions to the manifest und fügen Sie dem <manifest>-Element den folgenden Code hinzu.
<!-- TODO: Add both activity recognition permissions to the manifest. -->
<!-- Required for 28 and below. -->
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<!-- Required for 29+. -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />

Ihr Code sollte nun in etwa so aussehen:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.example.myapp">
<!-- TODO: Add both activity recognition permissions to the manifest. -->
<!-- Required for 28 and below. -->
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<!-- Required for 29+. -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />

  ...
</manifest>

Wie Sie den Kommentaren entnehmen können, müssen Sie für Android 10 eine zweite Berechtigung hinzufügen. Dies ist für die Laufzeitberechtigung erforderlich, die in API-Version 29 hinzugefügt wurde.

Fertig! Ihre App kann jetzt die Aktivitätserkennung unterstützen. Wir müssen nur noch den Code dafür hinzufügen.

Lauf-App

Führen Sie Ihre App in Android Studio aus. Sie sollte genau gleich aussehen. Wir haben noch keinen Code zum Erfassen von Übergängen hinzugefügt. Das erfolgt im nächsten Abschnitt.

4. Laufzeitberechtigungen in Android prüfen/anfordern

Für API-Version 28 und niedriger haben wir die Berechtigung, aber für API-Version 29 und höher müssen wir Laufzeitberechtigungen unterstützen:

  • Im MainActivity.java prüfen wir, ob der Nutzer Android 10 (29) oder höher verwendet. Wenn das der Fall ist, prüfen wir die Berechtigungen zur Aktivitätserkennung.
  • Wenn Berechtigungen nicht erteilt werden, wird der Nutzer zu einem Splash-Screen (PermissionRationalActivity.java) weitergeleitet, auf dem erklärt wird, warum die App die Berechtigung benötigt. Dort kann er sie dann genehmigen.

Code zur Überprüfung der Android-Version prüfen

Suchen Sie im Modul base in MainActivity.java nach TODO: Review check for devices with Android 10 (29+). Dieses Code-Snippet sollte angezeigt werden.

Hinweis: Für diesen Abschnitt ist keine Aktion erforderlich.

// TODO: Review check for devices with Android 10 (29+).
private boolean runningQOrLater =
    android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q;

Wie bereits erwähnt, benötigen Sie unter Android 10 und höher eine Genehmigung für die Laufzeitberechtigung android.permission.ACTIVITY_RECOGNITION. Anhand dieser einfachen Prüfung wird entschieden, ob die Laufzeitberechtigungen geprüft werden müssen.

Bei Bedarf Laufzeitberechtigungsprüfung für die Aktivitätserkennung überprüfen

Suchen Sie im Modul base in MainActivity.java nach TODO: Review permission check for 29+. Dieses Code-Snippet sollte angezeigt werden.

Hinweis: Für diesen Abschnitt ist keine Aktion erforderlich.

// TODO: Review permission check for 29+.
if (runningQOrLater) {

   return PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(
           this,
           Manifest.permission.ACTIVITY_RECOGNITION
   );
} else {
   return true;
}

Wir verwenden die im vorherigen Schritt erstellte Variable, um zu prüfen, ob wir Laufzeitberechtigungen benötigen.

Bei Android Q und höher prüfen wir die Laufzeitberechtigung und geben das Ergebnis zurück. Dies ist Teil einer größeren Methode namens activityRecognitionPermissionApproved(), mit der der Entwickler in einem einfachen Aufruf erfahren kann, ob eine Berechtigung angefordert werden muss oder nicht.

Laufzeitberechtigungen anfordern und Übergänge für die Aktivitätserkennung aktivieren/deaktivieren

Suchen Sie im base-Modul in MainActivity.java nach TODO: Enable/Disable activity tracking and ask for permissions if needed. Fügen Sie den folgenden Code nach dem Kommentar ein.

// TODO: Enable/Disable activity tracking and ask for permissions if needed.
if (activityRecognitionPermissionApproved()) {

   if (activityTrackingEnabled) {
      disableActivityTransitions();

   } else {
      enableActivityTransitions();
   }

} else {  
   // Request permission and start activity for result. If the permission is approved, we
   // want to make sure we start activity recognition tracking.
   Intent startIntent = new Intent(this, PermissionRationalActivity.class);
   startActivityForResult(startIntent, 0);

}

Hier werden Sie gefragt, ob die Aktivitätserkennung genehmigt werden soll. Wenn das der Fall ist und die Aktivitätserkennung bereits aktiviert ist, deaktivieren wir sie. Andernfalls aktivieren wir sie.

Wenn die Berechtigung nicht genehmigt wird, leiten wir den Nutzer zum Splash-Screen weiter, auf dem erklärt wird, warum wir die Berechtigung benötigen, und auf dem er sie aktivieren kann.

Code für Berechtigungsanfrage prüfen

Suchen Sie im Modul base in PermissionRationalActivity.java nach TODO: Review permission request for activity recognition (TODO: Berechtigungsanfrage für die Aktivitätserkennung überprüfen). Dieses Code-Snippet sollte angezeigt werden.

Hinweis: Für diesen Abschnitt ist keine Aktion erforderlich.

// TODO: Review permission request for activity recognition.
ActivityCompat.requestPermissions(
             this,
             new String[]{Manifest.permission.ACTIVITY_RECOGNITION},
             PERMISSION_REQUEST_ACTIVITY_RECOGNITION)

Das ist der wichtigste Teil der Aktivität und der Teil, den Sie überprüfen sollten. Der Code löst die Anfrage für die Berechtigung aus, wenn der Nutzer sie anfordert.

Außerdem wird in der Klasse PermissionRationalActivity.java eine Begründung dafür angezeigt, warum der Nutzer die Berechtigung zur Aktivitätserkennung genehmigen sollte (Best Practice). Der Nutzer kann entweder auf die Schaltfläche Nein, danke oder auf die Schaltfläche Weiter klicken (wodurch der oben genannte Code ausgelöst wird).

Wenn Sie mehr erfahren möchten, können Sie sich die Datei ansehen.

5. Empfänger für Aktivitätsübergänge registrieren/deregistrieren

Bevor wir den Code für die Aktivitätserkennung einrichten, müssen wir dafür sorgen, dass unsere Aktivität Übergangsaktionen verarbeiten kann, die vom System ausgelöst werden.

BroadcastReceiver für den Übergang erstellen

Suchen Sie im Modul base in MainActivity.java nach TODO: Create a BroadcastReceiver to listen for activity transitions. Fügen Sie das unten stehende Snippet ein.

// TODO: Create a BroadcastReceiver to listen for activity transitions.
// The receiver listens for the PendingIntent above that is triggered by the system when an
// activity transition occurs.
mTransitionsReceiver = new TransitionsReceiver();

BroadcastReceiver für den Übergang registrieren

Suchen Sie im Modul base in MainActivity.java nach TODO: Register a BroadcastReceiver to listen for activity transitions. Es befindet sich in onStart(). Fügen Sie das Snippet unten ein.

// TODO: Register a BroadcastReceiver to listen for activity transitions.
registerReceiver(mTransitionsReceiver, new IntentFilter(TRANSITIONS_RECEIVER_ACTION));

Jetzt haben wir eine Möglichkeit, Updates zu erhalten, wenn die Aktivitätsübergänge über den PendingIntent ausgelöst werden.

BroadcastReceiver abmelden

Suchen Sie im Modul base in MainActivity.java nach Unregister activity transition receiver when user leaves the app (Empfänger für Aktivitätsübergang abmelden, wenn Nutzer die App verlässt). (Es befindet sich in onStop().) Fügen Sie das Snippet unten ein.

// TODO: Unregister activity transition receiver when user leaves the app.
unregisterReceiver(mTransitionsReceiver);

Es empfiehlt sich, einen Empfänger zu deregistrieren, wenn Activity heruntergefahren wird.

6. Aktivitätsübergänge einrichten und Updates anfordern

Damit Sie Updates zu Aktivitätsübergängen erhalten, müssen Sie Folgendes implementieren:

Liste der zu verfolgenden ActivityTransitions erstellen

Um das ActivityTransitionRequest-Objekt zu erstellen, müssen Sie eine Liste von ActivityTransition-Objekten erstellen, die den Übergang darstellen, den Sie erfassen möchten. Ein ActivityTransition-Objekt enthält die folgenden Daten:

  1. Ein Aktivitätstyp, der durch die Klasse DetectedActivity dargestellt wird. Die Transition API unterstützt die folgenden Aktivitäten:
  1. Ein Übergangstyp, der durch die Klasse ActivityTransition dargestellt wird. Folgende Übergangstypen sind verfügbar:

Suchen Sie im Modul base in MainActivity.java nach TODO: Add activity transitions to track. Fügen Sie den folgenden Code nach dem Kommentar ein.

// TODO: Add activity transitions to track.
activityTransitionList.add(new ActivityTransition.Builder()
        .setActivityType(DetectedActivity.WALKING)
        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
        .build());
activityTransitionList.add(new ActivityTransition.Builder()
        .setActivityType(DetectedActivity.WALKING)
        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
        .build());
activityTransitionList.add(new ActivityTransition.Builder()
        .setActivityType(DetectedActivity.STILL)
        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
        .build());
activityTransitionList.add(new ActivityTransition.Builder()
        .setActivityType(DetectedActivity.STILL)
        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
        .build());

Mit diesem Code werden die Übergänge, die wir erfassen möchten, einer zuvor leeren Liste hinzugefügt.

PendingIntent erstellen

Wie bereits erwähnt, benötigen wir ein PendingIntent, wenn wir über Änderungen in unserem ActivityTransitionRequest benachrichtigt werden möchten. Bevor wir also unser ActivityTransitionRequest einrichten, müssen wir ein PendingIntent erstellen.

Suchen Sie im Modul base in MainActivity.java nach TODO: Initialize PendingIntent that will be triggered when a activity transition occurs. Fügen Sie den folgenden Code nach dem Kommentar ein.

// TODO: Initialize PendingIntent that will be triggered when a activity transition occurs.
Intent intent = new Intent(TRANSITIONS_RECEIVER_ACTION);
mActivityTransitionsPendingIntent =
        PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);

Jetzt haben wir ein PendingIntent, das wir auslösen können, wenn eine der ActivityTransition auftritt.

ActivityTransitionRequest erstellen und Updates anfordern

Sie können ein ActivityTransitionRequest-Objekt erstellen, indem Sie die Liste der ActivityTransitions an die ActivityTransitionRequest-Klasse übergeben.

Suchen Sie im Modul base in MainActivity.java nach Create request and listen for activity changes (Anfrage erstellen und auf Änderungen bei Aktivitäten reagieren). Fügen Sie den folgenden Code nach dem Kommentar ein.

// TODO: Create request and listen for activity changes.
ActivityTransitionRequest request = new ActivityTransitionRequest(activityTransitionList);

// Register for Transitions Updates.
Task<Void> task =
        ActivityRecognition.getClient(this)
                .requestActivityTransitionUpdates(request, mActivityTransitionsPendingIntent);


task.addOnSuccessListener(
        new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void result) {
                activityTrackingEnabled = true;
                printToScreen("Transitions Api was successfully registered.");

            }
        });
task.addOnFailureListener(
        new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                printToScreen("Transitions Api could NOT be registered: " + e);
                Log.e(TAG, "Transitions Api could NOT be registered: " + e);

            }
        });

Sehen wir uns den Code an. Zuerst erstellen wir einen ActivityTransitionRequest aus unserer Liste der Aktivitätsübergänge.

ActivityTransitionRequest request = new ActivityTransitionRequest(activityTransitionList);

Als Nächstes registrieren wir uns für Updates zu Aktivitätsübergängen, indem wir unsere Instanz von ActivityTransitionRequest und das im letzten Schritt erstellte PendingIntent-Objekt an die Methode requestActivityTransitionUpdates() übergeben. Die Methode „requestActivityTransitionUpdates()“ gibt ein Task-Objekt zurück, das Sie auf Erfolg oder Fehler prüfen können, wie im nächsten Codeblock gezeigt:

// Register for Transitions Updates.
Task<Void> task =
        ActivityRecognition.getClient(this)
                .requestActivityTransitionUpdates(request, mActivityTransitionsPendingIntent);


task.addOnSuccessListener(
        new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void result) {
                activityTrackingEnabled = true;
                printToScreen("Transitions Api was successfully registered.");

            }
        });
task.addOnFailureListener(
        new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                printToScreen("Transitions Api could NOT be registered: " + e);
                Log.e(TAG, "Transitions Api could NOT be registered: " + e);

            }
        });

Nachdem Sie sich erfolgreich für Updates zum Aktivitätsübergang registriert haben, erhält Ihre App Benachrichtigungen im registrierten PendingIntent. Außerdem legen wir eine Variable fest, die angibt, ob die Aktivitätsaufzeichnung aktiviert ist. So können wir feststellen, ob sie deaktiviert oder aktiviert werden soll, wenn der Nutzer noch einmal auf die Schaltfläche klickt.

Updates entfernen, wenn die App geschlossen wird

Es ist wichtig, dass wir Übergangsaktualisierungen entfernen, wenn die App geschlossen wird.

Suchen Sie im Modul base in MainActivity.java nach Aufhören, auf Aktivitätsänderungen zu warten. Fügen Sie den folgenden Code nach dem Kommentar ein.

// TODO: Stop listening for activity changes.
ActivityRecognition.getClient(this).removeActivityTransitionUpdates(mActivityTransitionsPendingIntent)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                activityTrackingEnabled = false;
                printToScreen("Transitions successfully unregistered.");
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                printToScreen("Transitions could not be unregistered: " + e);
                Log.e(TAG,"Transitions could not be unregistered: " + e);
            }
        });

Jetzt müssen wir die Methode mit dem oben genannten Code aufrufen, wenn die App geschlossen wird.

Suchen Sie im Modul base in MainActivity.java in onPause() nach TODO: Disable activity transitions when user leaves the app. Fügen Sie den folgenden Code nach dem Kommentar ein.

// TODO: Disable activity transitions when user leaves the app.
if (activityTrackingEnabled) {
    disableActivityTransitions();
}

Das war es schon zum Tracking der Änderungen an Aktivitätsübergängen. Jetzt müssen wir nur noch die Updates verarbeiten.

7. Ereignisse verarbeiten

Wenn der angeforderte Aktivitätsübergang erfolgt, erhält Ihre App einen Intent-Callback. Ein ActivityTransitionResult-Objekt kann aus dem Intent extrahiert werden. Es enthält eine Liste von ActivityTransitionEvent-Objekten. Die Ereignisse sind chronologisch geordnet. Wenn eine App beispielsweise den Aktivitätstyp IN_VEHICLE für die Übergänge ACTIVITY_TRANSITION_ENTER und ACTIVITY_TRANSITION_EXIT anfordert, erhält sie ein ActivityTransitionEvent-Objekt, wenn der Nutzer mit dem Autofahren beginnt, und ein weiteres, wenn der Nutzer zu einer anderen Aktivität wechselt.

Fügen wir den Code für die Verarbeitung dieser Ereignisse hinzu.

Suchen Sie im Modul base in MainActivity.java in onReceive()des zuvor erstellten BroadcastReceiver nach TODO: Extract activity transition information from listener. Fügen Sie den folgenden Code nach dem Kommentar ein.

// TODO: Extract activity transition information from listener.
if (ActivityTransitionResult.hasResult(intent)) {

    ActivityTransitionResult result = ActivityTransitionResult.extractResult(intent);

    for (ActivityTransitionEvent event : result.getTransitionEvents()) {

        String info = "Transition: " + toActivityString(event.getActivityType()) +
                " (" + toTransitionType(event.getTransitionType()) + ")" + "   " +
                new SimpleDateFormat("HH:mm:ss", Locale.US).format(new Date());

        printToScreen(info);
    }
}

Dadurch werden die Informationen in eine String umgewandelt und auf dem Bildschirm ausgegeben.

Das war alles. Versuchen Sie, die App auszuführen.

WICHTIGER HINWEIS: Es ist schwierig, Aktivitätsänderungen im Emulator zu reproduzieren. Wir empfehlen daher, ein physisches Gerät zu verwenden.

Sie sollten Änderungen an Aktivitäten nachvollziehen können.

Die besten Ergebnisse erzielen Sie, wenn Sie die App auf einem physischen Gerät installieren und sich bewegen. :)

8. Code prüfen

Sie haben eine einfache App entwickelt, die Aktivitätsübergänge erfasst und auf dem Bildschirm auflistet.

Sie können sich den gesamten Code ansehen, um zu sehen, was Sie getan haben, und ein besseres Verständnis dafür zu bekommen, wie alles zusammenhängt.