绑定服务崩溃与" Context.startForegroundService()然后没有调用Service.startForeground()"错误

时间:2017-12-02 15:08:33

标签: android service kotlin android-8.0-oreo

我目前正在处理音频播放应用,我使用启动绑定服务在后台播放音乐。我使用以下代码启动并绑定到服务。

val intent = Intent(context, MusicService::class.java)
context.startService(intent)
context.bindService(intent, serviceConnection, 0)

在播放时会升级到前景,在音乐暂停时会降级。

// onAudioPlay
service.startForeground(NOTIFY_ID, notification)

// onAudioPause
service.stopForeground(false)

到目前为止服务工作很好。但是当用户在暂停状态下刷新(删除)通知时,服务会在几秒钟后崩溃,从而出现此错误。

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myplayer, PID: 4380
    android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
        android.app.ActivityThread$H.handleMessage(ActivityThread.java:1775)
        android.os.Handler.dispatchMessage(Handler.java:105)
        android.os.Looper.loop(Looper.java:164)
        android.app.ActivityThread.main(ActivityThread.java:6541)
        java.lang.reflect.Method.invoke(Native Method)
      com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

这只发生在奥利奥上,我已经读过奥利奥的背景限制。但是以下几点让我感到困惑。

  • 此服务是受约束的服务(不受限制影响)
  • 我从不使用Context.startForegroundService()来启动服务。(并且不想使用它)
  • 当服务从前台降级时,服务不会崩溃,删除通知时会发生这种情况。

为什么服务崩溃了?我究竟做错了什么?如果有人告诉我这里发生了什么,我感激不尽。

7 个答案:

答案 0 :(得分:10)

展开UdeshUk's answer - 使用MediaButtonReceiver(构建待定意图或仅接收媒体按钮意图)可能会导致使用startForegroundService调用您的服务,因为{{1}在Oreo上以这种方式启动你的服务。我还没有在任何地方看到过这种情况。

答案 1 :(得分:7)

您必须在Service类onCreate()方法中调用此方法: - >

private void startServiceOreoCondition(){
        if (Build.VERSION.SDK_INT >= 26) {


            String CHANNEL_ID = "my_service";
            String CHANNEL_NAME = "My Background Service";

            NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                    CHANNEL_NAME,NotificationManager.IMPORTANCE_NONE);
            ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);

            Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                    .setCategory(Notification.CATEGORY_SERVICE).setSmallIcon(R.drawable.ic_tgc_icon).setPriority(PRIORITY_MIN).build();

            startForeground(101, notification);
        }
    }

答案 2 :(得分:5)

我发现了问题。在我的通知中,我已经设置了

setDeleteIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(service, PlaybackStateCompat.ACTION_STOP))

因此,当用户删除通知时,它会调用startForegroundService(),因为我在暂停时调用了stopForeground()。

为了克服这个问题,我使用了自定义待处理意图并在onStartCommand()而不是 MediaButtonReveiver&#39> PendingIntent

中处理了它

答案 3 :(得分:2)

来自文档8.0 Behavior Changes

  

系统允许应用甚至调用Context.startForegroundService()   而应用程序在后台。但是,应用程序必须调用它   服务的startForeground()方法在5秒后   服务已创建。

因此,您必须在onCreate()内为您的服务调用startForeground。

答案 4 :(得分:1)

该聚会迟到了,但是正如前面所提到的,它是MediaButtonReceiver;它具有以下代码:

    @Override
    public void onReceive(Context context, Intent intent) {
        ...
        startForegroundService(context, intent);
        ...
    }

我在绑定服务中使用接收器,因此我创建了一个类,该类的代码与MediaButtonReceiver完全相同,但此行除外。我将其替换为:

        context.startService(intent);

答案 5 :(得分:0)

我遇到了同样的问题,但是我使用通知服务对其进行了修复

public void createNotificationChannel(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

        NotificationChannel serviceChanel =new NotificationChannel(
                CHANNEL_ID,
                "Forground service Chane"
                , NotificationManager.IMPORTANCE_DEFAULT
        );
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(serviceChanel);
    }
}

在课程开始时创建Chanel ID

public static final String CHANNEL_ID = "ForegroundServiceChannel";

和onStartCommand内部服务

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {


        createNotificationChannel();
        Intent notificationIntent = new Intent(this , MainActivity.class);
        PendingIntent pendingIntent =PendingIntent.getActivity(this,0,notificationIntent,0);
        Notification notification = new NotificationCompat.Builder(this,CHANNEL_ID)
                .setContentTitle("ForgroundService")
                .setContentText("Any message")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(pendingIntent)
                .build();
        startForeground(1,notification);
    }

输入该代码

来源https://androidwave.com/foreground-service-android-example/

答案 6 :(得分:0)

MediaButtonReceiver调用startForegroundService,这对我来说是元凶。当我没有媒体可播放(播放列表为空)时,发生了我的问题。我通过显示通知并立即在onStartCommand中取消通知来解决了这个问题:

    if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);

        builder.setSmallIcon(R.drawable.notification)
                .setContentTitle("")
                .setContentText("")
                .setSmallIcon(R.drawable.notification);
        startForeground(99, builder.build());
        stopForeground(true);
        
        MyMediaButtonReceiver.handleIntent(mediaSessionCompat, intent);
    
        return START_NOT_STICKY;
      }