Codelab interfejsu Activity Recognition Transition API

1. Wprowadzenie

Telefony nosimy ze sobą wszędzie, ale do tej pory aplikacje miały trudności z dopasowywaniem się do ciągle zmieniającego się otoczenia i działalności użytkownika.

W przeszłości deweloperzy poświęcali cenny czas na to, aby łączyć różne sygnały (lokalizacja, czujnik itp.), aby określić, kiedy rozpoczęła się lub zakończyła dana aktywność, np. chodzenie czy jazda samochodem. Co gorsza, gdy aplikacje niezależnie i ciągle sprawdzają zmiany w aktywności użytkownika, pogarsza się czas pracy na baterii.

Interfejs Activity Recognition Transition API rozwiązuje te problemy, udostępniając prosty interfejs API, który przetwarza wszystkie dane za Ciebie i informuje Cię tylko o tym, co jest dla Ciebie ważne, czyli o tym, kiedy aktywność użytkownika się zmieniła. Aplikacja po prostu subskrybuje przejście w aktywności, które Cię interesują, a interfejs API powiadomi Cię o zmianach.

Na przykład aplikacja do obsługi wiadomości może poprosić o to, aby poinformować, gdy użytkownik wsiądzie lub wysiądzie z pojazdu, aby ustawić jego stan na „Zajęty”. Podobnie aplikacja do wykrywania parkowania może poprosić o powiadomienie, gdy użytkownik wyjdzie z pojazdu i zacznie chodzić, aby zapisać miejsce parkowania.

Z tego Codelab dowiesz się, jak używać interfejsu Activity Recognition Transition API do określania, kiedy użytkownik rozpoczyna lub kończy aktywność, np. chodzenie lub bieganie.

Wymagania wstępne

znajomość programowania na Androida i przydatna znajomość wywołań zwrotnych;

Czego się nauczysz

  • Rejestrowanie się na przechodzenie między aktywnościami
  • Przetwarzanie tych zdarzeń
  • Rejestrowanie się w celu przenoszenia aktywności, gdy nie są już potrzebne

Co będzie Ci potrzebne

  • Android Studio Bumblebee
  • urządzenie z Androidem lub emulator,

2. Pierwsze kroki

Sklonuj repozytorium projektu startowego

Aby jak najszybciej rozpocząć pracę, przygotowaliśmy projekt startowy, na którym możesz budować. Jeśli masz zainstalowany git, możesz po prostu uruchomić podane niżej polecenie. (możesz to sprawdzić, wpisując git --version w terminalu lub wierszu poleceń i sprawdzając, czy polecenie zostało wykonane prawidłowo).

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

Jeśli nie masz git, możesz pobrać projekt jako plik zip:

Importowanie projektu

Uruchom Android Studio i na ekranie powitalnym wybierz „Otwórz istniejący projekt Android Studio”. Następnie otwórz katalog projektu.

Po załadowaniu projektu możesz też zobaczyć alert, że Git nie śledzi wszystkich zmian lokalnych. W prawym górnym rogu możesz kliknąć „Ignoruj” lub „X”. (nie będziesz przesyłać żadnych zmian do repozytorium Git).

Jeśli w oknie projektu masz widok Android, w lewym górnym rogu powinien pojawić się widok podobny do tego na ilustracji poniżej. (jeśli korzystasz z widoku Projekt, musisz rozwinąć projekt, aby zobaczyć te same informacje).

d2363db913d8e5ad.png

Istnieją 2 ikony folderów (basecomplete). Każda z nich jest nazywana „modułem”.

Pamiętaj, że kompilacja projektu w tle może zająć Android Studio kilka sekund. W tym czasie na pasku stanu u dołu Android Studio będzie widoczny wskaźnik:

c9f23d5336be3cfe.png

Zalecamy, aby przed wprowadzeniem zmian w kodzie poczekać, aż ten proces się zakończy. Dzięki temu Android Studio będzie mogło pobrać wszystkie niezbędne komponenty.

Jeśli pojawi się komunikat „Czy chcesz odświeżyć stronę, aby zmiany języka zaczęły obowiązywać?” lub podobny, kliknij „Tak”.

Informacje o projekcie startowym

Wszystko gotowe. Możesz teraz dodać rozpoznawanie aktywności. Użyjemy modułu base, który jest punktem wyjścia w tym laboratorium programistycznym. Innymi słowy, do pliku base dodasz kod z każdego kroku.

Moduł complete możesz wykorzystać do sprawdzenia swojej pracy lub w razie problemów.

