Reconocimiento de actividad en Android

En este artículo, vamos a aprender sobre una API llamada API de transición de reconocimiento de actividad o API de transición  que está destinada a detectar la actividad de un usuario en particular, como conducir, caminar o correr, etc. Hay muchas aplicaciones que utilizan esta actividad. API de transición de reconocimiento. Por ejemplo, una aplicación de búsqueda de kilómetros comienza a ejecutarse cuando comienza a conducir un automóvil o una bicicleta y se detiene cuando deja de conducir. Otros ejemplos de este reconocimiento de actividad pueden ser cualquier aplicación de salud y estado físico que determine cuántos metros o kilómetros está corriendo o caminando en un día en particular y luego puede encontrar las calorías quemadas en ese día y mucho más.

Aquí vamos a crear una aplicación que detectará la actividad del usuario, como estar quieto, correr, caminar , conducir u otra cosa . A continuación se muestra una imagen de captura de pantalla de muestra para tener una idea de lo que vamos a hacer en este artículo. 

Implementación paso a paso

Paso 1: Crear un nuevo proyecto

Para crear un nuevo proyecto en Android Studio, consulte Cómo crear/iniciar un nuevo proyecto en Android Studio . Tenga en cuenta que seleccione Kotlin como lenguaje de programación.

Paso 2: Agregar dependencias

// Ubicación del servicio de Google Play

implementación ‘com.google.android.gms:play-services-ubicación:18.0.0’

implementación “androidx.preference:preference-ktx:1.1.1”

// Madera

implementación ‘com.jakewharton.timber:timber:4.7.1’

// Biblioteca de notificaciones

implementación “io.karn:notify:1.3.0”

// Permisos fáciles

implementación ‘pub.devrel:permisosfáciles:3.0.0’

// Diseño de materiales

implementación ‘com.google.android.material:material:1.5.0-alpha02’

Paso 3: Agregue una referencia al repositorio maven en el build.gradle de nivel superior

