I'm new to android development. Now, I'm trying to develop an app for detecting user activities. In this case, I used Google Play Services Activity Recognition API, and also, I followed the instructions (e.g., the google sample code for the API).

The app runs successfully and correctly with full functionality (on the app side), also I'm registered for the API successfully using the requestActivityTransitionUpdates().

The problem is the API doesn't update the user transition events and the ActivityTransitionResult.extractResult(intent).transitionEvents() is always empty. I don't have any idea how to solve this problem because I have this problem also with the Sleep API, too.

HELP!

Receiver.kt

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
import com.example.hendi.util.ActivityTransitionUtil
import com.google.android.gms.location.ActivityTransitionResult

class ActivityTransitionReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        Log.d("MyShedCheck", "onReceive()")
        if (ActivityTransitionResult.hasResult(intent)) {
            val result = ActivityTransitionResult.extractResult(intent)
            result?.let {
                result.transitionEvents.forEach { event ->
                    Log.d("RECEIVER", "Activity Detected:" +
                            "\ncontext: ${context}" +
                            "\nintent:${intent}" +
                            "\ntype: ${ActivityTransitionUtil.toActivityString(event.activityType)}"
                    )
                }
            }
        }
    }
}

MainActivity.kt

import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.annotation.RequiresApi
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.preference.PreferenceManager
import com.example.hendi.receiver.ActivityTransitionReceiver
import com.example.hendi.ui.theme.HendiTheme
import com.example.hendi.util.ActivityTransitionUtil
import com.example.hendi.util.Constants
import com.example.hendi.util.PermissionState
import com.google.android.gms.location.ActivityRecognition
import com.google.android.gms.location.ActivityRecognitionClient

class MainActivity : ComponentActivity() {

    lateinit var client: ActivityRecognitionClient
    lateinit var storage: SharedPreferences

    companion object {
        const val TAG = "MyShedCheck"
    }

    @RequiresApi(Build.VERSION_CODES.S)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        client = ActivityRecognition.getClient(this)
        storage = PreferenceManager.getDefaultSharedPreferences(this)

        var isChecked = false
        val permissionState = PermissionState(this) {
            if (it.permissionGranted) {
                isChecked = true
                requestForUpdates()
            } else {
                isChecked = false
                it.requestPermission()
            }
        }



        setContent {
            HendiTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    ToggleAction(permissionState = permissionState,
                        request = { requestForUpdates() },
                        remove = { deregisterForUpdates() })
                }
            }
        }
    }


    @RequiresApi(Build.VERSION_CODES.S)
    @SuppressLint("MissingPermission")
    fun requestForUpdates() {
        client
            .requestActivityTransitionUpdates(
                ActivityTransitionUtil.getActivityTransitionRequest(),
                getPendingIntent()
            )
            .addOnSuccessListener {
                Log.d(TAG, "Successful registration")
            }
            .addOnFailureListener {
                Log.d(TAG,"Unsuccessful registration:$it")
            }
    }

    @SuppressLint("MissingPermission")
    @RequiresApi(Build.VERSION_CODES.S)
    fun deregisterForUpdates() {
        client
            .removeActivityTransitionUpdates(getPendingIntent())
            .addOnSuccessListener {
                Log.d(TAG, "Successful deregistration")
            }
            .addOnFailureListener {
                Log.d(TAG,"Unsuccessful deregistration:$it")
            }
    }

    @RequiresApi(Build.VERSION_CODES.S)
    private fun getPendingIntent() :PendingIntent {
        val intent = Intent(this, ActivityTransitionReceiver::class.java)
        return PendingIntent.getBroadcast(
            this,
            122,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
        )
    }

}

@Composable
fun ToggleAction(permissionState: PermissionState, request: () -> Unit, remove: () -> Unit) {

    Log.d("MyShedCheck", "Permission: ${permissionState.permissionGranted}")
    var isChecked by remember { mutableStateOf(
        if (permissionState.permissionGranted) {
            true
        } else {
            permissionState.requestPermission()
            false
        }
    )
    }
    Switch(checked = isChecked,
        onCheckedChange = {
            isChecked = it

            if (it) {
                request()
            } else {
                remove()
            }
        }
    )
}

AndroidManifast.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- Required for 28 and below. -->
    <uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
    <!-- Required for 29+. -->
    <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />

    <application
        android:name=".App"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.Tracker"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:theme="@style/Theme.Tracker">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <receiver
            android:name=".receiver.ActivityTransitionReceiver"
            android:exported="false"
            android:permission="com.google.android.gms.permission.ACTIVITY_RECOGNITION">
            <intent-filter>
                <action android:name="action.TRANSITIONS_DATA" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

ActivityTransitionUtil.kt

import android.content.Context
import com.google.android.gms.location.ActivityTransition
import com.google.android.gms.location.ActivityTransitionRequest
import com.google.android.gms.location.DetectedActivity

object ActivityTransitionUtil {
    private fun getTransitions(): MutableList<ActivityTransition> {
        val transitions = mutableListOf<ActivityTransition>()

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

        transitions.add(
            ActivityTransition.Builder()
                .setActivityType(DetectedActivity.STILL)
                .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
                .build()
        )
        transitions.add(
            ActivityTransition.Builder()
                .setActivityType(DetectedActivity.STILL)
                .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
                .build()
        )

        return transitions
    }

    fun getActivityTransitionRequest() = ActivityTransitionRequest(getTransitions())

    fun hasActivityTransitionPermissions(context: Context): Boolean =
        context.hasPermission()

    fun toActivityString(activity: Int): String {
        return when (activity) {
            DetectedActivity.STILL -> "STILL"
            DetectedActivity.WALKING -> "WAKING"
            else -> "UNKNOWN"
        }
    }

    fun toTransitionType(transitionType: Int): String {
        return when (transitionType) {
            ActivityTransition.ACTIVITY_TRANSITION_ENTER -> "ENTER"
            ActivityTransition.ACTIVITY_TRANSITION_EXIT -> "EXIT"
            else -> "UNKNOWN"
        }
    }
}

App.kt

import android.app.Application

class App : Application() {
    override fun onCreate() {
        super.onCreate()
    }
}
0

There are 0 best solutions below