Android Activity Recognition API

What is the Activity Recognition API?

Detect when users start or end an activity

How can I use the Activity Recognition API?

Activity Recognition

ActivityRecognitionClient mActivityRecognitionClient = new ActivityRecognitionClient(this);Task<Void> task = mActivityRecognitionClient.requestActivityUpdates(Constants.DETECTION_INTERVAL_IN_MILLISECONDS,mPendingIntent);ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);ArrayList<DetectedActivity> detectedActivities = (ArrayList) result.getProbableActivities();for (DetectedActivity activity : detectedActivities) {Log.e(TAG, "Detected activity: " + activity.getType() + ", " + activity.getConfidence());}

Setup Project for Android App

implementation 'com.google.android.gms:play-services-location:16.0.0'
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/txt_activity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="48dp"
android:textAllCaps="true"
android:textColor="@color/colorPrimary"
android:textSize="18dp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/txt_confidence"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/txt_confidence"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="24dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:textAllCaps="true"
android:textSize="14dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_start_tracking"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:text="Start Tracking"
app:layout_constraintBottom_toTopOf="@+id/btn_stop_tracking"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btn_stop_tracking"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:text="Stop Tracking"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</android.support.constraint.ConstraintLayout>
<resources>
<string name="app_name">Activity Recognition</string>
<string name="activity_in_vehicle">In Vehicle</string>
<string name="activity_on_bicycle">On Bicycle</string>
<string name="activity_on_foot">On Foot</string>
<string name="activity_running">Running</string>
<string name="activity_still">Still</string>
<string name="activity_tilting">Tilting</string>
<string name="activity_walking">walking</string>
<string name="activity_unknown">Unknown</string>
</resources>
class DetectedActivitiesIntentService : IntentService(TAG) {    override fun onCreate() {
super.onCreate()
}
override fun onHandleIntent(intent: Intent?) {
val result = ActivityRecognitionResult.extractResult(intent)
// Get the list of the probable activities associated with the current state of the
// device. Each activity is associated with a confidence level, which is an int between
// 0 and 100.
val detectedActivities = result.probableActivities as ArrayList<*>
for (activity in detectedActivities) {
broadcastActivity(activity as DetectedActivity)
}
}
private fun broadcastActivity(activity: DetectedActivity) {
val intent = Intent(MainActivity.BROADCAST_DETECTED_ACTIVITY)
intent.putExtra("type", activity.type)
intent.putExtra("confidence", activity.confidence)
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
}
companion object { protected val TAG = DetectedActivitiesIntentService::class.java.simpleName
}
}// Use the TAG to name the worker thread.
class BackgroundDetectedActivitiesService : Service() {    private lateinit var mIntentService: Intent
private lateinit var mPendingIntent: PendingIntent
private lateinit var mActivityRecognitionClient: ActivityRecognitionClient
internal var mBinder: IBinder = LocalBinder() inner class LocalBinder : Binder() {
val serverInstance: BackgroundDetectedActivitiesService
get() = this@BackgroundDetectedActivitiesService
}
override fun onCreate() {
super.onCreate()
mActivityRecognitionClient = ActivityRecognitionClient(this)
mIntentService = Intent(this, DetectedActivitiesIntentService::class.java)
mPendingIntent = PendingIntent.getService(this, 1, mIntentService, PendingIntent.FLAG_UPDATE_CURRENT)
requestActivityUpdatesButtonHandler()
}
override fun onBind(intent: Intent): IBinder? {
return mBinder
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId)
return Service.START_STICKY
}
fun requestActivityUpdatesButtonHandler() {
val task = mActivityRecognitionClient?.requestActivityUpdates(
MainActivity.DETECTION_INTERVAL_IN_MILLISECONDS,
mPendingIntent)
task?.addOnSuccessListener {
Toast.makeText(applicationContext,
"Successfully requested activity updates",
Toast.LENGTH_SHORT)
.show()
}
task?.addOnFailureListener {
Toast.makeText(applicationContext,
"Requesting activity updates failed to start",
Toast.LENGTH_SHORT)
.show()
}
}
fun removeActivityUpdatesButtonHandler() {
val task = mActivityRecognitionClient?.removeActivityUpdates(
mPendingIntent)
task?.addOnSuccessListener {
Toast.makeText(applicationContext,
"Removed activity updates successfully!",
Toast.LENGTH_SHORT)
.show()
}
task?.addOnFailureListener {
Toast.makeText(applicationContext, "Failed to remove activity updates!",
Toast.LENGTH_SHORT).show()
}
}
override fun onDestroy() {
super.onDestroy()
removeActivityUpdatesButtonHandler()
}
companion object {
private val TAG = BackgroundDetectedActivitiesService::class.java?.getSimpleName()
}
}
class MainActivity : AppCompatActivity() {    private val TAG = MainActivity::class.java.simpleName
internal lateinit var broadcastReceiver: BroadcastReceiver
private lateinit var txtActivity: TextView
private lateinit var txtConfidence: TextView
private lateinit var btnStartTrcking: Button
private lateinit var btnStopTracking: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
txtActivity = findViewById(R.id.txt_activity)
txtConfidence = findViewById(R.id.txt_confidence)
btnStartTrcking = findViewById(R.id.btn_start_tracking)
btnStopTracking = findViewById(R.id.btn_stop_tracking)
btnStartTrcking?.setOnClickListener { startTracking() } btnStopTracking?.setOnClickListener { stopTracking() } broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == MainActivity.BROADCAST_DETECTED_ACTIVITY) {
val type = intent.getIntExtra("type", -1)
val confidence = intent.getIntExtra("confidence", 0)
handleUserActivity(type, confidence)
}
}
}
startTracking()
}
private fun handleUserActivity(type: Int, confidence: Int) {
var label = getString(R.string.activity_unknown)
when (type) {
DetectedActivity.IN_VEHICLE -> {
label = "You are in Vehicle"
}
DetectedActivity.ON_BICYCLE -> {
label = "You are on Bicycle"
}
DetectedActivity.ON_FOOT -> {
label = "You are on Foot"
}
DetectedActivity.RUNNING -> {
label = "You are Running"
}
DetectedActivity.STILL -> {
label = "You are Still"
}
DetectedActivity.TILTING -> {
label = "Your phone is Tilted"
}
DetectedActivity.WALKING -> {
label = "You are Walking"
}
DetectedActivity.UNKNOWN -> {
label = "Unkown Activity"
}
}
Log.e(TAG, "User activity: $label, Confidence: $confidence") if (confidence > MainActivity.CONFIDENCE) {
txtActivity?.text = label
txtConfidence?.text = "Confidence: $confidence"
}
}
override fun onResume() {
super.onResume()
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver,
IntentFilter(MainActivity.BROADCAST_DETECTED_ACTIVITY))
}
override fun onPause() {
super.onPause()
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver)
}
private fun startTracking() {
val intent = Intent(this@MainActivity, BackgroundDetectedActivitiesService::class.java)
startService(intent)
}
private fun stopTracking() {
val intent = Intent(this@MainActivity, BackgroundDetectedActivitiesService::class.java)
stopService(intent)
}
companion object { val BROADCAST_DETECTED_ACTIVITY = "activity_intent" internal val DETECTION_INTERVAL_IN_MILLISECONDS: Long = 1000 val CONFIDENCE = 70
}
}

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Abhishek Srivastava

Abhishek Srivastava

165 Followers

Senior Software Engineer | Android | Java | Kotlin |Xamarin Native Android |Flutter |Go