Codelab sull'API Activity Recognition Transition

1. Introduzione

Portiamo con noi gli smartphone ovunque, ma finora è stato difficile per le app adattare la loro esperienza all'ambiente e alle attività in continua evoluzione di un utente.

In passato, per farlo,gli sviluppatori impiegavano tempo prezioso per combinare vari indicatori (posizione, sensore e così via) per determinare quando un'attività come camminare o guidare era iniziata o terminata. Peggio ancora, quando le app controllano in modo indipendente e continuo la presenza di modifiche nell'attività utente, la durata della batteria ne risente.

L'API Activity Recognition Transition risolve questi problemi fornendo un'API semplice che esegue tutta l'elaborazione per te e ti dice solo ciò che ti interessa: quando l'attività di un utente è cambiata. La tua app si iscrive semplicemente a una transizione nelle attività che ti interessano e l'API ti invia una notifica delle modifiche.

Ad esempio, un'app di messaggistica può chiedere "Fammi sapere quando l'utente è entrato o uscito da un veicolo" per impostare lo stato dell'utente su occupato. Analogamente, un'app di rilevamento dei parcheggi può chiedere "Fammi sapere quando l'utente è sceso da un veicolo e ha iniziato a camminare" per salvare la posizione del parcheggio dell'utente.

In questo codelab imparerai a utilizzare l'API Activity Recognition Transition per determinare quando un utente avvia/ferma un'attività come camminare o correre.

Prerequisiti

Familiarità con lo sviluppo Android e una certa familiarità con i callback.

Cosa imparerai

  • Registrazione per le transizioni di attività
  • Elaborazione di questi eventi
  • La disattivazione delle transizioni di attività quando non sono più necessarie

Occorrente

  • Android Studio Bumblebee
  • Un dispositivo o un emulatore Android

2. Per iniziare

Clona il repository del progetto iniziale

Per consentirti di iniziare il prima possibile, abbiamo preparato un progetto iniziale su cui puoi lavorare. Se hai installato git, puoi semplicemente eseguire il comando seguente. Puoi controllare digitando git --version nel terminale / nella riga di comando e verificare che venga eseguito correttamente.

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

Se non hai git, puoi scaricare il progetto come file ZIP:

Importa il progetto

Avvia Android Studio, seleziona "Apri un progetto Android Studio esistente" dalla schermata di benvenuto e apri la directory del progetto.

Dopo aver caricato il progetto, potresti anche visualizzare un avviso che indica che Git non monitora tutte le modifiche locali. Puoi fare clic su "Ignora" o "X" in alto a destra. Non eseguirai il push di alcuna modifica nel repository Git.

Se sei nella visualizzazione Android, nell'angolo in alto a sinistra della finestra del progetto dovresti vedere qualcosa di simile all'immagine seguente. Se sei nella visualizzazione Progetto, devi espandere il progetto per vedere la stessa cosa.

d2363db913d8e5ad.png

Esistono due icone di cartella (base e complete). Ognuna è nota come "modulo".

Tieni presente che Android Studio potrebbe impiegare diversi secondi per compilare il progetto in background per la prima volta. Durante questo periodo, nella barra di stato in fondo ad Android Studio viene visualizzato un indicatore di attesa:

c9f23d5336be3cfe.png

Ti consigliamo di attendere il completamento dell'operazione prima di apportare modifiche al codice. In questo modo, Android Studio potrà importare tutti i componenti necessari.

Inoltre, se viene visualizzato il messaggio "Vuoi ricaricare per applicare le modifiche alla lingua?" o un messaggio simile, seleziona "Sì".

Informazioni sul progetto iniziale

Ottimo, è tutto pronto per aggiungere il riconoscimento attività. Utilizzeremo il modulo base, che è il punto di partenza di questo codelab. In altre parole, aggiungerai il codice di ogni passaggio a base.

Il modulo complete può essere utilizzato per controllare il tuo lavoro o come riferimento in caso di problemi.

Panoramica dei componenti chiave:

  • MainActivity: contiene tutto il codice necessario per il riconoscimento delle attività.

Configurazione dell'emulatore

