Transition API can tell if your users are walking, running, cycling, or in a vehicle and you can use it to improve your app experience.

Transition API combine various signals like location and sensor data to determine when the user has started or ended an activity like walking or driving.

1.Add Dependencies


Declare a dependency to the API, add a reference to the Google maven repository and add an implementation entry to com.google.android.gms:play-services-location:12.0.0 to the dependencies section of your app build.gradle file.

dependencies {
    ....
    implementation 'com.google.android.gms:play-services-location:12.0.0'
    ...
}

2.Add Permission


Specify the com.google.android.gms.permission.ACTIVITY_RECOGNITION permission in the app manifest.

<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>

3.Register for activity transition updates


To start receiving notifications about activity transitions, you must implement, An ActivityTransitionRequest object that specifies the type of activity and transition.PendingIntent callback where your app receives notifications.

ActivityTransitionRequest

You must create a list of ActivityTransition objects, which represent the transition that you want to receive notifications about. An ActivityTransition object includes the 1.An activity type  IN_VEHICLE,ON_BICYCLE,RUNNING,STILL,WALKING

2.A transition type of ACTIVITY_TRANSITION_ENTER or ACTIVITY_TRANSITION_EXIT. For more information, refer to theActivityTransition class.

The following code shows how to create a list of ActivityTransition objects:

private List<ActivityTransition> transitions;
private ActivityRecognitionClient activityRecognitionClient;
private PendingIntent transitionPendingIntent;
private Context mContext;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ....
    mContext = this;
    activityRecognitionClient = ActivityRecognition.getClient(mContext);

    Intent intent = new Intent(this, TransitionIntentService.class);
    transitionPendingIntent = PendingIntent.getService(this, 100, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

public void registerHandler(View view) {
    transitions = new ArrayList<>();

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


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


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

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

PendingIntent

When using the API, a common use case is that an application wants to monitor activity in the background and perform an action when a specific activity is detected.The application specifies a pending intent callback typically an intent service, which will be called with an intent when activities are detected.So there’s no need to keep the service always running in the background.

public void registerHandler(View view) {
     
    .....    

    ActivityTransitionRequest activityTransitionRequest 
                               = new ActivityTransitionRequest(transitions);

    Task<Void> task = activityRecognitionClient.requestActivityTransitionUpdates(activityTransitionRequest, transitionPendingIntent);

     task.addOnSuccessListener(new OnSuccessListener<Void>() {
          @Override
          public void onSuccess(Void aVoid) {
              Toast.makeText(mContext, "Transition update set up", Toast.LENGTH_LONG).show();
          }
     });

     task.addOnFailureListener(new OnFailureListener() {
          @Override
          public void onFailure(@NonNull Exception e) {
               Toast.makeText(mContext, "Transition update Failed to set up", Toast.LENGTH_LONG).show();
               e.printStackTrace();
          }
     });
}

After successfully registering for activity transition updates, your app receives notifications in the registered PendingIntent.

4.Receive activity transition events


When the requested activity transition occurs, you app receives an Intent callback.The events are ordered in chronological order, for example, if an app requests for the IN_VEHICLE activity type on the ACTIVITY_TRANSITION_ENTER and ACTIVITY_TRANSITION_EXIT transitions, then it receives an ActivityTransitionEvent object when the user starts driving, and another one when the user transitions to any other activity.

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

import com.google.android.gms.location.ActivityTransitionEvent;
import com.google.android.gms.location.ActivityTransitionResult;


public class TransitionIntentService extends IntentService {

    private static final String TAG = TransitionIntentService.class.getSimpleName();

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

    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            if (ActivityTransitionResult.hasResult(intent)) {
                ActivityTransitionResult result = ActivityTransitionResult.extractResult(intent);
                for (ActivityTransitionEvent event : result.getTransitionEvents()) {

                    Toast.makeText(this, event.getTransitionType() + "-" + event.getActivityType(), Toast.LENGTH_LONG).show();
                    //7 for walking and 8 for running
                    Log.i(TAG, "Activity Type " + event.getActivityType());

                    // 0 for enter, 1 for exit
                    Log.i(TAG, "Transition Type " + event.getTransitionType());
                }
            }
        }
    }
}

Your application will receive callbacks with extras containing an activity recognition result.This contains a list of activities that the user may be doing at the particular time.

5.Deregister for activity transition updates


Deregister for activity transition updates by calling the removeActivityTransitionUpdates() method of the ActivityRecognitionClient and passing your PendingIntent object as a parameter.

public void deregisterHandler(View view) {
    Task<Void> task = activityRecognitionClient.removeActivityTransitionUpdates(transitionPendingIntent);
    task.addOnSuccessListener(new OnSuccessListener<Void>() {
         @Override
         public void onSuccess(Void aVoid) {
             transitionPendingIntent.cancel();
             Toast.makeText(mContext, "Remove Activity Transition Successfully", Toast.LENGTH_LONG).show();
         }
    });

    task.addOnFailureListener(new OnFailureListener() {
         @Override
         public void onFailure(@NonNull Exception e) {
             Toast.makeText(mContext, "Remove Activity Transition Failed", Toast.LENGTH_LONG).show();
             e.printStackTrace();
         }
    });
}

Download this project from GitHub