远程服务异常:Context.startForegroundService未调用Service.startForeground。

8

我从设备监视器中得到以下异常输出:

//FATAL EXCEPTION: main
//Process: com.xxx.yyy, PID: 11584
//android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
//    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1881)
//    at android.os.Handler.dispatchMessage(Handler.java:105)
//    at android.os.Looper.loop(Looper.java:164)
//    at android.app.ActivityThread.main(ActivityThread.java:6944)
//    at java.lang.reflect.Method.invoke(Native Method)
//    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
//    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

我的应用程序中有4个服务,所有这些服务基本上都是这样的:

public class MyService extends Service {

    private static final int forgroundId = 55544433; //Unique for each Service
    private Notification notification;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        initNotification(); //Creates a notification

        startForeground(forgroundId, notification); //Start foreground, very first thing..

        //Do Stuff

        return START_STICKY;
    }
}

启动服务时,我使用以下命令:

Intent i = new Intent(context, MyService.class);
i.SetAction("myaction..");
i.PutExtra(...);
android.support.v4.content.ContextCompat.startForegroundService(context, i);

我在我的项目中还包含了一些可能启动服务的其他库:
  • Fabric.io
  • Firebase Messaging/Analytics等。
  • Google Play服务的分析/GCM/Tasks等。
  • Evernote的Android-Job
问题是,我无法确定到底是哪个服务引起了此错误。如果异常中包含了该类,那么我就不会在这里了......
有没有任何方法可以[捕获/抛出/我不知道]异常来确定异常的来源?
我已经阅读了所有以下帖子,但都没有运气: 这种情况只会在打开应用程序时偶尔发生,因此对我来说我的代码是正确的?

我只想知道如何找出这是来自哪个服务。


你能否重现这个问题吗?即使只是偶尔出现也可以。如果可以,你应该能够回到Logcat并找出最近启动的服务是什么。但是,如果你只从生产用户那里得到这个问题,那么这种方法就行不通了。 - CommonsWare
@CommonsWare 谢谢您的回答,通过找出您的意思是为启动的服务添加日志行,然后看看可能是哪一个?这种情况经常发生,但不能直接重现。 - Pierre
“你的意思是为启动的服务添加日志行,然后看看可能是哪个服务?”-- 不,我认为有系统日志消息报告服务启动。对于活动启动肯定也有。 - CommonsWare
1
可能。您可以考虑摆脱所有这些,当工作完成时让服务自行停止。或者,您可以考虑切换到WorkManager(或Android-Job,因为您似乎已经在使用它),而不是为此编写自己的服务。 - CommonsWare
2
@CommonsWare 移除 onDestroyonLowMemory 方法解决了我的问题。 - Pierre
显示剩余4条评论
1个回答

7
如果您调用了startForegroundService(),则需要让服务启动。否则,您将收到“Context.startForegroundService()未调用Service.startForeground()”异常。
在您的情况下,似乎有时候您会在调用startForegroundService()之后但在服务的onStartCommand()被调用之前停止服务。显然这意味着服务最终没有启动。这可能是框架中的一个错误,但我们不太可能改变它,所以我们需要处理它。
一种方法是不使用自己的服务。对于像这样的“火并忘”类型的工作,使用WorkManager或可能的JobIntentService,您就不再需要担心前台。
如果您想坚持使用前台服务,请允许服务启动。一种做法是让服务停止自己。例如,服务可以有自己的onLowMemory()方法,在那里它可以停止自己。服务知道是否已经调用了startForeground(),并且可以比外部方案更优雅地处理这个问题。

1
这不是我的问题。我没有直接停止服务。相反,我发送了一个在服务的“onStartCommand”(调用“startForeground”)中注册的广播“关闭服务”。因此,在调用“startForeground”之前,服务永远不会停止。但是我仍然看到有时会报告错误。 - Huy Duong Tu

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