Se hai bisogno di aiuto per configurare un emulatore Android, consulta l'articolo Eseguire l'app.

Esegui il progetto iniziale

Eseguiamo l'app.

  • Collega il dispositivo Android al computer o avvia un emulatore.
  • Nella barra degli strumenti, seleziona la configurazione base dal selettore a discesa e fai clic sul triangolo verde (Esegui) accanto:

a640a291ffaf62ad.png

  • Dovresti vedere l'applicazione di seguito:

f58d4bb92ee77f41.png

  • L'app ora non fa altro che stampare un messaggio. Ora aggiungeremo il riconoscimento attività.

Riepilogo

In questo passaggio hai appreso:

  • Configurazione generale del codelab.
  • Nozioni di base della nostra app.
  • Come eseguire il deployment dell'app.

3. Esamina la libreria e aggiungi l'autorizzazione al manifest

Per utilizzare l'API Transition nella tua app, devi dichiarare una dipendenza dall'API Riconoscimento attività e posizione di Google e specificare l'autorizzazione com.google.android.gms.permission.ACTIVITY_RECOGNITION nel file manifest dell'app.

  1. Cerca DA FARE: esamina la libreria Play Services richiesta per il riconoscimento delle attività nel file build.gradle. Non è richiesta alcuna azione per questo passaggio (passaggio 1), ma devi solo esaminare la dipendenza dichiarata che richiediamo. Dovrebbe avere il seguente aspetto:
    // TODO: Review play services library required for activity recognition.
    implementation 'com.google.android.gms:play-services-location:19.0.1'
  1. Nel modulo base, cerca DA FARE: aggiungi entrambe le autorizzazioni di riconoscimento attività al manifest in AndroidManifest.xml e aggiungi il codice riportato di seguito all'elemento <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" />

Il codice dovrebbe avere il seguente aspetto:

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

Come puoi vedere dai commenti, devi aggiungere una seconda autorizzazione per Android 10. Questo è necessario per l'autorizzazione di runtime aggiunta nella versione 29 dell'API.

È tutto. Ora la tua app può supportare il riconoscimento delle attività, devi solo aggiungere il codice per ottenerlo.

Esegui app

Esegui l'app da Android Studio. Dovrebbe avere esattamente lo stesso aspetto. Non abbiamo ancora aggiunto alcun codice per monitorare le transizioni, ma lo faremo nella sezione successiva.

4. Controllare/richiedere le autorizzazioni di runtime in Android

Sebbene le autorizzazioni siano coperte nella versione 28 e precedenti dell'API, dobbiamo supportare le autorizzazioni di runtime nella versione 29 e successive dell'API:

  • In MainActivity.java, verificheremo se l'utente utilizza Android 10 (29) o versioni successive e, in questo caso, verificheremo le autorizzazioni di riconoscimento delle attività.
  • Se le autorizzazioni non vengono concesse, l'utente verrà indirizzato a una schermata iniziale (PermissionRationalActivity.java) che spiega perché l'app ha bisogno dell'autorizzazione e gli consente di approvarla.

Esaminare il codice che controlla la versione di Android

Nel modulo base, cerca DA FARE: controlla la presenza di dispositivi con Android 10 (29 e versioni successive) in MainActivity.java. Dovresti visualizzare questo snippet di codice.

Tieni presente che non è richiesta alcuna azione per questa sezione.

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

Come affermato in precedenza, devi ottenere l'approvazione per l'autorizzazione di runtime android.permission.ACTIVITY_RECOGNITION in Android 10 e versioni successive. Utilizziamo questo semplice controllo per decidere se dobbiamo o meno controllare le autorizzazioni di runtime.

Se necessario, controlla il controllo delle autorizzazioni di runtime per il riconoscimento delle attività

Nel modulo base, cerca DA FARE: controlla l'autorizzazione per più di 29 anni in MainActivity.java. Dovresti visualizzare questo snippet di codice.

Tieni presente che non è richiesta alcuna azione per questa sezione.

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

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

Utilizziamo la variabile creata nel passaggio precedente per verificare se è necessario controllare le autorizzazioni di runtime.

