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.html shows a correct implementation while https://developer.android.com/guide/components/bound-services.html in the 'ActivityMessenger' shows a Very INCORRECT implementation.
In the 'ActivityMessenger' example onStop() could potentially be called before the service has actually been bound.
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)
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.
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.
-------------------Use mIsBound
inside doBindService()
and doUnbindService()
instead of in the ServiceConnection
instance.
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
-------------------java.lang.IllegalArgumentException: Service not registered
means that you weren't bound to service when unbindService()
was called.
So in your case, onSomeEvent()
was never called before call to unbindService()
in onPause()
이 예외의 또 다른 가능한 이유 unbindService
는 잘못된 호출 일 수 있습니다 Context
. 서비스는 활동뿐 아니라 Context
다른 서비스에 의해 상속 된 다른 인스턴스 (BroadcastReceivers 제외)에 의해서도 unbindService
바인딩 Service
될 수 있으므로 바인딩 Service
자체가 아닌 바인딩 된 컨텍스트에 의해 호출되어야합니다 . 이 경우 위의 예외 "서비스가 등록되지 않음"이 직접 발생합니다.
이유?
Activity에서 unbindService ()가 bindService () 전에 호출되면 this 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);
}
}
관련 링크 :
안드로이드 공식 문서가 제안 하는 것이
이 서비스와 상호 작용이 필요한 경우 활동이있는 동안 만 볼 수 다음으로 이동 Solution1 . 백그라운드
에서 중지 된 상태에서도 활동이 응답을 받도록하려면 Solution2 로 이동하십시오 .
제 경우에는 bindService를 사용하여 호출 Activity Context
하고 ApplicationContext
. 하지마.
내 응용 프로그램과 똑같은 문제가 있습니다. 때때로 나는 IllegalArgumentException
. 서비스가 바인딩 해제되고 이전onPause
에 호출 될 때 특별한 경우가 발생한다고 생각합니다 . 그래서 나는 올바른 실행을 보장하기 위해 노력할 것입니다. onServiceDisconnected
Synchronized
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()
}
출처
https://stackoverflow.com/questions/22080054