[英]When should I use unbindService(), and how should I use it properly to unbind from a remote service that is using an AIDL interface?
I'm writing a simple music player, and I've created a playback service which implements an AIDL interface to bind with the clients, one a simple track browser and the other an even simpler player activity.我正在编写一个简单的音乐播放器,并且我创建了一个播放服务,它实现了一个与客户端绑定的 AIDL 接口,一个是简单的曲目浏览器,另一个是更简单的播放器活动。 The service controls the MediaPlayer object while the two activities use ServiceConnections to obtain connections to the service.
该服务控制 MediaPlayer object,而这两个活动使用 ServiceConnections 来获取与服务的连接。
This is included in the onStart() methods of both activities:这包含在两个活动的 onStart() 方法中:
@Override
public void onStart()
{
super.onStart();
Intent i = new Intent(this, PureService.class);
startService(i);
bindService(i, mConnection, 0);
}
I did this so that the service would not immediately stop upon unbinding.我这样做是为了使服务在解除绑定后不会立即停止。 Of course, that hasn't actually been a problem because my activity refuses to unbind from the service at all.
当然,这实际上并不是问题,因为我的活动根本拒绝与服务解除绑定。 Anytime my application gets to unbindService in either of these activities, unbindService throws IllegalArgumentException every time, without exception (hehe).
每当我的应用程序在这些活动中的任何一个中到达 unbindService 时,unbindService 每次都会抛出 IllegalArgumentException,无一例外(呵呵)。
In the onStop methods:在 onStop 方法中:
@Override
public void onStop()
{
super.onStop();
if (mBound) {
try {
unbindService(mConnection);
} catch (java.lang.IllegalArgumentException e)
{
//Print to log or make toast that it failed
}
}
mBound = false;
}
What I'm wondering is this:我想知道的是:
Thanks in advance.提前致谢。
EDIT: Here are the ServiceConnection overrides编辑:这里是 ServiceConnection 覆盖
public void onServiceConnected(ComponentName className, IBinder service) {
mBound = true;
mService = IPureService.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
There's some additional code in the player activity, but it's unrelated to the binding itself.玩家活动中有一些额外的代码,但它与绑定本身无关。
First, unless you actually need to make calls to this service across processes (that is, from other.apks, or you are using android:process to split up your own.apk into multiple processes for some reason), then I really recommend just dropping the use of aidl.首先,除非您确实需要跨进程调用此服务(即从 other.apks,或者您正在使用 android:process 出于某种原因将您 own.apk 拆分为多个进程),那么我真的建议只是放弃使用aidl。 It is more complexity for no gain.
它更加复杂,没有任何收获。 The "Local Service Sample" in the Service documentation shows how to do this: http://developer.android.com/reference/android/app/Service.html
服务文档中的“本地服务示例”显示了如何执行此操作: http://developer.android.com/reference/android/app/Service.html
Second, doing a bind at the same time as a start is a strong indication of some basic flaw in the design.其次,在开始的同时进行绑定是设计中存在一些基本缺陷的强烈迹象。 Starting a service and binding to a service are semantically very different, so will be done at different places based on those different semantics.
启动服务和绑定到服务在语义上非常不同,因此将根据这些不同的语义在不同的地方完成。 That is, if both are even done at all... in fact it is an unusual situation where you are using both start and bind with the same service.
也就是说,如果两者都完成了......事实上,这是一种不寻常的情况,您同时使用启动和绑定相同的服务。
In the class implementation of a service for doing music playback, it would use start when it is actively performing playback (so its process doesn't get killed by the system when the user is no longer actively interacting with the application's UI).在用于播放音乐的服务的 class 实现中,它将在主动执行播放时使用 start (因此当用户不再主动与应用程序的 UI 交互时,其进程不会被系统杀死)。 Starting the service when the user has enters the UI is likely to cause pain because now the start/stopped state of the service is not clearly defined -- it could be started either because it is doing playback or because the user happens to have gone into the app's UI, and now when is the right time to stop it?
当用户进入 UI 时启动服务可能会造成痛苦,因为现在服务的启动/停止 state 没有明确定义——它可能因为正在播放或用户碰巧进入应用程序的用户界面,现在什么时候停止它? This is going to be troublesome.
这会很麻烦。
Now as far as when to unbind -- you just need to make sure you always match an unbindService() with a previous bindService().现在至于何时解除绑定——您只需要确保始终将 unbindService() 与先前的 bindService() 匹配。 From your snippets of code it looks like you are doing this, but there are strange things in it like mBound never being set.
从您的代码片段来看,您似乎正在这样做,但其中有一些奇怪的事情,例如从未设置过 mBound。 In fact if you are consistently binding in onStart() and unbinding in onStop(), you should never need to have an mBound to decide whether to unbind, because onStop() is always called after onStart().
事实上,如果您始终在 onStart() 中绑定并在 onStop() 中取消绑定,则永远不需要 mBound 来决定是否取消绑定,因为 onStop() 总是在 onStart() 之后调用。
So with the code you give here, it doesn't look like there is a problem.因此,使用您在此处提供的代码,看起来没有问题。 If you are getting exceptions, though, there clearly is so it may be elsewhere in your app.
但是,如果您遇到异常,那么很明显它可能在您的应用程序的其他地方。 To help narrow the problem down, you can use this flag when you call bindService() to get additional information in the log when the failure happens: http://developer.android.com/reference/android/content/Context.html#BIND_DEBUG_UNBIND
为了帮助缩小问题范围,您可以在调用 bindService() 时使用此标志以在发生故障时获取日志中的其他信息: http://developer.android.com/reference/android/content/Context.html# BIND_DEBUG_UNBIND
A couple of points:几点:
onStop
is fine: this is where I call it in multiple apps and I've never seen that particular error. onStop
中的 unbindService() 很好:这是我在多个应用程序中调用它的地方,我从未见过那个特定的错误。 I expect you have some other issue with your ServiceConnection: show the code for your mConnection
object and we can probably figure out what's wrong with it.mConnection
object 的代码,我们可能会弄清楚它有什么问题。 I had this weird error as well.我也有这个奇怪的错误。 Then I tried doing the bind to the service in onResume() instead of in onStart() in the Activity, and voila, no more exceptions.
然后我尝试在 onResume() 中而不是在 Activity 中的 onStart() 中绑定到服务,瞧,没有更多的例外。 I am still a bit clueless as to why this works, If someone could explain.
如果有人可以解释,我仍然对为什么会这样工作一无所知。 I'd be one happy coder: :)
我会成为一名快乐的编码员::)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.