Per Q e versioni successive, controlliamo e restituiamo il risultato per l'autorizzazione di runtime. Questo fa parte di un metodo più grande chiamato activityRecognitionPermissionApproved() che consente allo sviluppatore di sapere con una semplice chiamata se è necessario richiedere o meno un'autorizzazione.

Richiedere le autorizzazioni di runtime e attivare/disattivare le transizioni di riconoscimento delle attività

Nel modulo base, cerca DA FARE: attiva/disattiva il monitoraggio delle attività e, se necessario, chiedi le autorizzazioni in MainActivity.java. Aggiungi il codice seguente dopo il commento.

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

}

Qui chiediamo se il riconoscimento attività è approvato. Se è così e il riconoscimento attività è già attivo, lo disattiviamo. In caso contrario, lo attiviamo.

Se l'autorizzazione non viene approvata, indirizziamo l'utente all'attività della schermata iniziale che spiega perché abbiamo bisogno dell'autorizzazione e gli consentiamo di attivarla.

Esamina il codice della richiesta di autorizzazione

Nel modulo base, cerca DA FARE: esamina la richiesta di autorizzazione per il riconoscimento attività in PermissionRationalActivity.java. Dovresti visualizzare questo snippet di codice.

Tieni presente che non è richiesta alcuna azione per questa sezione.

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

Questa è la parte più importante dell'attività e quella da esaminare. Il codice attiva la richiesta di autorizzazione quando l'utente la richiede.

Oltre a questo, la classe PermissionRationalActivity.java mostra una motivazione per cui l'utente dovrebbe approvare l'autorizzazione di riconoscimento delle attività (best practice). L'utente può fare clic sul pulsante No grazie o sul pulsante Continua (che attiva il codice riportato sopra).

Non esitare a esaminare il file se vuoi saperne di più.

5. Registra/annulla la registrazione del receiver per le transizioni di attività

Prima di configurare il codice di riconoscimento delle attività, vogliamo assicurarci che la nostra attività possa gestire le azioni di transizione sollevate dal sistema.

Crea un BroadcastReceiver per la transizione

Nel modulo base, cerca DA FARE: crea un BroadcastReceiver per ascoltare le transizioni di attività in MainActivity.java. Incolla lo snippet di seguito.

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

Registra un BroadcastReceiver per la transizione

Nel modulo base, cerca DA FARE: registra un BroadcastReceiver per ascoltare le transizioni di attività in MainActivity.java. (si trova in onStart()). Incolla lo snippet di seguito.

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

Ora abbiamo un modo per ricevere aggiornamenti quando le transizioni di attività vengono attivate tramite PendingIntent.

Annullare la registrazione di BroadcastReceiver

Nel modulo base, cerca Unregister activity transition receiver when user leaves the app in MainActivity.java. (si trova in onStop()).Incolla lo snippet di seguito.

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

È buona prassi annullare la registrazione di un ricevitore quando Activity si arresta.

6. Configura le transizioni delle attività e richiedi aggiornamenti

Per iniziare a ricevere aggiornamenti sulle transizioni delle attività, devi implementare:

Creare un elenco di transizioni di attività da seguire

Per creare l'oggetto ActivityTransitionRequest, devi creare un elenco di oggetti ActivityTransition che rappresentano la transizione che vuoi monitorare. Un oggetto ActivityTransition include i seguenti dati:

  1. Un tipo di attività, rappresentato dalla classe DetectedActivity. L'API Transition supporta le seguenti attività:
  1. Un tipo di transizione, rappresentato dalla classe ActivityTransition. I tipi di transizione sono:

Nel modulo base, cerca DA FARE: aggiungi le transizioni di attività da monitorare in MainActivity.java. Aggiungi il codice seguente dopo il commento.

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

Questo codice aggiunge le transizioni che vogliamo monitorare a un elenco precedentemente vuoto.

Creare un PendingIntent

Come indicato in precedenza, abbiamo bisogno di un PendingIntent se vogliamo ricevere avvisi per eventuali modifiche al nostro ActivityTransitionRequest, quindi prima di configurare ActivityTransitionRequest, dobbiamo creare un PendingIntent.