Omówienie najważniejszych elementów:

  • MainActivity: zawiera cały kod potrzebny do rozpoznawania aktywności.

Konfigurowanie emulatora

Jeśli potrzebujesz pomocy przy konfigurowaniu emulatora Androida, przeczytaj artykuł Uruchamianie aplikacji.

Uruchomienie projektu startowego

Uruchom aplikację.

  • Podłącz urządzenie z Androidem do komputera lub uruchom emulator.
  • Na pasku narzędzi wybierz konfigurację base z menu selektora, a potem kliknij obok niej zielony trójkąt (Uruchom):

a640a291ffaf62ad.png

  • Powinna się wyświetlić aplikacja:

f58d4bb92ee77f41.png

  • Aplikacja nie robi teraz nic oprócz drukowania wiadomości. Teraz dodamy rozpoznawanie aktywności.

Podsumowanie

Na tym etapie dowiesz się o tych kwestiach:

  • Ogólne ustawienia dotyczące Codelab.
  • Podstawy korzystania z naszej aplikacji.
  • Jak wdrożyć aplikację.

3. Sprawdzanie biblioteki i dodawanie uprawnień do pliku manifestu

Aby używać interfejsu Transition API w aplikacji, musisz zadeklarować zależność od interfejsu Google Location and Activity Recognition API i w pliku manifestu aplikacji określić uprawnienie com.google.android.gms.permission.ACTIVITY_RECOGNITION.

  1. W pliku build.gradle wyszukaj TODO: Sprawdź bibliotekę Play Services wymaganą do rozpoznawania aktywności. W tym kroku (krok 1) nie musisz nic robić. Sprawdź tylko wymaganą deklarowaną zależność. Powinien on wyglądać podobnie do tego:
    // TODO: Review play services library required for activity recognition.
    implementation 'com.google.android.gms:play-services-location:19.0.1'
  1. W module base wyszukaj TODO: Add both activity recognition permissions to the manifest (DO ZROBIĆ: dodaj do pliku manifestu oba uprawnienia do rozpoznawania aktywności) w AndroidManifest.xml i dodaj kod poniżej do elementu <manifest>.
<!-- 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" />

Twój kod powinien teraz wyglądać mniej więcej tak:

<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>

Jak widać z komentarzy, musisz dodać drugie uprawnienie dla Androida 10. Jest to wymagane w przypadku uprawnienia w czasie wykonywania, które zostało dodane w wersji interfejsu API 29.

Znakomicie. Twoja aplikacja może teraz obsługiwać rozpoznawanie aktywności. Musimy tylko dodać kod.

Uruchomienie aplikacji

Uruchom aplikację w Android Studio. Powinien wyglądać dokładnie tak samo. Nie dodaliśmy jeszcze kodu do śledzenia przejść, ale zrobimy to w następnej sekcji.

4. Sprawdzanie/wysyłanie żądań uprawnień czasu działania na Androidzie

W przypadku interfejsu API w wersji 28 i starszych obsługujemy uprawnienia, ale musimy obsługiwać uprawnienia w czasie wykonywania w interfejsie API w wersji 29 i późniejszych:

  • MainActivity.java sprawdzimy, czy użytkownik korzysta z Androida 10 (29) lub nowszego. Jeśli tak, sprawdzimy uprawnienia do rozpoznawania aktywności.
  • Jeśli użytkownik nie przyzna uprawnień, prześlemy go na ekran powitalny (PermissionRationalActivity.java), na którym wyjaśnimy, dlaczego aplikacja potrzebuje tych uprawnień, i zapytamy o zatwierdzenie.

Sprawdzanie kodu pod kątem wersji Androida

W module base wyszukaj MainActivity.java TODO: Sprawdź, czy na urządzeniach z Androidem 10 (29+). Powinien pojawić się ten fragment kodu.

W tej sekcji nie musisz podejmować żadnych działań.

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

Jak już wspomnieliśmy, w Androidzie 10 i nowszych wersjach musisz uzyskać zgodę na uprawnienie android.permission.ACTIVITY_RECOGNITION w czasie działania aplikacji. Za pomocą tego prostego sprawdzenia decydujemy, czy musimy sprawdzić uprawnienia w czasie działania.

Sprawdź, czy w ramach rozpoznawania aktywności jest sprawdzane uprawnienie na czas działania

W module base wyszukaj TODO: Sprawdź uprawnienia w wersji 29+MainActivity.java. Powinien pojawić się ten fragment kodu.

W tej sekcji nie musisz podejmować żadnych działań.

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

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

