Ошибка связанного обслуживания с помощью "Context.startForegroundService() не вызвала ошибку Service.startForeground()"
В настоящее время я работаю над приложением для воспроизведения звука, и я использую запущенную службу для воспроизведения музыки в фоновом режиме. Я начинаю и привязываюсь к службе, используя следующий код.
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)
Это происходит только в Oreo, и я уже читал об ограничениях фона в Oreo. Но следующие моменты меня обманывают.
- Эта служба является связанной службой (на которую не распространяются ограничения)
- Я никогда не использую Context.startForegroundService() для запуска службы (и не хочу ее использовать).
- Служба не сбрасывается, когда ее снижают с приоритета, это происходит при удалении уведомления.
Почему служба рушится? Что я делаю не так? Я очень благодарен, если кто-то скажет мне, что происходит здесь.
Ответы
Ответ 1
Чтобы расширить ответ UdeshUk - любое использование MediaButtonReceiver
(либо создание ожидающих намерений, либо просто получение намерений мультимедийных кнопок) может привести к тому, что ваш сервис будет вызываться с помощью startForegroundService
, поскольку MediaButtonReceiver.onReceive
запускает ваш сервис таким образом в Oreo. Я не видел это нигде документально.
Ответ 2
Вы должны вызвать этот метод внутри вашего класса 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);
}
}
Ответ 3
Я нашел проблему. В моем уведомлении я установил
setDeleteIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(service, PlaybackStateCompat.ACTION_STOP))
Поэтому, когда пользователь удаляет уведомление, он вызывает startForegroundService(), потому что я вызывал stopForeground() ранее при паузе.
Чтобы преодолеть, я использовал индивидуальное ожидающее намерение и обработал его в onStartCommand()
вместо MediaButtonReveiver PendingIntent
Ответ 4
Из документов 8.0 Изменения поведения
Система позволяет приложениям вызывать Context.startForegroundService() даже в то время как приложение находится в фоновом режиме. Однако приложение должно вызвать это службы startForeground() в течение пяти секунд после создается сервис.
Итак, вы должны вызвать startForeground внутри onCreate() для вашей службы.
Ответ 5
Поздно к вечеринке, но, как упоминалось ранее, это MediaButtonReceiver
; у него есть этот код:
@Override
public void onReceive(Context context, Intent intent) {
...
startForegroundService(context, intent);
...
}
Я использую получатель в связанном сервисе, поэтому я создал класс, который имеет тот же код, что и MediaButtonReceiver
, за исключением этой строки. Я заменил его на:
context.startService(intent);