Nel modulo base, cerca DA FARE: inizializza PendingIntent che verrà attivato quando si verifica una transizione di attività in MainActivity.java. Aggiungi il codice seguente dopo il commento.

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

Ora abbiamo un PendingIntent che possiamo attivare quando si verifica una delle transizioni di attività.

Creare un'attività TransitionRequest e richiedere aggiornamenti

Puoi creare un oggetto ActivityTransitionRequest passando l'elenco di ActivityTransitions alla classe ActivityTransitionRequest.

Nel modulo base, cerca Crea richiesta e ascolta le modifiche dell'attività in MainActivity.java. Aggiungi il codice seguente dopo il commento.

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

            }
        });

Esaminiamo il codice. Innanzitutto, creiamo un ActivityTransitionRequest dal nostro elenco di transizioni di attività.

ActivityTransitionRequest request = new ActivityTransitionRequest(activityTransitionList);

Successivamente, ci registriamo per gli aggiornamenti delle transizioni di attività passando l'istanza di ActivityTransitionRequest e l'oggetto PendingIntent che abbiamo creato nell'ultimo passaggio al metodo requestActivityTransitionUpdates(). Il metodo requestActivityTransitionUpdates() restituisce un oggetto Task che puoi controllare per verificare se l'operazione è riuscita o meno, come mostrato nel blocco di codice successivo:

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

            }
        });

Dopo aver effettuato la registrazione per gli aggiornamenti delle transizioni di attività, la tua app riceve le notifiche nell'PendingIntent registrato. Impostiamo anche una variabile che indica che il monitoraggio delle attività è attivo per consentirci di sapere se disattivare/attivare se l'utente fa di nuovo clic sul pulsante.

Rimuovere gli aggiornamenti alla chiusura dell'app

È importante rimuovere gli aggiornamenti di transizione quando l'app si chiude.

Nel modulo base, cerca Interrompi l'ascolto delle modifiche delle attività in MainActivity.java. Aggiungi il codice seguente dopo il commento.

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

Ora dobbiamo chiamare il metodo contenente il codice riportato sopra quando l'app si arresta

Nel modulo base, cerca DA FARE: disattiva le transizioni di attività quando l'utente esce dall'app in MainActivity.java in onPause(). Aggiungi il codice seguente dopo il commento.

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

È tutto per il monitoraggio delle modifiche alle transizioni di attività. Ora dobbiamo solo elaborare gli aggiornamenti.

7. Eventi di elaborazione

Quando si verifica la transizione dell'attività richiesta, la tua app riceve un callback Intent. Dall'intent è possibile estrarre un oggetto ActivityTransitionResult, che include un elenco di oggetti ActivityTransitionEvent. Gli eventi sono ordinati in ordine cronologico. Ad esempio, se un'app richiede il tipo di attività IN_VEHICLE nelle transizioni ACTIVITY_TRANSITION_ENTER e ACTIVITY_TRANSITION_EXIT, riceve un oggetto ActivityTransitionEvent quando l'utente inizia a guidare e un altro quando passa a qualsiasi altra attività.

Aggiungiamo il codice per gestire questi eventi.

Nel modulo base, cerca DA FARE: estrai le informazioni sulle transizioni delle attività dall'ascoltatore in MainActivity.java in onReceive()del BroadcastReceiver che abbiamo creato in precedenza. Aggiungi il codice seguente dopo il commento.

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

Le informazioni verranno convertite in un String e stampate sullo schermo.

È tutto. Prova a eseguire l'app.

NOTA IMPORTANTE: è difficile riprodurre le modifiche delle attività sull'emulatore, quindi consigliamo di utilizzare un dispositivo fisico.

Dovresti essere in grado di monitorare le modifiche delle attività.

Per risultati ottimali, installa l'app su un dispositivo fisico e cammina. :)

8. Esamina il codice

Hai creato un'app semplice che monitora le transizioni di Attività e le elenca sullo schermo.

Non esitare a leggere il codice nella sua interezza per rivedere ciò che hai fatto e avere un'idea migliore di come funzionano insieme.