Android java.lang.IllegalArgumentException:服务未注册
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22079909/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android java.lang.IllegalArgumentException: Service not registered
提问by dcow
I have a setup that looks something like this:
我有一个看起来像这样的设置:
class MyFragment implements SomeEventListener {
Application mAppContext;
boolean mBound;
boolean mDidCallUnbind;
MyIBinder mBinder;
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBound = true;
mBinder = (MyIBinder) service;
mBinder.getThings();...
}
@Override
public void onServiceDisconnected(ComponentName name) {
mDidCallUnbind = false;
mBound = false;
mBinder = null;
}
};
...
@Override
public void onSomeEvent() {
mAppContext.bindService(...);
}
void unbindService() {
if (mBound && !mDidCallUnbind) {
mDidCallUnbind = true;
mAppContext.unbindService(mConnection);
}
}
@Override
public void onPause() {
unbindService();
super.onPause();
}
}
However, I am still seeing the error in the title from time to time: java.lang.IllegalArgumentException: Service not registered
being generated when unbindService()
is called. Am I missing something silly, or is there more going on? I should note that there may be more than one of this same fragment in existence.
但是,我仍然时不时地看到标题中的错误:java.lang.IllegalArgumentException: Service not registered
在unbindService()
调用时生成。我错过了一些愚蠢的事情,还是还有更多事情发生?我应该注意到,可能存在多个相同的片段。
Edit
编辑
Since no one actually seems to be reading the code, let me explain. unbindService()
does not call Context.unbindService(ServiceConnection)
unless the service is bound (mBound
) andit had not previously been called before the onServiceDisconnected(...)
callback was hit from a possible previous call to unbindService()
.
由于实际上似乎没有人在阅读代码,让我解释一下。 unbindService()
不会调用,Context.unbindService(ServiceConnection)
除非服务被绑定 ( mBound
)并且在之前onServiceDisconnected(...)
可能调用unbindService()
.
That in mind, are there any cases where Android will unbind your service for you such that the service would become unbound but onServiceDisconnected would not be called thus leaving me in a stale state?
请记住,在任何情况下,Android 是否会为您解除绑定您的服务,从而使该服务解除绑定,但不会调用 onServiceDisconnected 从而使我处于陈旧状态?
Also, I am using my Application context to do the initial binding. Assume something like:
此外,我正在使用我的应用程序上下文进行初始绑定。假设类似:
@Override
public void onCreate() {
mApplication = getContext().getApplicationContext();
}
采纳答案by aaronvargas
I realize this question has already been answered. But I think there is reason to go into why people are making this mistake.
我意识到这个问题已经得到了回答。但我认为有理由深入探讨为什么人们会犯这个错误。
The issue is really with the training docs. http://developer.android.com/reference/android/app/Service.htmlshows a correct implementation while https://developer.android.com/guide/components/bound-services.htmlin the 'ActivityMessenger' shows a Very INCORRECTimplementation.
问题确实出在培训文档上。http://developer.android.com/reference/android/app/Service.html显示了正确的实现,而“ActivityMessenger”中的https://developer.android.com/guide/components/bound-services.html显示了一个非常不正确实施。
In the 'ActivityMessenger' example onStop() could potentially be called before the service has actually been bound.
在“ActivityMessenger”示例中,可能在实际绑定服务之前调用 onStop()。
The reason for this confusion is they are using the bound service boolean to mean different things in different examples. (mainly, was bindService() called OR is the Service actually connected)
这种混淆的原因是他们使用绑定服务布尔值在不同的例子中表示不同的东西。(主要是 bindService() 被调用或者是实际连接的服务)
In the correct examples where unbind() is done based on the value of the bound boolean, the bound boolean indicates that the bindService() was called. Since it's queued up for main thread execution, then unbindService() needs to be called (so queued to be executed), regardless of when (if ever) onServiceConnected() happens.
在根据绑定布尔值完成 unbind() 的正确示例中,绑定布尔值表示调用了bindService()。由于它已排队等待主线程执行,因此需要调用 unbindService()(因此排队等待执行),无论何时(如果有)onServiceConnected() 发生。
In other examples, such as the one in http://developer.android.com/reference/android/app/Service.html. The bound indicates that the Services is Actually bound so that you can use it and not get a NullPointerException. Note that in this example, the unbindService() call is still made and the bound boolean doesn't determine whether to unbind or not.
在其他示例中,例如http://developer.android.com/reference/android/app/Service.html 中的示例。绑定表明服务实际上是绑定的,这样您就可以使用它而不会得到 NullPointerException。请注意,在此示例中,仍会调用 unbindService() 并且绑定的布尔值无法确定是否取消绑定。
回答by Jacob Phillips
Use mIsBound
inside doBindService()
and doUnbindService()
instead of in the ServiceConnection
instance.
使用mIsBound
内部doBindService()
和doUnbindService()
代替的ServiceConnection
实例。
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinder = (MyIBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
mBinder = null;
}
};
...
public void doBindService() {
bindService(new Intent(this, MyService.class),
mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
public void doUnbindService() {
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
}
}
This is how it's done in http://developer.android.com/reference/android/app/Service.html
这就是它在http://developer.android.com/reference/android/app/Service.html 中的完成方式
回答by pelotasplus
java.lang.IllegalArgumentException: Service not registered
means that you weren't bound to service when unbindService()
was called.
java.lang.IllegalArgumentException: Service not registered
意味着您在unbindService()
被调用时不受服务的约束。
So in your case, onSomeEvent()
was never called before call to unbindService()
in onPause()
所以在你的情况下,onSomeEvent()
在调用之前从未被调用unbindService()
过onPause()
回答by Cordis Audax Agrinova
Another possible reason for this exception might be that unbindService
is called by the wrong Context
. Because services can be bound not only by Activities, but also by other instances inherited by Context
(with the exception of BroadcastReceivers), even by other Services, be sure that unbindService
is called by the context that has bound the Service
and not by the bound Service
itself. This would yield directly the above exception "Service not registered".
此异常的另一个可能原因可能unbindService
是由错误的Context
. 因为服务不仅可以被活动绑定,还可以被其他继承的实例Context
(除了广播接收器),甚至被其他服务unbindService
绑定,请确保由绑定了Service
而不是由绑定Service
本身的上下文调用。这将直接产生上述异常“服务未注册”。
回答by Rohit Singh
Reason?
原因?
If in your Activity, unbindService() gets called before bindService() then you will get this IllegalArgumentException
.
如果在您的活动中, unbindService() 在 bindService() 之前被调用,那么您将得到 this IllegalArgumentException
。
How to avoid it?
It's simple. You would not need a boolean flag if you bind and unbind service in this order.
如何避免?
这很简单。如果按此顺序绑定和取消绑定服务,则不需要布尔标志。
Solution 1:
Bind in
onStart()
and unbind inonStop()
解决方案1:
绑定
onStart()
和解绑onStop()
Your Activity {
@Override
public void onStart()
{
super.onStart();
bindService(intent, mConnection , Context.BIND_AUTO_CREATE);
}
@Override
public void onStop()
{
super.onStop();
unbindService(mConnection);
}
}
Solution 2:
Bind inonCreate()
and unbind inonDestroy()
解决方案2:
绑定onCreate()
和解绑onDestroy()
Your Activity {
@Override
public void onCreate(Bindle sis)
{
super.onCreate(sis);
....
bindService(intent, mConnection , Context.BIND_AUTO_CREATE);
}
@Override
public void onDestroy()
{
super.onDestroy();
unbindService(mConnection);
}
}
Relevant Link:
相关链接:
Android official documentation suggeststhat
If you need to interact with the service only while your activity is visiblethen go with Solution1.
If you want your activity to receive responses even while it is stopped in the backgroundthen go with Solution2.
Android的官方文件表明是
如果你需要互动与服务只在您的活动是可见的,然后一起去解决方法1。
如果您希望您的活动即使在后台停止时也能收到响应,请使用Solution2。
回答by NickUnuchek
class ServiceBindManager<T>(val context: Context, clazz: Class<T>) {
val TAG: String = "ServiceBindManager"
private val isBound: AtomicBoolean = AtomicBoolean(false)
private var intent: Intent = Intent(context, clazz)
private val connection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
Log.d(TAG, "onServiceConnected: $context")
isBound.set(true)
}
override fun onServiceDisconnected(name: ComponentName?) {
Log.d(TAG, "onServiceDisconnected: $context")
isBound.set(false)
}
override fun onBindingDied(name: ComponentName?) {
isBound.set(false)
}
override fun onNullBinding(name: ComponentName?) {
isBound.set(false)
}
}
fun bindService() {
Log.e(TAG, "bindService: $context")
isBound.set(context.bindService(intent, connection, BIND_AUTO_CREATE))
}
fun unbindService() {
Log.e(TAG, "unbindService: $context")
if (isBound.get()) {
isBound.set(false)
context.unbindService(connection)
}
}
}
Usage:
用法:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
serviceBindManager = ServiceBindManager(this@MyActivity, MyService::class.java)
}
override fun onStart() {
super.onStart()
serviceBindManager.bindService()
}
override fun onStop() {
super.onStop()
serviceBindManager.unbindService()
}
回答by slott
I have the exact same issue with my application. Every now and then I get IllegalArgumentException
. I guess the special case is caused when the service is unbound and the onPause
is called beforeonServiceDisconnected
. So I would try Synchronized
things to ensure correct execution.
我的应用程序有完全相同的问题。我时不时地得到IllegalArgumentException
。我想这种特殊情况是在服务未绑定并且之前onPause
被调用时引起的。所以我会尝试确保正确执行。onServiceDisconnected
Synchronized