JobIntentService - onHandleWork 并不总是被调用?

JobIntentService - onHandleWork is not always called?

我有主屏幕小部件,它有一个简单的 AppWidgetProviderJobIntentService,我可以在其中完成所有工作。

问题是 - 它的工作有点随机。有时它会,有时它不会 - 最奇怪的是,我可以在日志中看到,在每个小部件上更新 JobIntentServiceenqueueWork 方法总是被调用,但 onHandleWork 方法只是有时被调用。

(我发现与电池优化有很强的相关性,但不是 100%。如果我打开“自动管理应用程序”,那么它 99% 可靠地工作。如果打开,就像掷硬币一样. 有时会,有时不会。Best to ilustrate behavior would be this short simple video

这是我的代码(小部件提供程序):

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);
    }
}

这是我的服务 (JobIntentService),我负责所有工作:

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: ");
    }
    
}

这就是发生在我身上的同一件事。我发现在 android 文档中,它说:

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.

这意味着在AndroidO及以上设备中,不保证jobIntentService立即启动,而是根据设备情况延迟启动。但是,一些 phone 制造商故意取消这项工作以延长电池寿命(例如 OnePlus)。所以这个工作永远不会被调用。

我使用的解决方法是创建一个 LOW_IMPORTANCE 前台服务并使用以下方式调用它:

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

但缺点是通知显示时间很短,直到工作完成。

也许 google 应该对设备制造商如何管理后台应用程序施加一些限制。