JobIntentService - onHandleWork 并不总是被调用?

Posted

技术标签:

【中文标题】JobIntentService - onHandleWork 并不总是被调用?【英文标题】:JobIntentService - onHandleWork is not always called? 【发布时间】:2020-11-16 13:37:44 【问题描述】:

我有一个主屏幕小部件,它有一个简单的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: ");
    
    

【问题讨论】:

enqueueWork(context, UpdateServiceCalendar.class, JOB_ID, work);它应该是 enqueueWork(context, MyJobIntentService.class, JOB_ID, work);? 显然这只是一个错字,当我重命名课程时。抱歉,我更正了它 我有完全相同的设置和类似的问题...:/ 经典的谷歌——他们打破了自己的安卓标准,他们自己的文档,显然不能正常工作。令人难以置信的是,这家公司有多蹩脚,这可能是我在他们的 API 中发现的第 100 个错误。不要让我从制造商开始,这个网站总结得很好 - 长话短说,他们也打破了安卓标准:dontkillmyapp.com/ 【参考方案1】:

这也是发生在我身上的事情。我发现在 android 文档中,它说:

当作为 pre-O 服务运行时,排队工作的行为将 一般会立即启动服务,不管是否 设备正在打瞌睡或处于其他状态。作为作业运行时,它 将受标准 JobScheduler 政策的约束 JobInfo.Builder.setOverrideDeadline(long) of 0:作业不会运行 当设备打瞌睡时,它可能会比服务延迟更多,如果 该设备承受着强大的内存压力,需要大量运行 工作。

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

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

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

但缺点是通知会显示一小段时间,直到工作完成。

也许谷歌应该对设备制造商如何管理后台应用程序进行一些限制。

【讨论】:

好吧,问题是文档对此非常模糊(而且也不正确)。它基本上说“不能保证 jobIntentService 何时启动”,但实际上,它有时永远不会启动 - 他们忘了提及它。如果后台服务随机停止运行,这是一个严重的 BUG,即使您将其排除在电池优化之外...... 但感谢前台服务的提示。我将尝试该解决方案 - 它是否可靠地工作(= 它是确定性的)? 是的,我同意。我在我的 OnePlus 手机和其他设备上看到的是,有时,工作正在排队,但没有处理,但只要我启动应用程序,所有以前排队的工作都会立即处理。 是的,前台服务工作可靠,但通知显示时间很短。 是的,它在我的设备上也是如此。有时,完全随机地,它只是停止处理(排队仍然有效),有时几分钟甚至几个小时都不起作用 - 或者直到我启动应用程序。然后再次处理所有先前排队的工作。它完全不确定,我相信错误的行为。无论如何感谢您的帮助...

以上是关于JobIntentService - onHandleWork 并不总是被调用?的主要内容,如果未能解决你的问题,请参考以下文章

JobIntentService 的 onDestroy 被调用后会发生啥?

JobIntentService 不调用 OnHandleWork

JobIntentService - onHandleWork 并不总是被调用?

JobIntentService 不会在 Android 8.0 上立即启动

Proguard:JobIntentService IllegalArgumentException启用模糊处理

Kotlin:如何从 Fragment 调用 JobIntentService?