Getting Started WIth Activity Recognition: Android Developer Guide

This one’s for the Android devs!

Google’s Activity Recognition is so new it’s hard to find any documentation on it, although there are abundant news stories announcing it. I’ve put together a very quick guide on adding it into your app. You can find the official API docs here. It’s worth a read, it contains lines such as: “The device is on a bicycle”, which I find unreasonably funny.

You will need:
Make sure you have the latest versions of Google Play Services library – download/update using Android SDK Manager and also ADT (use Help>Check for updates). If you already have the Google Play Service library in your workspace I recommend running a Clean (Project>Clean…) after updating it, if you don’t have it import it as a library project, as described here.

Add the manifest permission:
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"\>

Note, that in contrast to Android GoogleMaps no API key is needed, suggesting this service is unlikely to be rate limited, at least not for a while.

ActivityRecognitionScan
Create a new class that can kick off a scan for ActivityRecognition, I’ve called mine ActivityRecognitionScan.class. Here it is in full:


public class ActivityRecognitionScan implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener{
private Context context;
private static final String TAG = "ActivityRecognition";
private static ActivityRecognitionClient mActivityRecognitionClient;
private static PendingIntent callbackIntent;

public ActivityRecognitionScan(Context context) {
this.context=context;
}

/**
* Call this to start a scan - don't forget to stop the scan once it's done.
* Note the scan will not start immediately, because it needs to establish a connection with Google's servers - you'll be notified of this at onConnected
*/
public void startActivityRecognitionScan(){
mActivityRecognitionClient = new ActivityRecognitionClient(context, this, this);
mActivityRecognitionClient.connect();
if(Config.TESTER_VERSION){Log.d(TAG,"startActivityRecognitionScan");}
}

public void stopActivityRecognitionScan(){
try{
mActivityRecognitionClient.removeActivityUpdates(callbackIntent);
if(Config.TESTER_VERSION){Log.d(TAG,"stopActivityRecognitionScan");}
} catch (IllegalStateException e){
// probably the scan was not set up, we'll ignore
}
}

@Override
public void onConnectionFailed(ConnectionResult result) {
if(Config.TESTER_VERSION){Log.d(TAG,"onConnectionFailed");}
}

/**
* Connection established - start listening now
*/
@Override
public void onConnected(Bundle connectionHint) {
Intent intent = new Intent(context, ActivityRecognitionService.class);
callbackIntent = PendingIntent.getService(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
mActivityRecognitionClient.requestActivityUpdates(0, callbackIntent); // 0 sets it to update as fast as possible, just use this for testing!
}

@Override
public void onDisconnected() {
}

}

Not Confi.TESTER_VERSION is a global constant boolean (public static final boolean) which I’m using to control whether logs appear.
Now we need to set up the service that is called in the above class:

Create the service to receive updates from Google Play Services

package com.opensignal.weathersignal.datacollection;

import com.google.android.gms.location.ActivityRecognitionResult;
import com.google.android.gms.location.DetectedActivity;

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

public class ActivityRecognitionService extends IntentService{

private static final String TAG ="ActivityRecognition";

public ActivityRecognitionService() {
super("ActivityRecognitionService");
}

/**
* Google Play Services calls this once it has analysed the sensor data
*/
@Override
protected void onHandleIntent(Intent intent) {
if (ActivityRecognitionResult.hasResult(intent)) {
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
if(Config.TESTER_VERSION){
Log.d(TAG, "ActivityRecognitionResult: "+getFriendlyName(result.getMostProbableActivity().getType()));
Log.d(TAG, result.toString());
}

// YOUR FUNKY CODE GOES HERE!
}
}

/**
* When supplied with the integer representation of the activity returns the activity as friendly string
* @param type the DetectedActivity.getType()
* @return a friendly string of the
*/
private static String getFriendlyName(int detected_activity_type){
switch (detected_activity_type ) {
case DetectedActivity.IN_VEHICLE:
return "in vehicle";
case DetectedActivity.ON_BICYCLE:
return "on bike";
case DetectedActivity.ON_FOOT:
return "on foot";
case DetectedActivity.TILTING:
return "tilting";
case DetectedActivity.STILL:
return "still";
default:
return "unknown";
}
}
}

Declare the service in the manifest
Don’t forget to declare this service in the Manifest – doing so won’t throw any errors, but your code won’t work.

Now all you need to do is call new ActivityRecognitionScan(this).startActivityRecognitionScan() from an activity and you should start getting udpates if you have a network connection – though it may take a couple of seconds.

Make sure you don’t break compatibility
Note, you’ll likely want to check:

GooglePlayServicesUtil.isGooglePlayServicesAvailable(context)==ConnectionResult.SUCCESS

Before calling any services that depend on Google Play Services.

Have fun!

This entry was posted in Android Development. Bookmark the permalink.

2 Responses to Getting Started WIth Activity Recognition: Android Developer Guide

  1. drmendozaz says:

    Hi, thank you for this amazing guide!

    I want to implement the Activity Recognition using an Android Service instead of an IntentService in order to keep the scan running in the foreground as described .

    Could you give me a hint of how can I achieve that?

    Thanks in advance!

    Daniel

  2. drmendozaz says:

    Hi, thank you for this amazing guide!

    I want to implement the Activity Recognition using an Android Service instead of an IntentService in order to keep the scan running in the foreground as described here.

    Could you give me a hint of how can I achieve that?

    Thanks in advance!

    Daniel

Leave a Reply