我目前正在处理音频播放应用,我使用启动绑定服务在后台播放音乐。我使用以下代码启动并绑定到服务。
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)
这只发生在奥利奥上,我已经读过奥利奥的背景限制。但是以下几点让我感到困惑。
为什么服务崩溃了?我究竟做错了什么?如果有人告诉我这里发生了什么,我感激不尽。
答案 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)
系统允许应用甚至调用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;
}