Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Sleep API - not getting data

I use the Sleep API in my Kotlin Android app. To get sleep data, I am following these steps:

  • Getting the android.permission.ACTIVITY_RECOGNITION permission from the user
  • Successfully registering to both SleepSegmentEvent and SleepClassifyEvent
  • Listening to events using a Broadcast Receiver

I'm periodically receiving events (testing in an API 30 physical device), but they do not contain SleepSegment or SleepClassify data at all. In fact, incoming intents are completely empty. To illustrate this:

class SleepAPIReceiver: BroadcastReceiver() {

    override fun onReceive(context: Context?, intent: Intent?) {
        if (SleepSegmentEvent.hasEvents(intent)) {
            ...
        } else if (SleepClassifyEvent.hasEvents(intent)) {
            ...
        } else {
            // THIS ELSE CLAUSE IS TRIGGERED
        }
    }

The last "else" is triggered, which is weird considering no events should be received if no data is available (or so I thought). Official examples do not even consider receiving intents with neither SleepSegment nor SleepClassify events.

What could be the source of this problem?

like image 923
Sergi Domingo Avatar asked Sep 26 '26 01:09

Sergi Domingo


1 Answers

Finally found the bug in my code. It turns out the PendingIntent for your receiver needs to be mutable! Because I had updated my compileSdkVersion to 31 (Android 12+), having a mutability flag became required. Before, when it wasn't required (and was working), this was my PendingIntent:

class SleepReceiver: BroadcastReceiver() {

    companion object {
        fun createPendingIntent(context: Context): PendingIntent {
            val intent = Intent(context, SleepReceiver::class.java)
            return PendingIntent.getBroadcast(
                context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT)
        }
    }

   ...
}

Here is my working code with the new mutable flag:

var flags = PendingIntent.FLAG_CANCEL_CURRENT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    flags = flags or PendingIntent.FLAG_MUTABLE // <-- FLAG_IMMUTABLE breaks the code!
}

val intent = Intent(context, SleepReceiver::class.java)
return PendingIntent.getBroadcast(context, 0, intent, flags)
like image 183
ConcernedHobbit Avatar answered Sep 27 '26 15:09

ConcernedHobbit