Activity Recognition API Tutorial for Android: Getting Started

Learn to track your activities in your Android app by creating a fitness app that uses the Activity Recognition API. By Andrej Vukelic.

4 (4) · 2 Reviews

Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Tracking Activities in the Background

Apps that track your activity should work in the background so you can still use other apps on your mobile device. In this section, you’ll learn how to use the Sampling API and run it in the background service.

Remember how you requested transition updates from the ActivityRecognitionClient? Requesting activity sampling updates is almost the same process.

Find DetectedActivityService.kt. Then replace TODO 15 with:

val task = ActivityRecognitionClient(this).requestActivityUpdates(ACTIVITY_UPDATES_INTERVAL,
        DetectedActivityReceiver.getPendingIntent(this))

    task.run {
      addOnSuccessListener {
        Log.d("ActivityUpdate", getString(R.string.activity_update_request_success))
      }
      addOnFailureListener {
        Log.d("ActivityUpdate", getString(R.string.activity_update_request_failed))
      }
    }

In the above code, you can see the process is pretty much the same as requesting transition updates. You create a task and apply success and failure listeners to that task. The difference is that now you call requestActivityUpdates which takes detectionInterval and the activity’s pending intent as parameters and updates the receiver’s PendingIntent.

Now, ActivityRecognitionClient will send periodic updates to your app.

Next, add code to stop the updates in case a user closes the app. Find TODO 16 and replace it with:

val task = ActivityRecognitionClient(this).removeActivityUpdates(
        DetectedActivityReceiver.getPendingIntent(this))

    task.run {
      addOnSuccessListener {
        Log.d("ActivityUpdate", getString(R.string.activity_update_remove_success))
      }
      addOnFailureListener {
        Log.d("ActivityUpdate", getString(R.string.activity_update_remove_failed))
      }
    }

This code removes all activity updates specified for PendingIntent. It also helps you control battery consumption.

Now, you’ll register the service and broadcast receiver in AndroidManifes.xml.

Open AndroidManifes.xml. Find TODO 17 and replace it with:

<service android:name=".detectedactivity.DetectedActivityService" />
<receiver android:name=".detectedactivity.DetectedActivityReceiver"/>

This code lets your service and receiver work in the background.

Now, switch to DetectedActivityReceiver.kt. Here, you’ll handle messages received from the ActivityRecognitionClient.

First, find TODO 18 and uncomment handleDetectedActivities and showNotification. Next, add the imports:

import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.google.android.gms.location.DetectedActivity
import com.raywenderlich.android.petbuddy.MainActivity
import com.raywenderlich.android.petbuddy.R
import com.raywenderlich.android.petbuddy.SUPPORTED_ACTIVITY_KEY
import com.raywenderlich.android.petbuddy.SupportedActivity

Now, you’ll handle the Intent received from the ActivityRecognitionClient with the same steps you used for transition updates. Find TODO 19, and replace it with:

// 1
if (ActivityRecognitionResult.hasResult(intent)) {
 // 2
 val result = ActivityRecognitionResult.extractResult(intent)
 // 3
 result?.let { handleDetectedActivities(it.probableActivities, context) }
}

Here, the logic:

  1. Checks if the received intent contains a wanted result.
  2. Then, extracts ActivityRecognitionResult from the intent.
  3. If the result is not null, it handles probable activities.

probableActivites is a sorted list of activities based on confidence grades. Since your pet likes to walk and run, you don’t want to track any other activities. Okay, you’ll take standing still into consideration, too.

In DetectedActivityReceiver.kt, find TODO 20. Replace it with:

detectedActivities
        .filter {
          it.type == DetectedActivity.STILL ||
              it.type == DetectedActivity.WALKING ||
              it.type == DetectedActivity.RUNNING
        }
        .filter { it.confidence > RELIABLE_CONFIDENCE }
        .run {
          if (isNotEmpty()) {
            showNotification(this[0], context)
          }
        }

First, you filter activities you’re interested in. Then, you filter activities with a confidence grade over 75% because you’re only interested in the most probable activity.

Voila! The notification is here.

When you requested permission, you logged a message on permission granted. In the MainActivity.kt, find TODO 21. In the else branch above it, add:

  startService(Intent(this, DetectedActivityService::class.java))
  requestActivityTransitionUpdates()

When a user taps Start on a fresh install of the app, the permission dialog shows. When a user allows the permission, it’ll start tracking activity.

Great job! You’re ready to use the Sampling API.

Build and run. Go outside, start tracking and pay attention to the status bar. You’ll see a notification like this:

Notification with standing still status

Congratulations! You created your first activity tracker app. Take your dog for a walk and enjoy nature.

Where to Go From Here?

In this tutorial, you learned why and how to use the Activity Recognition API. You used the Activity Recognition Client to detect the start and end of an activity and how to keep track of activity transitions. You also learned about confidence grades and tracking activities in the background.

You can download the complete project by clicking Download Materials at the top or bottom of this tutorial.

If you want to know more about this topic, check out the official documentation for building apps with Android Recognition Client.

There’s one API left in the Android Recognition Client. Take a look at the official documentation for Sleep API.