Cómo detectar cuándo un usuario inicia o finaliza una actividad

Es posible que debas diseñar tu app para identificar cuándo un usuario inicia o detiene una actividad en particular, como caminar, andar en bicicleta o conducir. Por ejemplo, una app de seguimiento de kilometraje podría comenzar a realizar el seguimiento cuando un usuario comienza a conducir, o una app de mensajería podría silenciar todas las conversaciones hasta que el usuario deje de conducir.

Se puede utilizar la API de transición de reconocimiento de actividad para detectar cambios en la actividad del usuario. Tu app se suscribe a una transición en actividades de interés y la API le envía notificaciones solo cuando es necesario. En esta página, se muestra cómo usar la API de transición de reconocimiento de actividad, también llamada API de transición.

Cómo configurar tu proyecto

Para usar la API de transición en tu app, debes declarar una dependencia a la versión 12.0.0 o superior de la API de ubicación y reconocimiento de actividad de Google, y especificar el permiso com.google.android.gms.permission.ACTIVITY_RECOGNITION en el manifiesto de la app.

  1. Si deseas declarar una dependencia a la API, agrega una referencia al repositorio de Maven de Google y una entrada de implementación para com.google.android.gms:play-services-location:12.0.0 en la sección de dependencias del archivo build.gradle de tu app. Para obtener más información, consulta Cómo configurar los Servicios de Google Play.
  2. Si deseas especificar el permiso com.google.android.gms.permission.ACTIVITY_RECOGNITION, agrega un elemento <uses-permission> en el manifiesto de la app, como se muestra en el siguiente ejemplo:

     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
             package="com.example.myapp">
    
       <uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
       …
     </manifest>
    

Cómo registrarse para ver las actualizaciones de la transición de actividad

Para comenzar a recibir notificaciones sobre las transiciones de actividad, debes implementar lo siguiente:

Para crear el objeto ActivityTransitionRequest, debes crear una lista de objetos ActivityTransition, que representa la transición sobre la que deseas recibir notificaciones. Un objeto ActivityTransition incluye los siguientes datos:

En el siguiente código, se muestra cómo crear una lista de objetos ActivityTransition:

Kotlin

val transitions = mutableListOf<ActivityTransition>()

transitions +=
        ActivityTransition.Builder()
          .setActivityType(DetectedActivity.IN_VEHICLE)
          .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
          .build()

transitions +=
        ActivityTransition.Builder()
          .setActivityType(DetectedActivity.IN_VEHICLE)
          .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
          .build()

transitions +=
        ActivityTransition.Builder()
          .setActivityType(DetectedActivity.WALKING)
          .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
          .build()

Java

List<ActivityTransition> transitions = new ArrayList<>();

transitions.add(
        new ActivityTransition.Builder()
          .setActivityType(DetectedActivity.IN_VEHICLE)
          .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
          .build());

transitions.add(
        new ActivityTransition.Builder()
          .setActivityType(DetectedActivity.IN_VEHICLE)
          .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
          .build());

transitions.add(
        new ActivityTransition.Builder()
          .setActivityType(DetectedActivity.WALKING)
          .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
          .build());

Puedes crear un objeto ActivityTransitionRequest pasando la lista de ActivityTransitions a la clase ActivityTransitionRequest, como se muestra en el siguiente ejemplo:

Kotlin

val request = ActivityTransitionRequest(transitions)

Java

ActivityTransitionRequest request = new ActivityTransitionRequest(transitions);

Puedes registrarte para las actualizaciones de transición de actividad pasando tu instancia de ActivityTransitionRequest y tu objeto PendingIntent al método requestActivityTransitionUpdates(). El método requestActivityTransitionUpdates() muestra un objeto Task, que puedes verificar si es correcto o no, como se muestra en el siguiente ejemplo de código:

Kotlin

// myPendingIntent is the instance of PendingIntent where the app receives callbacks.
val task = ActivityRecognition.getClient(context)
        .requestActivityTransitionUpdates(request, myPendingIntent)

task.addOnSuccessListener {
    // Handle success
}

task.addOnFailureListener { e: Exception ->
    // Handle error
}

Java

// myPendingIntent is the instance of PendingIntent where the app receives callbacks.
Task<Void> task = ActivityRecognition.getClient(context)
          .requestActivityTransitionUpdates(request, myPendingIntent);

task.addOnSuccessListener(
    new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void result) {
            // Handle success
        }
    }
);

task.addOnFailureListener(
    new OnFailureListener() {
        @Override
        public void onFailure(Exception e) {
            // Handle error
        }
    }
);

Después de registrarte correctamente para las actualizaciones de transición de actividad, tu app recibirá notificaciones en el PendingIntent registrado.

Cómo procesar eventos de transición de actividad

Cuando se produce la transición de actividad solicitada, tu app recibe una devolución de llamada de Intent. Se puede extraer un objeto ActivityTransitionResult de Intent, que incluye una lista de objetos ActivityTransitionEvent. Se muestran los eventos en orden cronológico; por ejemplo, si una app solicita el tipo de actividad IN_VEHICLE en las transiciones ACTIVITY_TRANSITION_ENTER y ACTIVITY_TRANSITION_EXIT, recibirá un objeto ActivityTransitionEvent cuando el usuario comience a conducir y otro cuando el usuario realice una transición a cualquier otra actividad.

Si quieres implementar la devolución de llamada, crea una subclase de BroadcastReceiver e implementa el método onReceive() para obtener la lista de eventos de transición de actividad. Para obtener más información, consulta Transmisiones. En el siguiente ejemplo, se muestra cómo implementar el método onReceive():

Kotlin

override fun onReceive(context: Context, intent: Intent) {
    if (ActivityTransitionResult.hasResult(intent)) {
        val result = ActivityTransitionResult.extractResult(intent)!!
        for (event in result.transitionEvents) {
            // chronological sequence of events....
        }
    }
}

Java

@Override
public void onReceive(Context context, Intent intent) {
    if (ActivityTransitionResult.hasResult(intent)) {
        ActivityTransitionResult result = ActivityTransitionResult.extractResult(intent);
        for (ActivityTransitionEvent event : result.getTransitionEvents()) {
            // chronological sequence of events....
        }
    }
}

Cómo anular el registro a las actualizaciones de transición de actividad

Puedes anular el registro de las actualizaciones de transición de actividad invocando el método removeActivityTransitionUpdates() de ActivityRecognitionClient y pasando tu objeto PendingIntent como parámetro, como se muestra en el siguiente ejemplo:

Kotlin

// myPendingIntent is the instance of PendingIntent where the app receives callbacks.
val task = ActivityRecognition.getClient(context)
        .removeActivityTransitionUpdates(myPendingIntent)

task.addOnSuccessListener {
    myPendingIntent.cancel()
}

task.addOnFailureListener { e: Exception ->
    Log.e("MYCOMPONENT", e.message)
}

Java

// myPendingIntent is the instance of PendingIntent where the app receives callbacks.
Task<Void> task = ActivityRecognition.getClient(context)
        .removeActivityTransitionUpdates(myPendingIntent);

task.addOnSuccessListener(
    new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void result) {
            myPendingIntent.cancel();
        }
    }
);

task.addOnFailureListener(
    new OnFailureListener() {
        @Override
        public void onFailure(Exception e) {
            Log.e("MYCOMPONENT", e.getMessage());
        }
    }
);

Recursos adicionales

Para obtener más información sobre el uso de la API de User Activity Recognition, consulta los siguientes materiales:

Ejemplos

Ejemplo que muestra las prácticas recomendadas para el reconocimiento de actividad del usuario.