Context.startForegroundService()在停止服务后没有调用Service.startForeground()。

13

我的应用有一些远程操作可以触发服务和通知。在调用startForegroundService和服务尝试启动通知之间,可能会发生变化,因此服务会再次检查情况并决定接下来该做什么。

如果服务决定不需要运行,它将调用:

stopForeground(true);
stopSelf();

但出于某种原因,这似乎不起作用,因为在进行这些调用后很快就会出现异常。

11-16 13:34:23.488 15099-15099/mypackage E/AndroidRuntime: FATAL EXCEPTION: main
Process: mypackage, PID: 15099
android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1768)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

那我该如何解决这个问题呢?

谢谢。

编辑:

我创建了一个示例项目,它只是在Activity启动时调用startForegroundService,然后在服务上执行以下操作:

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG,"start");
        stopForeground(true);
        stopSelf();
        return super.onStartCommand(intent, flags, startId);
    }

无论我是否使用 stopForeground(true),它都会崩溃。

编辑:这似乎可以解决问题,但是创建一个虚假通知只是为了取消它看起来很丑陋。

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG,"start");
        String CHANNEL_ID = "my_channel_01";
        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(this, CHANNEL_ID)

                        .setContentTitle("My notification")
                        .setContentText("Hello World!");

        startForeground(-1,mBuilder.build());
        stopForeground(true);
        stopSelf();
        return super.onStartCommand(intent, flags, startId);
    }

尝试在调用stopForeground()stopSelf()之前立即调用startForeground() - CommonsWare
那么直接调用 stopSelf() 怎么样?如果一个 Service 被停止了,我认为(好吧,我猜)它将不再处于前台。 - Bö macht Blau
要启动前台,我需要一个通知,对吗?我将尝试仅使用stop self。 - casolorz
我刚刚阅读了startForegroundService()的文档。也许你的服务确实必须在执行任何其他操作之前调用startForeground(),因为它看起来像某种契约:“服务被赋予与ANR间隔相当的时间来执行此操作,否则系统将自动停止服务并声明应用程序ANR。” - Bö macht Blau
请注意,您无需仅为使用 startForeground() 调用 startForegroundService()。只有当您在后台并且该事件不是从少数几个允许的来源之一触发(例如,通知操作)时才需要它。 - CommonsWare
显示剩余5条评论
1个回答

7

我有同样的问题,并且在调用stopSelf()之前使用了相同的解决方法:

private void fakeStartForeground() {
        NotificationCompat.Builder builder =
                new NotificationCompat.Builder(this, CHANNEL_ID)
                        .setContentTitle("")
                        .setContentText("");

        startForeground(NOTIFICATION_ID, builder.build());
}

我认为谷歌的某个人应该给我们提供一些解决方案。你在谷歌错误报告论坛中发帖了吗?

1
我提交了一个错误报告,他们说一旦调用“start foreground service”方法,就会进入一个合同,在这个合同中必须创建一个通知。我正在使用与您相同的解决方法。 - casolorz

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