Android java.lang.IllegalArgumentException: служба не зарегистрирована

У меня есть установка, которая выглядит примерно так:

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();
    }
}

Однако время от времени я все еще вижу ошибку в заголовке: java.lang.IllegalArgumentException: Service not registered создается при вызове unbindService(). Я упустил что-то глупое или что-то еще происходит? Я должен отметить, что может существовать несколько таких фрагментов.

Изменить

Поскольку на самом деле кажется, что никто не читает код, позвольте мне объяснить. unbindService() не вызывает Context.unbindService(ServiceConnection), если служба не привязана (mBound) и она не вызывалась ранее до того, как обратный вызов onServiceDisconnected(...) был получен из возможного предыдущего вызова unbindService().

Имея это в виду, есть ли случаи, когда Android отвяжет вашу службу для вас, так что служба станет несвязанной, но onServiceDisconnected не будет вызываться, что оставит меня в устаревшем состоянии?

Кроме того, я использую контекст своего приложения для начальной привязки. Предположим что-то вроде:

@Override
public void onCreate() {
    mApplication = getContext().getApplicationContext();
}

person dcow    schedule 27.02.2014    source источник
comment
Если onSomeEvent() никогда не произойдет до onPause(), то ваша служба не привязана.   -  person Justin Jasmann    schedule 28.02.2014
comment
@JustinJasmann, ясно. Вы читали мой код?   -  person dcow    schedule 28.02.2014
comment
да. Вы не показали, где вы инициализируете mAppContext, какой контекст вы используете?   -  person Justin Jasmann    schedule 28.02.2014
comment
@JustinJasmann контекст приложения. mAppContext относится к типу Application.   -  person dcow    schedule 28.02.2014
comment
@dcow, ты нашел причину или решение? Заранее спасибо...   -  person burakk    schedule 15.12.2014
comment
@burakk Я не делал. Мы немного переделали архитектуру, так что это не было проблемой, но я до сих пор не знаю, в чем дело.   -  person dcow    schedule 16.12.2014
comment
У меня была такая же проблема. Этот ответ stackoverflow.com/a/16713212 помог.   -  person Roman Zhilich    schedule 18.03.2015
comment
@RomanZhilich молодец! Это объяснило бы это. Спасибо.   -  person dcow    schedule 18.03.2015


Ответы (8)


Я понимаю, что на этот вопрос уже дан ответ. Но я думаю, что есть причина выяснить, почему люди совершают эту ошибку.

Проблема действительно в учебной документации. http://developer.android.com/reference/android/app/Service.html показывает правильную реализацию, а https://developer.android.com/guide/components/bound-services.html в ActivityMessenger показывает очень НЕПРАВИЛЬНУЮ реализацию.

В примере ActivityMessenger onStop () потенциально может быть вызван до фактического связывания службы.

Причина этой путаницы в том, что они используют логическое значение связанной службы для обозначения разных вещей в разных примерах. (в основном, был вызван bindService () ИЛИ действительно ли служба подключена)

В правильных примерах, где unbind () выполняется на основе значения связанного логического значения, связанное логическое значение указывает, что была вызвана bindService (). Поскольку он поставлен в очередь для выполнения основного потока, необходимо вызвать unbindService () (поэтому он поставлен в очередь для выполнения), независимо от того, когда (если когда-либо) произойдет onServiceConnected ().

В других примерах, например, в http://developer.android.com/reference/android/app/Service.html. Граница указывает на то, что Службы фактически связаны, так что вы можете использовать их и не получать исключение NullPointerException. Обратите внимание, что в этом примере вызов unbindService () все еще выполняется, а связанное логическое значение не определяет, следует ли отменять привязку.

person aaronvargas    schedule 02.02.2018
comment
Я знал, что видел это с обеих сторон, но не мог вспомнить, откуда исходит дезинформация ... спасибо за установление связи. - person dcow; 05.02.2018
comment
Короче говоря, я должен использовать булевский возврат bindService () вместо зависимости от onServiceConnected (), верно? - person Aloha; 16.04.2020
comment
@PNDA Да, теперь в документации сказано: developer.android.com/reference/android/content/ - person now; 15.10.2020
comment
onServiceConnected, но услуга не ограничена? какого черта - person wukong; 23.11.2020

Используйте 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() {
    mIsBound =bindService(new Intent(this, MyService.class),
        mConnection, Context.BIND_AUTO_CREATE); 
}

