代码之家  ›  专栏  ›  技术社区  ›  UdeshUK

绑定服务崩溃,出现“Context.startForegroundService()未调用service.startForeground()”错误

  •  27
  • UdeshUK  · 技术社区  · 7 年前

    我目前正在开发音频播放应用程序,我正在使用一个已启动的绑定服务在后台播放音乐。我使用以下代码启动并绑定到服务。

    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)
    

    这只发生在奥利奥上,我已经读到奥利奥的背景限制。但以下几点让我很烦。

    • 此服务是绑定服务(不受限制)
    • 我从不使用语境。startForegroundService()启动服务。(不想使用)
    • 服务从前台降级时不会崩溃,而是在删除通知时发生。

    为什么服务会崩溃?我做错了什么?如果有人告诉我这里发生了什么,我非常感激。

    7 回复  |  直到 7 年前
        1
  •  16
  •   Andy S    6 年前

    展开 UdeshUk's answer -任何使用 MediaButtonReceiver (建立挂起的意图或只是接收媒体按钮意图)可能会导致调用您的服务 startForegroundService 因为 MediaButtonReceiver.onReceive 在奥利奥上以这种方式开始服务。我在任何地方都没有看到这方面的记录。

        2
  •  10
  •   UdeshUK    7 年前

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

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

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

    为了克服这个问题,我使用了一个自定义挂起意图,并在 onStartCommand() 而不是 MediaButtonReviever的 处理意图

        3
  •  7
  •   Ramkailash    6 年前

    您必须在服务类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);
            }
        }
    
        4
  •  3
  •   mhashim6    5 年前

    晚会迟到了,但正如前面提到的,这是 MediaButtonReceiver

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

    我在绑定服务中使用接收器,所以我创建了一个类,其代码与 MediaButton接收器 ,但此行除外。我将其替换为:

            context.startService(intent);
    
        5
  •  2
  •   lakshman.pasala    7 年前

    从文档中 8.0 Behavior Changes

    该系统允许应用程序调用上下文。startForegroundService()偶数 当应用程序在后台时。然而,应用程序必须调用它 服务的startForeground()方法 服务已创建。

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

        6
  •  0
  •   Shan Pathiraja    5 年前

    我也有同样的问题,但我用通知服务解决了

    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);
        }
    }
    

    在课程开始时创建香奈儿id

    public static final String CHANNEL_ID = "ForegroundServiceChannel";

    和服务

    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/

        7
  •  0
  •   Mateusz Kaflowski    4 年前

    MediaButtonReceiver 调用StartForegroundsService,这是我的罪魁祸首。我的问题发生在没有媒体播放时(播放列表为空)。我通过在中显示通知并立即取消它来解决这个问题 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;
          }