Używamy zmiennej utworzonej w poprzednim kroku, aby sprawdzić, czy musimy sprawdzić uprawnienia w czasie działania.

W przypadku wersji Q i wyższych sprawdzamy i zwracamy wynik dotyczący uprawnień w czasie działania. Jest to część większej metody o nazwie activityRecognitionPermissionApproved(), która w jednym prostym wywołaniu informuje dewelopera, czy potrzebujemy uprawnienia.

Prośba o uprawnienia czasu działania i włączanie/wyłączanie przejść rozpoznawania aktywności

W module base wyszukaj MainActivity.java TODO: Enable/Disable activity tracking and ask for permissions if needed. Dodaj kod pod komentarzem.

// 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);

}

Tutaj pytamy, czy rozpoznawanie aktywności jest zatwierdzone. Jeśli tak jest i rozpoznawanie aktywności jest już włączone, wyłączamy je. W przeciwnym razie go włączymy.

Jeśli użytkownik nie zatwierdzi uprawnienia, przekierowujemy go do ekranu wczytywania, na którym wyjaśnimy, dlaczego potrzebujemy tego uprawnienia, i zapytamy, czy chce je przyznać.

Sprawdzanie kodu prośby o przyznanie uprawnień

W module base wyszukaj PermissionRationalActivity.java TODO: Sprawdź prośbę o uprawnienia do rozpoznawania aktywności. Powinien pojawić się ten fragment kodu.

W tej sekcji nie musisz podejmować żadnych działań.

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

Jest to najważniejsza część aktywności i część do sprawdzenia. Gdy użytkownik poprosi o przyznanie uprawnień, kod spowoduje wysłanie prośby o te uprawnienia.

Poza tym klasa PermissionRationalActivity.java wyświetla uzasadnienie, dlaczego użytkownik powinien zatwierdzić uprawnienie do rozpoznawania aktywności (sprawdzona metoda). Użytkownik może kliknąć przycisk Nie, dziękuję lub przycisk Dalej (który uruchamia kod podany powyżej).

Jeśli chcesz dowiedzieć się więcej, zapoznaj się z tym plikiem.

5. Rejestrowanie i rejestrowanie anulowania odbiornika w przypadku przejść aktywności

Zanim skonfigurujemy kod rozpoznawania aktywności, chcemy się upewnić, że nasza Aktywność może obsługiwać działania przejścia wywołane przez system.

Tworzenie odbiornika transmisji dla przejścia na nową wersję

W module base w pliku MainActivity.java wyszukaj TODO: Create a BroadcastReceiver to listen for activity transitions. Wklej podany niżej fragment kodu.

// 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();

Rejestrowanie odbiornika BroadcastReceiver na potrzeby przejścia na nową wersję

W module base wyszukaj w MainActivity.java TODO: Register a BroadcastReceiver to listen for activity transitions. (znajdziesz go w sekcji onStart()). Wklej fragment kodu poniżej.

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

Teraz mamy sposób na otrzymywanie aktualizacji, gdy przejścia między aktywnościami są wywoływane za pomocą PendingIntent.

Wyrejestruj BroadcastReceiver

W module baseMainActivity.java wyszukaj Unregister activity transition receiver when user leaves the app (Wyrejestruj odbiornik przejścia do innej aktywności po opuszczeniu aplikacji przez użytkownika). (znajdziesz go w sekcji onStop()).Wklej fragment kodu poniżej.

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

Zalecamy odrejestrowanie odbiornika, gdy Activity jest wyłączany.

6. Konfigurowanie przejść między aktywnościami i żądanie aktualizacji

Aby zacząć otrzymywać powiadomienia o przechodzeniu do innej aktywności, musisz wdrożyć:

Utwórz listę przejść między aktywnościami, które mają być wykonywane

Aby utworzyć obiekt ActivityTransitionRequest, musisz utworzyć listę obiektów ActivityTransition, które reprezentują przejście, które chcesz śledzić. Obiekt ActivityTransition zawiera te dane:

  1. Typ aktywności reprezentowany przez klasę DetectedActivity. Interfejs Transition API obsługuje te czynności:
  1. Typ przejścia reprezentowany przez klasę ActivityTransition. Typy przejść:

W module base wyszukaj MainActivity.java TODO: Add activity transitions to track (TODO: dodaj przejścia aktywności do śledzenia). Dodaj kod pod komentarzem.

// 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());

Ten kod dodaje przejścia, które chcemy śledzić, do wcześniej pustej listy.

Tworzenie intencji oczekującej