public void doUnbindService() {
    if (mIsBound) {
        unbindService(mConnection);
        mIsBound = false;
    }
}

Вот как это делается в http://developer.android.com/reference/android/app/Service.html

person Jacob Phillips    schedule 10.09.2015
comment
не имеет смысла. вы устанавливаете mIsBound до, что он действительно привязан? Я считаю, что bindService находится в другом потоке. - person likejudo; 18.10.2016
comment
@likejiujitsu в документации говорится о методе bindService: If you have successfully bound to the service, true is returned; false is returned if the connection is not made so you will not receive the service object. However, you should still call unbindService(ServiceConnection) to release the connection. Другими словами, соединение устанавливается, как только метод возвращается, поэтому после вызова этого метода вы ДОЛЖНЫ отменить привязку службы. - person Rolf ツ; 17.08.2017
comment
Я больше не могу видеть часть, однако, в документации. Возможно, нам не следует вызывать unbind, если bind вернул false - person Klitos G.; 28.11.2019
comment
@Rolf ツ Может быть, тогда документация изменилась. Теперь в нем указано true if the system is in the process of bringing up a service that your client has permission to bind to; false if the system couldn't find the service or if your client doesn't have permission to bind to it. If this value is true, you should later call unbindService(ServiceConnection) to release the connection. - developer.android.com/reference/android/content/ - person now; 15.10.2020

java.lang.IllegalArgumentException: Service not registered означает, что вы не были привязаны к обслуживанию, когда был вызван unbindService().

Итак, в вашем случае onSomeEvent() никогда не вызывался до вызова unbindService() в onPause()

person pelotasplus    schedule 27.02.2014
comment
Спасибо за ответ, но объясните, пожалуйста, как вызов Context.unbindService (ServiceConnection); в мой код можно попасть. - person dcow; 28.02.2014
comment
У меня такая же проблема с моим приложением. Время от времени я получаю исключение IllegalArgumentException. - person slott; 28.06.2014
comment
Соответствующие документы: http://stackoverflow.com/questions/12277673/android-services-error-service-not-registered/16713212#16713212 - person dcow; 08.12.2015
comment
Каково решение? - person IgorGanapolsky; 03.06.2020

Другая возможная причина этого исключения может заключаться в том, что unbindService вызван неправильным Context. Поскольку службы могут быть связаны не только с действиями, но и с другими экземплярами, унаследованными Context (за исключением BroadcastReceivers), даже другими службами, убедитесь, что unbindService вызывается контекстом, который привязал Service, а не привязкой Service сам. Это приведет непосредственно к вышеуказанному исключению «Служба не зарегистрирована».

person Cordis Audax Agrinova    schedule 29.06.2018
comment
Это была моя проблема! - person JohnyTex; 02.05.2019

Причина?

Если в вашей деятельности unbindService () вызывается перед bindService (), вы получите это IllegalArgumentException.

Как этого избежать?
Все просто. Вам не понадобится логический флаг, если вы привязываете и отключаете службу в этом порядке.

Решение 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);
    }

 } 

Решение 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);
    }         

 }

Соответствующая ссылка:

Официальная документация Android предполагает, что
если вам нужно взаимодействовать с сервис только тогда, когда ваша активность видима, выберите Решение1.
Если вы хотите, чтобы ваши действия получали ответы, даже когда они остановлены в фоновом режиме затем выберите Решение2.

person Rohit Singh    schedule 06.04.2019
comment
Остановка и отмена привязки Сервиса не связана с жизненным циклом действия - person IgorGanapolsky; 03.06.2020

В моем случае я вызвал bindService с помощью Activity Context и попытался отвязать его с помощью ApplicationContext. Не делай этого.

person wukong    schedule 23.11.2020

У меня такая же проблема с моим приложением. Время от времени я получаю IllegalArgumentException. Я предполагаю, что особый случай возникает, когда служба не связана и onPause вызывается до onServiceDisconnected. Поэтому я бы попробовал Synchronized вещи, чтобы гарантировать правильное выполнение.

person slott    schedule 28.06.2014
comment
Но разве все они не вызваны в одном потоке? Возможно, я ошибался, думая об этом. - person dcow; 14.07.2014

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)
        }
    }

}

Использование:


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()
}
person NickUnuchek    schedule 09.09.2019