Android java.ленг.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();
}

5 ответов


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

проблема действительно в учебных документах. http://developer.android.com/reference/android/app/Service.html показывает правильную реализацию в то время как https://developer.android.com/guide/components/bound-services.html в "ActivityMessenger" показывает очень неправильно реализация.

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

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

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

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


использовать 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;
    }
}

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


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

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


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


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