Jul 23, 2013

Android ActivityRecognition Example


Introduction
Activity Recognition is very interesting API, It can open a gate of whole new kind of application and so helps to optimise existing apps, Activity Recognition is very simple API, It recognises four activities 1] In vehicle,2] On bicycle, 3] On foot and 4] Still. 

Location based application can take advantage of Activity Recognition API to optimise, accurate and battery efficient application with combination of Fused Location providers. Normally location based application fetch location periodically and push to the server, which is not optimise, Based on user's activity we can increase, decrease or stop location request.

Useful Methods
1. ActivityRecognitionClient
  • connect()
  • disconnect()
  • requestActivityUpdates()
  • removeActivityUpdates()
2. ActivityRecognitionResult
  • hasResult()
  • extractResult()
  • getMostProbableActivity().getType()
  • getMostProbableActivity().getConfidence()
Process
Let's understand with this diagram


1] Following operation needs to be done in Activity
  • Check availability of Google Play Service using "isGooglePlayServiceAvailable" function
  • If Google Play Service is available then do following steps
    • Implements ConnectCallback and OnConnectionFailedListener
    • Create Object of ActivityRecognitionClient 
    • Call connect() method using object of ActivityRecognitionClient.
    • onConnect method will call after connection is established between app and Google Play service. In this method we should start request for Activity Recognition.
    • Create and register BroadcastReceiver.
  • In Destroy method 
    • We need to remove activityupdates, disconnect with Google Play Service and remove BroadcastReceiver. 
2] In this example I am using BroadcastReceiver to pass ActivityRecognition data from IntentService to Activity. You can use any other technique as per requirement.

3] Google Play Service pass ActivityRecognitionResult object through Intent in IntentService.
4] Fire a BroadcastReceiver with Activity Type and Confidence.
5] Activity receives data and displays in TextView.

Application Screenshot

Source Code

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.kpbird.myactivityrecognition"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="17" />

    <uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        
        <activity
            android:name="com.kpbird.myactivityrecognition.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="ActivityRecognitionService"></service>
    </application>

</manifest>

activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/tvActivity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:text="@string/hello_world" />

</RelativeLayout>

MainActivity.java
package com.kpbird.myactivityrecognition;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.ActivityRecognitionClient;

public class MainActivity extends Activity implements GooglePlayServicesClient.ConnectionCallbacks,GooglePlayServicesClient.OnConnectionFailedListener {

 private ActivityRecognitionClient arclient;
 private PendingIntent pIntent;
 private BroadcastReceiver receiver;
 private TextView tvActivity;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  tvActivity = (TextView) findViewById(R.id.tvActivity);
  
  int resp =GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
  if(resp == ConnectionResult.SUCCESS){
   arclient = new ActivityRecognitionClient(this, this, this);
   arclient.connect();
   
   
  }
  else{
   Toast.makeText(this, "Please install Google Play Service.", Toast.LENGTH_SHORT).show();
  }
  
  receiver = new BroadcastReceiver() {
      @Override
      public void onReceive(Context context, Intent intent) {
       String v =  "Activity :" + intent.getStringExtra("Activity") + " " + "Confidence : " + intent.getExtras().getInt("Confidence") + "n";
       v += tvActivity.getText();
       tvActivity.setText(v);
      }
    };
    
   IntentFilter filter = new IntentFilter();
   filter.addAction("com.kpbird.myactivityrecognition.ACTIVITY_RECOGNITION_DATA");
   registerReceiver(receiver, filter);
  
 }
 
 
 @Override
 protected void onDestroy() {
  super.onDestroy();
  if(arclient!=null){
   arclient.removeActivityUpdates(pIntent);
   arclient.disconnect();
  }
  unregisterReceiver(receiver);
 }
 
 @Override
 public void onConnectionFailed(ConnectionResult arg0) {
  Toast.makeText(this, "Connection Failed", Toast.LENGTH_SHORT).show();
 }
 @Override
 public void onConnected(Bundle arg0) {
  Intent intent = new Intent(this, ActivityRecognitionService.class);
  pIntent = PendingIntent.getService(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
  arclient.requestActivityUpdates(1000, pIntent);   
 }
 @Override
 public void onDisconnected() {
 }

 
}


ActivityRecognitionService.java
package com.kpbird.myactivityrecognition;

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 String TAG = this.getClass().getSimpleName();
 public ActivityRecognitionService() {
  super("My Activity Recognition Service");
 }

 @Override
 protected void onHandleIntent(Intent intent) {
  if(ActivityRecognitionResult.hasResult(intent)){
   ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
   Log.i(TAG, getType(result.getMostProbableActivity().getType()) +"t" + result.getMostProbableActivity().getConfidence());
   Intent i = new Intent("com.kpbird.myactivityrecognition.ACTIVITY_RECOGNITION_DATA");
   i.putExtra("Activity", getType(result.getMostProbableActivity().getType()) );
   i.putExtra("Confidence", result.getMostProbableActivity().getConfidence());
   sendBroadcast(i);
  }
 }
 
 private String getType(int type){
  if(type == DetectedActivity.UNKNOWN)
   return "Unknown";
  else if(type == DetectedActivity.IN_VEHICLE)
   return "In Vehicle";
  else if(type == DetectedActivity.ON_BICYCLE)
   return "On Bicycle";
  else if(type == DetectedActivity.ON_FOOT)
   return "On Foot";
  else if(type == DetectedActivity.STILL)
   return "Still";
  else if(type == DetectedActivity.TILTING)
   return "Tilting";
  else
   return "";
 }

}

Download Source Code from Github

References