Search code examples
androidandroid-widgetandroid-serviceandroid-appwidgetandroid-8.1-oreo

Service not starting on Oreo in app widget using PendingIntent


I'm using Android app widgets. I'm creating a PendingIntent object and use it in the method RemoteViews#setOnClickPendingIntent(). This is the pending intent:

// The below code is called in the onUpdate(Context, AppWidgetManager, int[]) method of the AppWidgetProvider class.

// Explicit intent
Intent intent = new Intent(context, MyService.class);
intent.setAction(MY_ACTION);
intent.putExtra(EXTRA_KEY, VALUE);

// Create the pending intent
PendingIntent pendingIntent = PendingIntent.getService(context, appWidgetId, intent, 0);

// 'views' is a RemoteViews object provided by onUpdate in the AppWidgetProvider class.
views.setOnClickPendingIntent(R.id.root_layout, pendingIntent);

The above code works as expected before Android Oreo. However, in Android Oreo it no longer starts the service if the app is swiped away from recents. (no longer active). Aren't PendingIntents excluded in Oreo's background execution limits?

For testing purposes I replaced getService with getForegroundService but the Service is still not started. Both methods show the below message in the log:

W/ActivityManager: Background start not allowed: service Intent { act=com.example.myapp.MY_ACTION flg=0x10000000 cmp=com.example.myapp/com.example.myapp.MyService bnds=[607,716][833,942] (has extras) } to com.example.myapp/com.example.myapp.MyService from pid=-1 uid=10105 pkg=com.example.myapp

Why is the Service not started, even when using getForegroundService? I tested this on a Nexus 6P running Android 8.1.0.


Solution

  • As you note, an app widget does not count for the PendingIntent background whitelist. I do not know why — it would seem to be about on par with a PendingIntent started by a Notification. Perhaps it's an issue that the Notification is a system thing, whereas the app widget is a home screen thing. Regardless, you could:

    • Use getForegroundService(), as you have, or

    • Try getBroadcast() with an explicit Intent, and with the BroadcastReceiver starting a JobIntentService, if you do not want to raise a Notification (as a foreground service requires)

    Based on your symptoms, you appear to have tripped over what I would consider to be a bug: there should be a way to switch from getService() to getForegroundService() without having to reboot. :-) I'll try to run some experiments and will file an issue if I can reproduce the problem.