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(); } }); }