0

I'm working on a VoIP app that receives high priority notifications from Twilio when an incoming call happens.

Sometimes, when this happens I'm getting the following exception, which is a horrible time to crash as it forces the call to voicemail on the other end.

Fatal Exception: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.incomingCall cmp=com./.service.VoipService (has extras) }: app is in background uid UidRecord{368a9a8 u0a186 CEM idle procs:1 seq(0,0,0)}

The exceptions are all happening on Samsung Galaxy S7's running Android 8.0, which a lot of our users use.

I get the remote message in onMessageReceived, parse some data out of it, and then call Voice.handleMessage(this, data, twilioMessageListener) which does a tiny amount of Twilio logic, and then triggers the callback

private var twilioMessageListener: MessageListener = object : MessageListener {
        override fun onCallInvite(callInvite: CallInvite) {
            val intent = Intent(this@FcmListenerService, VoipService::class.java)
            with(intent) {
                action = Constants.ACTION.INCOMING_CALL
                putExtra(Constants.EXTRA.INCOMING_CALL_MESSAGE, callInvite)
                putExtra(Constants.EXTRA.INCOMING_CALL_MESSAGE_STATE, callInvite.state)
            }
            startService(intent)
        }
    }

And then crashes on start service.

According to the documentation

Under certain circumstances, a background app is placed on a temporary whitelist for several minutes. While an app is on the whitelist, it can launch services without limitation, and its background services are permitted to run. An app is placed on the whitelist when it handles a task that's visible to the user, such as:

Handling a high-priority Firebase Cloud Messaging (FCM) message.

So I'm not sure what I'm doing wrong, or what I can do to resolve this?

It's a high priority FCM and I'm still getting the error?

Is this a bug in the Samsung S7's OS? Is there something I can do to work around it? I've tried putting my devices into doze, but I can't replicate it.

Ben987654
  • 3,280
  • 4
  • 27
  • 50

1 Answers1

0

You can find in Google's documentation that IllegalState exception is thrown when startService is called from a background and this is your case:

If the application is in a state where the service can not be started (such as not in the foreground in a state when services are allowed)

https://developer.android.com/reference/android/content/Context.html#startService(android.content.Intent)

That's why you should use startForegroundService instead of startService

Similar to startService(android.content.Intent), but with an implicit promise that the Service will call startForeground(int, android.app.Notification) once it begins running

However, startForegroundService has it own shortcomings and I think, it's a platform bug. So my advice is not to use either as I've explained here:

Context.startForegroundService() did not then call Service.startForeground()

Oleg Gryb
  • 5,122
  • 1
  • 28
  • 40
  • Please read my whole post. I am doing this when I have an incoming high priority notification and I should be whitelisted. – Ben987654 Oct 11 '19 at 00:24
  • I am in a white listed situation. This should not be happening. – Ben987654 Oct 11 '19 at 00:28
  • Starting with android O (8) there is no any guarantee that your app that receives notifications will stay in foreground long enough, that's why nobody uses startService in O and higher versions. startFotegroundService should be used instead, but that one has problems too. – Oleg Gryb Oct 11 '19 at 00:36
  • So you're saying the documentation is flat out wrong? "Under certain circumstances, a background app is placed on a temporary whitelist for several minutes. " and this is one of those conditions. This literally all takes place in a matter of milliseconds, nowhere near minutes. – Ben987654 Oct 11 '19 at 00:37
  • Please provide a source of your quote and I'll dig out info about O in regard of startForegroundService. – Oleg Gryb Oct 11 '19 at 00:39
  • It's fully quoted in my post and comes from here https://developer.android.com/about/versions/oreo/background.html – Ben987654 Oct 11 '19 at 00:40
  • I'll answer later. Need to run now. – Oleg Gryb Oct 11 '19 at 00:41
  • I would be concerned about that "visible to a user" part. Does it mean that app's UI should be active? Anyway, can you try replacing startService with startForegroundService and tell us if you still see crashes. The crashes with startForegroundService are rare (1 per 1K users per month in my case), so we'll see the difference right away. Later ... – Oleg Gryb Oct 11 '19 at 00:52
  • I can try, but these S7 crashes are uncommon enough to begin with, so I would probably catch the exception to not impact everyone else and then try again with a foreground. In this scenario the service would next be triggering a notification with a full screen pending intent if it was screen off, or a notification about the call if it was still on. – Ben987654 Oct 11 '19 at 01:16
  • Another thing: you use this@FcmListenerService for the parent context. As I understand, that's a service that doesn't have a UI. If my understanding is correct try changing it to your app's activity that does have UI. Probably that will make the described whitelisting working. – Oleg Gryb Oct 11 '19 at 02:16
  • I'm launching the service from the FCM listener (class FcmListenerService : FirebaseMessagingService()) where the push notification comes in. There is no activity open yet when this happens. The service is what will open the activity if the screen is off (full screen pending notification) or simply show a notification on the screen once it's collected all the necessary data if it's already open. – Ben987654 Oct 11 '19 at 05:01
  • That's probably why whitelisting doesn't work. It was probably meant for apps with UI and that's why they have that "visible to a user" condition. Just a guess. – Oleg Gryb Oct 11 '19 at 05:05
  • I still feel like Samsung has done something to break it... I'd be seeing crashes on other devices if I was just completely wrong on how this was set up, but if Samsung did bork it, then that foreground might be the only way short of rewriting it all. – Ben987654 Oct 11 '19 at 05:10