Jak już wspomnieliśmy, potrzebujemy obiektu PendingIntent, jeśli chcemy otrzymywać alerty o wszelkich zmianach w ActivityTransitionRequest. Dlatego przed skonfigurowaniem ActivityTransitionRequest musimy utworzyć PendingIntent.

W module base wyszukaj w MainActivity.java TODO: Initialize PendingIntent that will be triggered when a activity transition occurs. Dodaj kod pod komentarzem.

// 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);

Teraz mamy PendingIntent, który możemy wywołać, gdy wystąpi jedno z ActivityTransition.

Tworzenie obiektu ActivityTransitionRequest i żądanie aktualizacji

Obiekt ActivityTransitionRequest możesz utworzyć, przekazując do klasy ActivityTransitionRequest listę obiektów ActivityTransitions.

W module base w sekcji MainActivity.java wyszukaj Tworzenie prośby i słuchanie o zmianach aktywności. Dodaj kod pod komentarzem.

// 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);

            }
        });

Przyjrzyjmy się kodowi. Najpierw tworzymy ActivityTransitionRequest na podstawie listy przejść między aktywnościami.

ActivityTransitionRequest request = new ActivityTransitionRequest(activityTransitionList);

Następnie rejestrujemy aktualizacje dotyczące przejścia do aktywności, przekazując instancję ActivityTransitionRequest i nasz obiekt PendingIntent utworzony w ostatnim kroku do metody requestActivityTransitionUpdates(). Metoda requestActivityTransitionUpdates() zwraca obiekt Task, którego powodzenie lub niepowodzenie możesz sprawdzić, jak pokazano w następnym bloku kodu:

// 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);

            }
        });

Po zarejestrowaniu się w celu otrzymywania powiadomień o przechodzeniu do innej aktywności aplikacja otrzymuje powiadomienia w ramach zarejestrowanego PendingIntent. Ustawiamy też zmienną, która informuje, czy śledzenie aktywności jest włączone, aby wiedzieć, czy wyłączyć czy włączyć śledzenie, gdy użytkownik ponownie kliknie przycisk.

Usuwanie aktualizacji podczas zamykania aplikacji

Podczas zamykania aplikacji usuwamy aktualizacje przejścia.

W module base wyszukaj MainActivity.java, aby znaleźć opcję Zatrzymaj słuchanie zmian aktywności. Dodaj kod pod komentarzem.

// 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);
            }
        });

Teraz musimy wywołać metodę zawierającą powyższy kod, gdy aplikacja się zamyka.

W module baseonPause()MainActivity.java wyszukaj TODO: Disable activity transitions when user leaves the app (DO: wyłącz przejścia aktywności po opuszczeniu aplikacji przez użytkownika). Dodaj kod pod komentarzem.

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

To wszystko, co musisz wiedzieć o śledzeniu zmian w przechodzeniu między aktywnościami. Teraz musimy tylko przetworzyć zmiany.

7. Przetwarzanie zdarzeń

Gdy nastąpi przejście do żądanej aktywności, aplikacja otrzyma wywołanie zwrotne Intent. Z intencji można wyodrębnić obiekt ActivityTransitionResult, który zawiera listę obiektów ActivityTransitionEvent. Zdarzenia są uporządkowane chronologicznie. Jeśli na przykład aplikacja prosi o typ działania IN_VEHICLE w przypadku przejść ACTIVITY_TRANSITION_ENTERACTIVITY_TRANSITION_EXIT, to po rozpoczęciu jazdy przez użytkownika otrzymuje obiekt ActivityTransitionEvent, a po przejściu do innego działania – kolejny.

Dodajmy kod do obsługi tych zdarzeń.

W module base wyszukaj TODO: Extract activity transition information from listenerMainActivity.javaonReceive() w utworzonym wcześniej komponencie BroadcastReceiver. Dodaj kod pod komentarzem.

// 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);
    }
}

Spowoduje to przekształcenie informacji w String i wyświetlenie ich na ekranie.

To wszystko. Spróbuj uruchomić aplikację.

WAŻNA UWAGA: zmiany aktywności trudno odtworzyć na emulatorze, dlatego zalecamy używanie urządzenia fizycznego.

Powinieneś mieć możliwość śledzenia zmian w aktywności.

Aby uzyskać najlepsze wyniki, zainstaluj aplikację na urządzeniu fizycznym i chodź po pokoju. :)

8. Sprawdzanie kodu

Utworzyłeś/-aś prostą aplikację, która śledzi przejścia między aktywnościami i wyświetla je na ekranie.

Możesz przeczytać cały kod, aby sprawdzić, co udało Ci się zrobić, i lepiej zrozumieć, jak to działa.