Service not starting on Oreo in app widget using PendingIntent

前端 未结 3 528
栀梦
栀梦 2020-12-31 02:37

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

3条回答
  •  既然无缘
    2020-12-31 03:08

    You can no longer start a service in background in 8.0, but you can use JobScheduler to achieve similar results. There is also a JobIntentService helper class that allows you to switch to JobScheduler from service without much refatoring. And you cannot use PendingIntent pointing to a service, but you can use one pointing to an Activity or BroadcastReceiver.

    If you had a working widget pre 8.0, and now you need to make it work on android 8.0, just perform this simple steps:

    1. Change your IntentService class to JobIntentService
    2. Rename service onHandleIntent method to onHandleWork (same parameters)
    3. Add BIND_JOB_SERVICE permission to your service in the manifest:
        
        
    
    1. To start this service, you must no longer use context.startService. Instead use enqueueWork static method (where JOB_ID is just an unique integer constant, must be the same value for all work enqueued for the same class):
        enqueueWork(context, MyWidgetService.class, JOB_ID, intent);
    
    1. For clicks, replace your pendingIntent that was pointing to service with a pendingIntent that points to a BroadcastReceiver. Since your subclass of AppWidgetProvider is a BroadcastReceiver itself, you might as well use it:
        Intent myIntent = new Intent(context, MyAppWidgetProvider.class);
        myIntent .setAction("SOME_UNIQUE_ACTION");
        pendingIntent = PendingIntent.getBroadcast(context, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    
    1. In onReceive start the service using enqueueWork (If your PendingIntent was starting the activity, just leave it be - it'll work just fine on android 8.0+):
        @Override
        public void onReceive(Context context, Intent intent) {
            super.onReceive(context, intent);
            if (intent.getAction().equals("SOME_UNIQUE_ACTION")) {
                MyWidgetService.enqueueWork(.....);
            }
        }
    
    1. To ensure that the widget will work on old devices, make sure you have WAKE_LOCK permission in your manifest (used by JobIntentService on old devices).

    That's it. This widget will now work properly on both new and old devices. The only real difference will be that if your 8.0 device is in doze mode it may not update widget all that often, but that shouldn't be a problem because if it is dozing, that means that user can't see your widget right now anyways.

提交回复
热议问题