JobIntentService - onHandleWork is not always called?
Asked Answered
O

1

1

I have home screen widget, which has a simple AppWidgetProvider and JobIntentService, where I do all the work.

Problem is - it works kind of randomly. Sometimes it does, sometimes it doesnt - weirdest thing is, I can see in the log, that on each widget update enqueueWork method of JobIntentService is ALWAYS called, but onHandleWork method only sometimes.

(I have found there is strong, though not 100% correlancy with battery optimization. If I turn of "Manage apps automatically", then it 99% works reliably. If it is turned on, its like flipping a coin. Sometimes it does, sometimes it doesnt. Best to ilustrate behavior would be this short simple video

This is my code (Widget provider):

public class MyWidgetProvider extends AppWidgetProvider {
    
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        Log.v("aaa", "onUpdate");
        // super.onUpdate(context, appWidgetManager, appWidgetIds);

        // update in my own Service (to avoid ANR)
        Intent intent = new Intent(context, MyJobIntentService.class);
        intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        MyJobIntentService.enqueueWork(context, intent);
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.v("aaa", "onReceive");

        super.onReceive(context, intent);
    }
}

And this is my service (JobIntentService) where I do all work:

public class MyJobIntentService extends JobIntentService {

    public static final int JOB_ID = 1;

    public static void enqueueWork(Context context, Intent work) {
        Log.v("aaa", "enqueueWork: ");
        enqueueWork(context, MyJobIntentService .class, JOB_ID, work);
    }

    @Override
    protected void onHandleWork(Intent intent) {
        Log.v("aaa", "onHandleWork: ");
    }
    
}
Oxide answered 27/7, 2020 at 8:43 Comment(4)
enqueueWork(context, UpdateServiceCalendar.class, JOB_ID, work); it should be enqueueWork(context, MyJobIntentService.class, JOB_ID, work);?Cilice
Obviously that was just a typo, when i was renaming classes. Sorry for that, I corrected itOxide
I have exactly same setup and similar issues... :/Flit
classic Google - they are BREAKING their own android standards, their own documentation, it is clearly not working as it should. Its unbelievable how lame is that company, this is probably like 100th bug I discovered in their APIs. And dont let me start on manufacturers, this website sums it up very well - long story short, they also break android standards: dontkillmyapp.com/Oxide
N
2

This is the same thing that is happening to me. What I've found out is that in the android documentation, it says:

When running as a pre-O service, the act of enqueueing work will generally start the service immediately, regardless of whether the device is dozing or in other conditions. When running as a Job, it will be subject to standard JobScheduler policies for a Job with a JobInfo.Builder.setOverrideDeadline(long) of 0: the job will not run while the device is dozing, it may get delayed more than a service if the device is under strong memory pressure with lots of demand to run jobs.

This means in Android O and above devices, it is not guaranteed that the jobIntentService starts immediately, but start with the delay depending on the device's condition. But, some phone manufacturers are deliberately canceling the job for better battery life (Like OnePlus). So the job is never called.

The workaround that I used is to create a LOW_IMPORTANCE foreground service and call it using:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    context.startForegroundService(startIntent);
} else {
    context.startService(startIntent);
}

But the drawback is that the notification is shown for a small duration till the work is complete.

Maybe google should put some restrictions on the device manufacturers on how to manage the background apps.

Noni answered 31/8, 2020 at 7:34 Comment(5)
Well the problem is documentation is very vague about it (and also, incorrect). It basically says "It is not guaranteed when jobIntentService starts" but in reality, it sometimes never starts - and they forgot to mention it. Which is btw a serious BUG if background service randomly just stops running out of the blue, even if you excluded it from battery optimizations...Oxide
but thanks for tip with foreground service. I will try that solution - does it works RELIABLY ( = is it deterministic)?Oxide
Yeah, I agree. What I have seen in my OnePlus phone and other devices is that sometimes, the job is enqueuing, but not handled, but as soon as I launch the app, all the previously enqueued works are handled immediately.Noni
Yes, foreground service works reliably but the notification is shown for a small duration.Noni
Yes, thats how it behaves on my device too. Sometimes, totally randomly, it just stops being handled (enqueuing still works) and it does not work for minutes or even hours sometimes - or until I launch the app. Then all previously enqueued works are handled again. Its totally undeterministic and I believe wrong behavior. Anyway thanks for your help...Oxide

© 2022 - 2024 — McMap. All rights reserved.