Unable to detect User activity transition , using broadcast receivers
Asked Answered
F

2

8

I have used the Activity Transition API launched by Google recently to detect when a User gets in and out of the vehicle. Below is the code I am using to achieve the same.

 val intent = Intent(context, ActivityTransitionReceiver::class.java)
    val pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT)

    transitions.apply {
        add(ActivityTransition.Builder()
                .setActivityType(DetectedActivity.IN_VEHICLE)
                .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
                .build())

        add(ActivityTransition.Builder()
                .setActivityType(DetectedActivity.IN_VEHICLE)
                .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
                .build())
    }

    var transitionRequest = ActivityTransitionRequest(transitions)

    // myPendingIntent is the instance of PendingIntent where the app receives callbacks.
    val task = ActivityRecognition.getClient(context).requestActivityTransitionUpdates(transitionRequest, pendingIntent)

    task.addOnSuccessListener {
        // Handle success
        context.toast("Task added successfully")
    }

    task.addOnFailureListener {
        // Handle error
        context.toast("Error adding task")
    }

The app works fine and receives the broadcast when it is not removed from the recent apps tab. But when the app is removed from the recent apps tab or killed by the system, I am unable to receive the broadcasts. I don't know what I am doing wrong. Is there any other way I can achieve the same?

I considered using foreground service so that the app doesn't get killed but then thought that showing a permanent notification just to detect User Activity Transition is not a good idea.

Edit: I have seen that some apps ask for special permission like "Ignore battery Optimisations" and when this permission is given, that app always seems to work and keeps sending the notification.

Flesh answered 30/3, 2018 at 14:10 Comment(4)
Are you deregistering in onDestroy? Have you tested on multiple devices? There is a need to be a 'protected app' for some https://mcmap.net/q/131509/-ontaskremoved-not-getting-called-in-huawei-and-xiaomi-devicesPrevot
Where did you using this code. In a Service or Activity?Gaughan
replace your pending intent stuff with this PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 4, intent, PendingIntent.FLAG_NO_CREATE); pendingIntent = PendingIntent.getBroadcast(this, 4, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);Sadye
#41278171 take a look at my question.. this could help youVishnu
S
0

You should do this in a background service and in manifest file set "stopWithTask" flag to false.

That way when user removes your app from recent apps, your service will not be killed.

https://developer.android.com/reference/android/content/pm/ServiceInfo.html

When user removes your task from recent apps, callback in service will be called: onTaskRemoved https://developer.android.com/reference/android/app/Service.html#onTaskRemoved(android.content.Intent)

You can do some cleanup or whatever you want in this callback

Lastly, start your service as STICKY. That way if user kills your app, the service restarts and you can resume doing your work. (this is not guarantee to happen, but it is a decent compromise)

I hope it helps

Slattery answered 5/4, 2018 at 22:11 Comment(0)
L
0

According to documentation you shouldn't expect an implicit receiver to be called if your target API is 26 or higher:

Note: If your app targets API level 26 or higher, you cannot use the manifest to declare a receiver for implicit broadcasts (broadcasts that do not target your app specifically), except for a few implicit broadcasts that are exempted from that restriction. In most cases, you can use scheduled jobs instead.

The only good solution seems to be a foreground service. You can keep it in the background all the time and only move it to foreground when app is closed using Service.onTaskRemoved.

Latonya answered 8/4, 2018 at 8:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.