Android 通过解除绑定所有绑定活动来停止服务
我有一个已启动且绑定的服务(音乐播放器),我想在单击通知的关闭按钮时停止它。但是,如果存在绑定到该服务的活动,则不会停止该服务。 单击按钮时,如何停止服务 我已尝试收集服务中活动的列表,并调用回调以解除绑定(实际上是Android 通过解除绑定所有绑定活动来停止服务,android,android-service,android-notifications,android-service-binding,Android,Android Service,Android Notifications,Android Service Binding,我有一个已启动且绑定的服务(音乐播放器),我想在单击通知的关闭按钮时停止它。但是,如果存在绑定到该服务的活动,则不会停止该服务。 单击按钮时,如何停止服务 我已尝试收集服务中活动的列表,并调用回调以解除绑定(实际上是finish(),然后在onStop()上调用unbind()),然后通过调用stopSelf()停止服务但我认为这不是一个好主意,因为生命周期问题和某些活动会被多次添加并维护列表很困难。应该有更好的办法!虽然我找了好几个小时没找到任何东西 这是我的PlayerService的onS
finish()
,然后在onStop()
上调用unbind()
),然后通过调用stopSelf()停止服务
但我认为这不是一个好主意,因为生命周期问题和某些活动会被多次添加并维护列表很困难。应该有更好的办法!虽然我找了好几个小时没找到任何东西
这是我的PlayerService
的onStartCommand()
我的活动:
playerService.clients.add(object : PlayerService.Client {
override fun onStop() {
finish()
}
})
这是我的定制通知:
private fun getCustomNotification(name: String, showMainActivity: Intent): Notification {
/*
some codes to prepare notificationLayout
*/
notificationLayout.setTextViewText(R.id.tv_name, name)
notificationLayout.setImageViewResource(R.id.btn_play, playDrawableID)
notificationLayout.setOnClickPendingIntent(R.id.btn_play, playPendingIntent)
notificationLayout.setOnClickPendingIntent(R.id.btn_cancel, cancelPendingIntent)
// Apply the layouts to the notification
return NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.logo_mouj)
.setCustomContentView(notificationLayout)
.setContentIntent(PendingIntent.getActivity(this, 0, showMainActivity, 0))
.setOngoing(true)
.build()
}
试试这样的方法
fun stopServices() {
val serviceIntent = Intent(this, NotificationService::class.java)
serviceIntent.action = Constants.ACTION.STOPTFOREGROUND_ACTION
stopService(serviceIntent)
}
在活动中调用此方法
在服务启动命令中
ACTION.STOPFOREGROUND_ACTION -> {
//Toast.makeText(this, "Service Stoped", Toast.LENGTH_SHORT).show();
stopForeground(true);
stopSelf();
Intent intents = new Intent("com.app.package.ACTION_STOP");
LocalBroadcastManager.getInstance(this).sendBroadcast(intents);
//startActivity(new Intent(this,MainActivity.class));
}
val notificationLayout= new RemoteViews(getPackageName(), R.layout.custom_layout);
Intent closeIntent = new Intent(this, NotificationService.class);
closeIntent.setAction(Constants.ACTION.STOPFOREGROUND_ACTION);
PendingIntent cancelPendingIntent= PendingIntent.getService(this, 0, closeIntent, 0);
关闭按钮点击
notificationLayout.setOnClickPendingIntent(R.id.btn_cancel, cancelPendingIntent);
如果这项任务看起来令人沮丧,可能是因为这是一个不寻常的用例,有点超出了Android设计者的想法。您可能想问问自己,是否有一种更“类似Android”的方式来实现您的目标(也就是说,不需要列举绑定的客户端) 考虑您的要求:
活动
)服务开始播放,并通过onDestroy()
终止播放。这是设计错误,它会给你带来很多问题。毕竟,根据,本地进程内服务
实际上只是表示“应用程序希望在不与用户交互的情况下执行更长时间的运行操作”,而“它本身并不是一种脱离主线程工作的手段”
相反,通过在onStart()
和onStop()
之间保持每个活动的绑定,在播放开始时使用startService()
,在播放停止时使用stopSelf()
,您将自动完成目标1、2和4。当应用程序处于所有活动都在屏幕外的状态时,它将有0个绑定客户端。除此之外,如果没有未完成的startService()
,则可能会被操作系统立即终止。在任何其他状态下,操作系统都会将其保留
这不需要任何额外的逻辑来跟踪绑定的活动
。当然,您可能希望在播放器播放时startForeground()
,播放完毕后stopForeground()
(可能您已经处理了该细节)
这就留下了如何实现目标3的问题。要在服务
中通过活动
或通知实现状态更改,您只需使用意图
(就像您已经在做的那样)。在这种情况下,服务将通过stopSelf()
管理自己的生命周期。这再次假设您在适当的时间使用startForeground()
(Oreo+),否则Android可能会因为错误而终止您的应用程序
事实上,如果您选择使用意图
,您可能会发现您甚至不需要将活动
绑定到服务
(在这种情况下,目标1是不相关的)。如果您需要直接引用某个服务(通过活页夹),您只需绑定到该服务即可。它不起作用,您只是在接收时发送一个带有操作的意图,我不太明白该代码应该做什么。我想要的是解除所有活动的绑定,以便服务可以停止。是否使用音乐播放器的自定义通知布局?是。谢谢提醒,我将把它添加到问题中。问题不是为了关闭通知,它已经完成了。问题是如何解除所有活动的绑定,以便服务可以停止。在我看来,这个问题也可以用“如何从服务中关闭所有活动?”来表达。你能解释一下这与使用System.exit(0)
有什么不同吗?我不需要关闭我的活动。我只需要停止我的服务,但是因为活动绑定到它,它们需要“解除绑定”,而不是关闭OK,那么为什么您需要停止服务
?您是否出于某种原因试图将其发送到ondestory()
?如果您的活动在可见时不需要引用服务
,那么为什么要首先绑定它们?它是一个音乐播放器。我想关闭,因为用户想停止音乐并关闭应用程序,而绑定是用来控制音乐的。您让我有点不知所措了——从您的代码看,播放似乎是通过onStartCommand()中的Intents
来控制的
。我正在将它们绑定到onStart
上,并将它们解除绑定到onStop
上,但这仍然留下了一个问题,即当我仍在其中一个活动中时,如何停止服务。如果我调用stopSelf
服务将不会停止。我需要首先分离所有活动。im绑定到服务的原因是我需要iBinder调用服务上的函数,并在手头的任务中获取一些信息。也许我不明白你的答案。感谢您详细回答“当我仍在某项活动中时如何停止服务”典型的方法是,如果您的活动
需要服务
,则它对该服务
具有“依赖性”,并且
notificationLayout.setOnClickPendingIntent(R.id.btn_cancel, cancelPendingIntent);