todos los proyectos {

   repositorios {

       …

       // Para la biblioteca Notificar

       experto {url ‘https://jitpack.io’}

   }

}

Paso 4: Trabajar con AndroidMenifest.xml

Asegúrese de agregar los siguientes permisos 

  <!– Obligatorio para menores de 28 años. –>

  <usos-permiso android:name=”com.google.android.gms.permission.ACTIVITY_RECOGNITION” />

  <!– Requerido para mayores de 29 años. –>

   <usos-permiso android:name=”android.permission.ACTIVITY_RECOGNITION” />

<aplicación>

….

<actividad>

….

</actividad>

<receptor

          android:name=”.ActivityTransitionReceiver”

          Android: exportado = «falso»

          android:permiso=”com.google.android.gms.permiso.ACTIVIDAD_RECONOCIMIENTO”>

          <intent-filter>

              <acción android:name=”acción.TRANSITIONS_DATA” />

          </intent-filter>

      </receptor>

</aplicación>

Paso 5: agregar la interfaz de usuario de la aplicación.

Vaya a la aplicación > res > diseño > actividad_principal.xml y agregue el siguiente código a ese archivo. A continuación se muestra el código para el archivo activity_main.xml .

XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
  
    <com.google.android.material.switchmaterial.SwitchMaterial
        android:id="@+id/switchActivityTransition"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Activity Transition"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
  
</androidx.constraintlayout.widget.ConstraintLayout>

Paso 6: Cree la clase Constant.kt y escriba todas las constantes requeridas aquí

Kotlin

// declare all required constants at one place
object Constants {
    const val REQUEST_CODE_ACTIVITY_TRANSITION = 123
    const val REQUEST_CODE_INTENT_ACTIVITY_TRANSITION = 122
    const val ACTIVITY_TRANSITION_NOTIFICATION_ID = 111
    const val ACTIVITY_TRANSITION_STORAGE = "ACTIVITY_TRANSITION_STORAGE"
}

En Android, tenemos el Cliente de reconocimiento de actividad que activa su dispositivo a intervalos regulares y luego recopila la información del sensor del dispositivo y luego esta información recopilada se utilizará para determinar las actividades con la ayuda de algún cálculo de aprendizaje automático. Simplemente debe utilizar el Cliente de reconocimiento de actividad y la API terminará para usted sin ninguna razón convincente para aprender ML.

 Las siguientes son las actividades que puede detectar el cliente de reconocimiento de actividad:

  • STILL: cuando el dispositivo móvil esté quieto cuando el usuario esté sentado en algún lugar o el dispositivo móvil no tenga movimiento, el cliente de reconocimiento de actividad detectará la actividad STILL.
  • ON_FOOT: cuando el dispositivo móvil se mueve a una velocidad normal, es decir, el usuario que lleva el dispositivo móvil camina o corre, el cliente de reconocimiento de actividad detectará la actividad ON_FOOT.
  • CAMINAR: esta es una subactividad de la actividad ON_FOOT que detecta el cliente de reconocimiento de actividad cuando el usuario que lleva el dispositivo móvil está caminando.
  • EJECUTANDO: Esta también es una subactividad de la actividad ON_FOOT que detecta el cliente de reconocimiento de actividad cuando el usuario que lleva el dispositivo móvil está corriendo.
  • IN_VEHICLE: esta actividad se detecta cuando el dispositivo móvil está en el autobús, automóvil o algún otro tipo de vehículo o el usuario que sostiene el dispositivo móvil está presente en el vehículo.
  • ON_BICYCLE: Cuando el dispositivo está en la bicicleta o el usuario que lleva el móvil está en una bicicleta entonces se detectará esta actividad.
  • INCLINACIÓN: cuando el dispositivo móvil se levanta y tiene algún ángulo con la superficie plana, el cliente de reconocimiento de actividad detectará esta actividad.
  • DESCONOCIDO: el cliente de reconocimiento de actividad mostrará este resultado cuando el dispositivo no pueda detectar ninguna actividad en el dispositivo móvil.

Paso 7: Cree la clase ActivityTransitionsUtil.kt que contendrá una lista de tipos de actividades y tipos de transición

Para comenzar a recibir notificaciones sobre transiciones de actividad, debemos crear un objeto ActivityTransitionRequest que determine el tipo de actividad y transición. Para ello, debemos crear una lista de objetos ActivityTransition y pasarla a la clase ActivityTransitionRequest. A continuación se muestra el código completo de la clase ActivityTransitionsUtil.kt. Se agregan comentarios dentro del código para comprender cada línea del código.

Kotlin

import android.Manifest
import android.content.Context
import android.os.Build
import androidx.annotation.RequiresApi
import com.google.android.gms.location.ActivityTransition
import com.google.android.gms.location.ActivityTransitionRequest
import com.google.android.gms.location.DetectedActivity
import pub.devrel.easypermissions.EasyPermissions
  
object ActivityTransitionsUtil {
    private fun getTransitions(): MutableList<ActivityTransition> {
  
        // List of activity transitions to track
        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_ENTER)
                .build()
  
        transitions +=
            ActivityTransition.Builder()
                .setActivityType(DetectedActivity.WALKING)
                .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
                .build()
  
        transitions +=
            ActivityTransition.Builder()
                .setActivityType(DetectedActivity.STILL)
                .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
                .build()
  
        transitions +=
            ActivityTransition.Builder()
                .setActivityType(DetectedActivity.STILL)
                .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
                .build()
  
        transitions +=
            ActivityTransition.Builder()
                .setActivityType(DetectedActivity.RUNNING)
                .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
                .build()
  
        transitions +=
            ActivityTransition.Builder()
                .setActivityType(DetectedActivity.RUNNING)
                .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
                .build()
  
        return transitions
    }
  
    // pass the list of ActivityTransition objects to the ActivityTransitionRequest class
    fun getActivityTransitionRequest() = ActivityTransitionRequest(getTransitions())
  
    // ask to allow permissions
    @RequiresApi(Build.VERSION_CODES.Q)
    fun hasActivityTransitionPermissions(context: Context): Boolean =
        EasyPermissions.hasPermissions(
            context,
            Manifest.permission.ACTIVITY_RECOGNITION
        )
  
    // types of activities
    fun toActivityString(activity: Int): String {
        return when (activity) {
            DetectedActivity.STILL -> "STILL"
            DetectedActivity.WALKING -> "WALKING"
            DetectedActivity.IN_VEHICLE -> "IN VEHICLE"
            DetectedActivity.RUNNING -> "RUNNING"
            else -> "UNKNOWN"
        }
    }
  
    // type of transitions
    fun toTransitionType(transitionType: Int): String {
        return when (transitionType) {
            ActivityTransition.ACTIVITY_TRANSITION_ENTER -> "ENTER"
            ActivityTransition.ACTIVITY_TRANSITION_EXIT -> "EXIT"
            else -> "UNKNOWN"
        }
    }
}

Paso 8: Cree la clase ActivityTransitionReceiver.kt que recibe las actividades y notifica el estado del usuario 

A continuación se muestra el código completo de la clase ActivityTransitionReceiver.kt. Se agregan comentarios dentro del código para comprender cada línea del código.

Kotlin

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast
import com.google.android.gms.location.ActivityTransitionResult
import io.karn.notify.Notify
import java.text.SimpleDateFormat
import java.util.*
  
class ActivityTransitionReceiver : BroadcastReceiver() {
  
    override fun onReceive(context: Context, intent: Intent) {
        if (ActivityTransitionResult.hasResult(intent)) {
            val result = ActivityTransitionResult.extractResult(intent)
            result?.let {
                result.transitionEvents.forEach { event ->
                    // Info about activity
                    val info =
                        "Transition: " + ActivityTransitionsUtil.toActivityString(event.activityType) +
                                " (" + ActivityTransitionsUtil.toTransitionType(event.transitionType) + ")" + "   " +
                                SimpleDateFormat("HH:mm:ss", Locale.US).format(Date())
                    // notification details
                    Notify
                        .with(context)
                        .content {
                            title = "Activity Detected"
                            text = "I can see you are in ${
                                ActivityTransitionsUtil.toActivityString(
                                    event.activityType
                                )
                            } state"
                        }
                        .show(id = Constants.ACTIVITY_TRANSITION_NOTIFICATION_ID)
                    Toast.makeText(context, info, Toast.LENGTH_LONG).show()
                }
            }
        }
    }
}

