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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:30:32  来源:igfitidea点击:

Android java.lang.IllegalArgumentException: Service not registered

androidandroid-serviceandroid-service-binding

提问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 registeredbeing 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 registeredunbindService()调用时生成。我错过了一些愚蠢的事情,还是还有更多事情发生?我应该注意到,可能存在多个相同的片段。

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 mIsBoundinside doBindService()and doUnbindService()instead of in the ServiceConnectioninstance.

使用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 registeredmeans 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 unbindServiceis 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 unbindServiceis called by the context that has bound the Serviceand not by the bound Serviceitself. 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 in onStop()

解决方案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 in onCreate()and unbind in onDestroy()

解决方案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 onPauseis called beforeonServiceDisconnected. So I would try Synchronizedthings to ensure correct execution.

我的应用程序有完全相同的问题。我时不时地得到IllegalArgumentException。我想这种特殊情况是在服务未绑定并且之前onPause被调用时引起的。所以我会尝试确保正确执行。onServiceDisconnectedSynchronized