自定义 JobIntentService 的 onHandleWork 方法未被调用

37

我最近更新了一款应用程序,使用JobIntentService处理来自推送的通知,而不是常规的IntentService,因为这似乎是在 Lollipop设备之前和之后正确处理此问题的方法。我正在这样排队工作:

enqueueWork(context, MyJobServiceExtension.class, JOB_ID, work);

这是清单声明:

<service android:name="com.example.MyJobServiceExtension"
            android:permission="android.permission.BIND_JOB_SERVICE"
            android:exported="true"
            tools:node="replace">

我从来没有在onHandleWork中看到任何回调或任何错误日志在我的logcat中。 有成功集成它的人可以帮忙吗?

更新1

我在一个API级别为21的设备上测试了这个,它可以工作...但似乎在我的Android Oreo Pixel XL设备上没有被调用...有什么线索吗?

更新2

另外,我似乎看到IntentService的onCreate被调用,但没有其他生命周期方法(包括onHandleWork)。还有人遇到过这种情况吗?


1
我有相同的症状,但还没有答案。在API级别23设备上运行良好,在API级别26 Nexus 5X上不行。你的“work” Intent是如何构建的? - Jule
@Jule 目前我的工作意图是使用自定义操作加上一些额外的内容来构建它,就这样。 - Eshaan
1
我遇到了相同的问题,实际上我收到了这个消息:“JobServiceContext: 在尝试绑定时超时...” - agirardello
12个回答

71

在从IntentService升级到JobIntentService后,我遇到了相同的问题。请确保从旧实现中删除此方法:

@Override
public IBinder onBind(Intent intent) {
    return null;
}

对我来说,这解决了问题,现在它可以在Oreo之前和之后都正常运作。


哇,非常感谢!这样就解决了。我希望安卓在这种情况下能够给我一些错误提示 =_= 我实际上从来没有注意到 ServiceContext 在尝试绑定日志时超时。 - Eshaan
好的,它正在工作,但我现在看到当应用程序打开或在最近使用列表中时,服务运行良好,但是当从最近使用列表中删除时,服务停止了,请在这里帮助我。 - Sunil Chaudhary
还必须删除onCreate和onStart的覆盖。 - syonip

10
我曾经遇到过同样的问题(在一台旧设备上可以正常工作,在一个 O 设备上没有任何反应)。今天我重新尝试使用昨天完全相同的代码,现在它能够正常运行了——唯一的区别是在两次尝试之间我重启了设备。
我的当前理论是,我的初始设置未能成功;而我的当前设置已经成功了,仅仅重新部署新代码并不能消除 JobScheduler 中的错误状态;必须进行设备重启或卸载/重新安装包来清除错误状态。
现在的工作设置已从原来的 IntentService 迁移而来:
<service
    android:name=".MyJobIntentService"
    android:exported="false"
    android:permission="android.permission.BIND_JOB_SERVICE"/>

并且开始于

Intent intent = new Intent(); 
intent.putExtra(EXTRA_NAME, extraValue);
JobIntentService.enqueueWork(context, MyJobIntentService.class, FIXED_JOB_ID, intent);

请注意,意图不是显式意图(即ComponentName未设置)。

startForegroundService 替换为 JobIntentService.enqueueWork 在 API 26 上可以让它正常工作。 - Kris B
确保 android:exported="true"。我刚刚测试过了。 - Ken Zira
@KenZira 为什么必须将“exported”设置为“true”? - Karan Harsh Wardhan
@KenZira能给我发个链接吗? - Karan Harsh Wardhan
好的,它正在工作,但我现在看到当应用程序打开或在最近使用列表中时,服务运行良好,但是当从最近使用列表中删除时,服务停止了,请在这里帮助我。 - Sunil Chaudhary
当您手动从最近使用列表中滑动应用程序时,它(通常)会被终止 - 请参见例如 https://medium.com/@er.abhishek.luthra/what-exactly-happens-to-running-services-when-you-swipe-an-android-app-from-recent-app-list-d343ca03a2a 上的一些信息,了解服务的工作原理。 - Jule

3

这是我成功的方法,

按照@agirardello的建议,移除 IBind 重写部分。

并添加以下内容:

@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    return super.onStartCommand(intent, flags, startId);
}

我不知道为什么这个有效。


3
如果您在JobIntentService中覆盖了onCreate方法,它将阻止调用onHandleWork方法。
我将我的Service转换为JobIntentService,只有在删除onCreate方法后它才能正常工作。

你能给出任何原因吗? - Karan Harsh Wardhan
在我移除了onCreate并添加了exported=true之后,它确实在Android 4.4(19)上运行成功了。 - Karan Harsh Wardhan
1
有过同样的问题。这个答案帮助我找到了解决方案。我非常认为您没有在onCreate()方法中调用super.onCreate()。如果您从Service切换到JobIntentService,您必须确保执行对父类onCreate方法的调用。 - Nico Feulner

