简体   繁体   English

何时应该使用 unbindService(),以及如何正确使用它来解除与使用 AIDL 接口的远程服务的绑定?

[英]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:我想知道的是:

  • Should I be calling unbindService() in the onStop() method?我应该在 onStop() 方法中调用 unbindService() 吗? Or at all?还是根本没有?
  • Am I calling it correctly?我正确地调用它吗?
  • Is there anything peculiar about the way I'm starting/binding the service that I should know about?我应该知道的启动/绑定服务的方式有什么特别之处吗?
  • Am I doing something utterly, completely wrong?我在做一些完全、完全错误的事情吗? I'm new to android programming so that's certainly not out of the question.我是 android 编程的新手,所以这当然不是不可能的。

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:几点:

  1. Return START_STICKY in onStartCommand if you want your Service to live longer than the bound Activities.如果您希望您的服务比绑定的活动寿命更长,请在onStartCommand中返回START_STICKY
  2. unbindService() in 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.我希望您的 ServiceConnection 有其他问题:显示您的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM