2

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?

  • I was just recently successfully using the API for months with no issue, and now I'm seeing this same problem. Trying to figure out what it is I updated to cause the problem! – ConcernedHobbit Jan 05 '22 at 17:30

2 Answers2

2

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)
Rafael
  • 6,091
  • 5
  • 54
  • 79
ConcernedHobbit
  • 764
  • 1
  • 8
  • 17
0

After the google play service is updated, the sleep API cannot receive sleep events and cannot obtain data