2
我在使用JobScheduler时遇到了问题,尝试将JobIntentService排队,但JobScheduler自带的enqueueWork()方法与JobIntentService不兼容,服务会启动但onHandleWork()方法不会被调用。使用JobIntentService上的静态enqueueWork()方法后,问题得到解决。例如:
MyJobIntentService.enqueueWork(context, ...)

从Android的javadoc中阅读这些内容是不明显的。


1
我在从Service迁移到JobIntentService后,遇到了一个类似的问题,即第二次不调用onHandleWork。日志显示enqueueWork被调用,但只有第一次执行onHandleWork并且似乎被卡住了。
经过更多的挖掘和记录,我发现“卡住”的情况是由于即使在onHandleWork中的所有操作都已完成,仍然存在JobIntentService#onDestroy
结果发现,罪魁祸首是将该服务的bindService调用绑定到活动生命周期,这会阻止处理第一个作业并导致服务“卡住”,之后再调用enqueueWork会导致服务永远不会运行任何后续的onHandleWork
因此,以下是一系列错误事件日志,其中JobIntentService在第一次调用后似乎被卡住,无法再触发onHandleWork
enqueueWork -> first call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
enqueueWork -> second call
enqueueWork -> third call

在删除bindService调用后,这里是使用JobIntentService正确运行的事件日志:

enqueueWork -> first call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
onDestroy (service is destroyed after the job is finished)
enqueueWork -> second call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
onDestroy
enqueueWork -> third call
onHandleWork started (log in the first line)
onHandleWork finished (log in the last line)
onDestroy

希望这对某人有所帮助。

这是我的情况,但从你的帖子中并不清楚你是如何解决问题的。你能否请澄清一下? - Samik R
检查您的代码中是否有bindService调用,并尝试将其删除以查看是否解决了问题@SamikR - git pull origin
这也发生在我身上,但我从未在代码中调用 bindService - JCarlosR

0

我终于找到了那个问题的解决方案,哈哈

如果你重写了 "onBind" 方法并使用 "enqueueWork" 方法调用工作,则需要返回绑定到执行此工作的引擎:

@Override @Nullable
    public IBinder onBind(@NonNull Intent intent) {
        [... Do What You Want ... ]
        return super.onBind(intent);
    }

因此,返回“super.onBind”方法的IBinder,因此您必须使用它来绑定到JobIntentService。

如果您想绑定并返回另一个binder,则可以这样做:

@Override @Nullable
    public IBinder onBind(@NonNull Intent intent) {
        IBinder binder = initSynchronizer();
        new Thread(
                () -> onHandleWork(intent)
            ).start();
        return binder;
    }

通过在另一个线程中启动"onHandleWork",您可以使用以下方式绑定服务并返回Binder:"bindService(....., JobIntentService.BIND_AUTO_CREATE);"。无论如何,当您从服务中解除绑定时,服务将被杀死,如果它仍在运行,则无法再次绑定到它,因为执行"onHandleWork"的线程仍在运行... 因此,我建议您仅在必须执行需要与活动通信直到其保持活动状态并且需要在活动被杀死后继续工作(无法重新绑定jobService,但只能启动新的jobService)的任务时才使用此版本。为了不在解除绑定后杀死服务,您需要在"onDestroy"中以"foreground"方式启动服务,并在其中使用"stopForeground"。这样,您的服务仍然会存在,只是用于处理"onHandleWork"方法的线程。希望Google能够快速解决这个问题,哈哈,我已经将所有旧的"Service"和"IntentService"转换为新的"jobs",但它们的效果比以前要差得多!好了,祝你编码愉快;)

我也在使用JobIntentService,并希望使用onBind将引用传递到该服务中。似乎这并不是为此而构建的,但是onBind允许执行该方法并传递引用。但现在onHandleWork根本没有被调用。这个类可能需要更多的细化来限制使用情况。 - Sergio
@SergioCouture 你好(如果你是意大利人,也可以说ciao)!我认为JobIntentService类有问题,因为它调用了"OnBind",但之后从未调用"onHandleWork"。解决这个问题有两种方法:你可以使用另一个类似于"Service"的类,其中绑定正常工作,或者你可以使用我上面写的方法手动启动"onHandleWork"。我知道这很糟糕,但我没有找到其他解决方案。个人而言,在我的后台服务中搜索BLE标签时,我使用了"Service"类来正确处理绑定。希望这能帮到你!祝你有愉快的一天和编程 :D - Z3R0

0

虽然听起来很有趣,但我曾经遇到过类似的问题,因为在enqueueWork()中我没有将类的名称更改为它自己的名称,而是从我的一个类中复制了代码。 更新后,它开始正常工作。


0

我认为我遇到了这样的问题,因为我试图在onHandleWork()内部弹出一些文本,但实际上问题是错误的。我应该使用一个Handler。如果在onHandleWork()内部使用例如AsyncTask子类来在另一个线程上执行,这可能是一个非常糟糕的想法。


0

对我来说,在enqueueWork之后仍然启动服务,因此导致出现错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接