Paso 9: trabajar con MainActivity.kt. A continuación se muestra el código de MainActivity.kt 

A continuación se muestra el código completo del archivo MainActivity.kt . Se agregan comentarios dentro del código para comprender cada línea del código.

Kotlin

import android.Manifest
import android.app.PendingIntent
import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import com.gfg.article.activityrecognition.Constants.ACTIVITY_TRANSITION_STORAGE
import com.google.android.gms.location.ActivityRecognition
import com.google.android.gms.location.ActivityRecognitionClient
import kotlinx.android.synthetic.main.activity_main.*
import pub.devrel.easypermissions.AppSettingsDialog
import pub.devrel.easypermissions.EasyPermissions
  
class MainActivity : AppCompatActivity(), EasyPermissions.PermissionCallbacks {
  
    lateinit var client: ActivityRecognitionClient
    lateinit var storage: SharedPreferences
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
  
        // The Activity Recognition Client returns a 
          // list of activities that a user might be doing
        client = ActivityRecognition.getClient(this)
          
        // variable to check whether the user have already given the permissions
        storage = androidx.preference.PreferenceManager.getDefaultSharedPreferences(this)
  
        // check switch is on/off
        switchActivityTransition.isChecked = getSwitchState()
  
        switchActivityTransition.setOnCheckedChangeListener { _, isChecked ->
            if (isChecked) {
                // check for devices with Android 10 (29+).
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
                    // check for permission
                    && !ActivityTransitionsUtil.hasActivityTransitionPermissions(this)
                ) {
                    switchActivityTransition.isChecked = false
                    // request for permission
                    requestActivityTransitionPermission()
                } else {
                    // when permission is already allowed
                    requestForUpdates()
                }
            } else {
                saveSwitchState(false)
                deregisterForUpdates()
            }
        }
    }
  
    // when permission is denied
    @RequiresApi(Build.VERSION_CODES.Q)
    override fun onPermissionsDenied(requestCode: Int, perms: MutableList<String>) {
        // permission is denied permanently
        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            AppSettingsDialog.Builder(this).build().show()
        } else {
            requestActivityTransitionPermission()
        }
    }
  
    // after giving permission
    override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) {
        switchActivityTransition.isChecked = true
        saveSwitchState(true)
        requestForUpdates()
    }
  
    // request for permission
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
    }
  
    // To register for changes we have to also supply the requestActivityTransitionUpdates() method
    // with the PendingIntent object that will contain an intent to the component
    // (i.e. IntentService, BroadcastReceiver etc.) that will receive and handle updates appropriately.
    private fun requestForUpdates() {
        client
            .requestActivityTransitionUpdates(
                ActivityTransitionsUtil.getActivityTransitionRequest(),
                getPendingIntent()
            )
            .addOnSuccessListener {
                showToast("successful registration")
            }
            .addOnFailureListener {
                showToast("Unsuccessful registration")
            }
    }
  
    // Deregistering from updates
    // call the removeActivityTransitionUpdates() method
    // of the ActivityRecognitionClient and pass 
    // ourPendingIntent object as a parameter
    private fun deregisterForUpdates() {
        client
            .removeActivityTransitionUpdates(getPendingIntent())
            .addOnSuccessListener {
                getPendingIntent().cancel()
                showToast("successful deregistration")
            }
            .addOnFailureListener { e: Exception ->
                showToast("unsuccessful deregistration")
            }
    }
  
    // creates and returns the PendingIntent object which holds 
    // an Intent to an BroadCastReceiver class
    private fun getPendingIntent(): PendingIntent {
        val intent = Intent(this, ActivityTransitionReceiver::class.java)
        return PendingIntent.getBroadcast(
            this,
            Constants.REQUEST_CODE_INTENT_ACTIVITY_TRANSITION,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT
        )
    }
  
    // requesting for permission
    @RequiresApi(Build.VERSION_CODES.Q)
    private fun requestActivityTransitionPermission() {
        EasyPermissions.requestPermissions(
            this,
            "You need to allow Activity Transition Permissions in order to recognize your activities",
            Constants.REQUEST_CODE_ACTIVITY_TRANSITION,
            Manifest.permission.ACTIVITY_RECOGNITION
        )
    }
  
    private fun showToast(message: String) {
        Toast.makeText(this, message, Toast.LENGTH_LONG)
            .show()
    }
  
    // save switch state
    private fun saveSwitchState(value: Boolean) {
        storage
            .edit()
            .putBoolean(ACTIVITY_TRANSITION_STORAGE, value)
            .apply()
    }
  
    // get the state of switch
    private fun getSwitchState() = storage.getBoolean(ACTIVITY_TRANSITION_STORAGE, false)
}

Ahora, ejecuta la aplicación

Producción:

Cuando el usuario camina

Cuando el usuario no tiene movimiento

Código fuente: Haga clic aquí

Publicación traducida automáticamente

Artículo escrito por anju1406 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *