web-dev-qa-db-ja.com

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

しかし、時々タイトルにエラーが表示されることがあります。unbindService()が呼び出されたときに_Java.lang.IllegalArgumentException: Service not registered_が生成されます。私は愚かな何かを見逃していますか、それとももっと起こっていますか?この同じフラグメントが複数存在する可能性があることに注意してください。

編集

実際に誰もコードを読んでいないようですので、説明させてください。 unbindService()は、サービスがバインドされていない限り、Context.unbindService(ServiceConnection)を呼び出しません(mBoundandonServiceDisconnected(...)コールバックは、unbindService()の以前の呼び出しからヒットしました。

そのことを念頭に置いて、Androidがサービスをアンバインドし、サービスがバインドされなくなりますが、onServiceDisconnectedが呼び出されず、古い状態のままになりますか?

また、アプリケーションコンテキストを使用して初期バインディングを実行しています。次のようなものと仮定します。

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

この質問はすでに回答されています。しかし、なぜ人々がこの間違いを犯しているのかを説明する理由があると思います。

問題は、実際にトレーニングドキュメントにあります。 http://developer.Android.com/reference/Android/app/Service.html は正しい実装を示していますが、 https://developer.Android.com/guide/components/bound -services.html 'ActivityMessenger'のVery[〜#〜] incorrect [〜#〜]実装を示しています。

「ActivityMessenger」の例では、サービスが実際にバインドされる前にonStop()が呼び出される可能性があります。

この混乱の理由は、バインドされたサービスブールを使用して、さまざまな例でさまざまなことを意味しているためです。 (主に、ORは実際に接続されているサービスです)と呼ばれるbindService()でした)

バインドされたブール値に基づいてunbind()が実行される正しい例では、バインドされたブール値はbindService()が呼び出されたことを示します。メインスレッドの実行のためにキューに入れられているため、onServiceConnected()がいつ発生するかに関係なく、unbindService()を呼び出す(実行するためにキューに入れる)必要があります。

http://developer.Android.com/reference/Android/app/Service.html のような他の例では。バインドは、NullPointerExceptionを取得せずに使用できるように、サービスが実際にバインドされていることを示します。この例では、unbindService()呼び出しが引き続き行われ、boundブール値は、アンバインドするかどうかを決定しないことに注意してください

16
aaronvargas

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 で行われる方法です。

25
Jacob Phillips

_Java.lang.IllegalArgumentException: Service not registered_は、unbindService()が呼び出されたときにサービスにバインドされなかったことを意味します。

したがって、あなたの場合、onSomeEvent()内のunbindService()を呼び出す前にonPause()が呼び出されることはありませんでした

8
pelotasplus

この例外の別の考えられる理由は、unbindServiceが間違ったContextによって呼び出されていることです。サービスはアクティビティだけでなく、Contextによって継承された他のインスタンス(BroadcastReceiversを除く)、他のサービスによってもバインドできるため、unbindServiceがコンテキストによって呼び出されることを確認してくださいバインドされたService自体ではなく、Serviceをバインドしています。これにより、上記の例外「サービスが登録されていません」が直接発生します。

理由?

アクティビティで、bindService()の前にunbindService()が呼び出されると、この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公式ドキュメント suggests that
アクティビティがvisibleのときにのみサービスと対話する必要がある場合は、Solution1を使用します。
アクティビティがbackgroundで停止している場合でも応答を受信する場合は、Solution2を使用します。

0
Rohit Singh

私のアプリケーションにもまったく同じ問題があります。たまにIllegalArgumentExceptionを取得します。サービスがバインドされておらず、onPausebeforeonServiceDisconnectedと呼ばれているときに、特殊なケースが発生すると思います。そこで、Synchronizedを試して、正しく実行されるようにします。

0
slott