Service stopService() 시 onDestroy() 가 작동하지 않거나 원하는 타이밍에 작동하지 않는 경우
하드웨어 제어 서비스를 프로그래밍하면서 잘 작동하던 Service의 onDestroy() 메소드가 stopService() 실행에 바로 작동하지 않는 경우가 있어서 이를 남겨본다.
생명주기상 안드로이드의 Service는 startService 또는 bindingService로 Service를 시작할 수 있는데 이중에 bindingService시 flag를 어떤 것을 사용하는지 어디서 startService가 발현하는지에 따라서 다양한 경우가 발생했다.
이중에서 내 프로그램에서 원하는대로 (stopService실행시 onDestroy를 바로타는 것) 처리할 수 있는 것은 bindingService에서 사용하는 flag를 변경하여 원하는 결과를 얻었다.
// java code private void bindingCradle() { DLog.d(TAG, "bindingCradle()"); // 크레들과 바인딩 conn = new CradleServiceConnection(); startService(new Intent(BusinessActivity.this, CradleService.class)); bindService(new Intent(BusinessActivity.this, CradleService.class), conn, Context.BIND_AUTO_CREATE); }
문제가 된 부분은 'Context.BIND_AUTO_CREATE' 이 flag이다. 이를 Context.BIND_ADJUST_WITH_ACTIVITY 으로 변경한 것만으로 정상적으로 원하는 타이밍에 onDestroy() 가 정상적으로 작동하였다.
// java code private void bindingCradle() { DLog.d(TAG, "bindingCradle()"); // 크레들과 바인딩 conn = new CradleServiceConnection(); startService(new Intent(BusinessActivity.this, CradleService.class)); bindService(new Intent(BusinessActivity.this, CradleService.class), conn, Context.BIND_ADJUST_WITH_ACTIVITY); }
요렇게 말이다. 아래는 안드로이드 doc에서 발췌한 부분이다.
http://developer.android.com/reference/android/content/Context.html#BIND_ABOVE_CLIENT
public static final int BIND_ABOVE_CLIENT
Flag for bindService(Intent, ServiceConnection, int)
: indicates that the client application
binding to this service considers the service to be more important than
the app itself. When set, the platform will try to have the out of
memory killer kill the app before it kills the service it is bound to, though
this is not guaranteed to be the case.
public static final int BIND_ADJUST_WITH_ACTIVITY
Flag for bindService(Intent, ServiceConnection, int)
: If binding from an activity, allow the
target service's process importance to be raised based on whether the
activity is visible to the user, regardless whether another flag is
used to reduce the amount that the client process's overall importance
is used to impact it.
public static final int BIND_ALLOW_OOM_MANAGEMENT
Flag for bindService(Intent, ServiceConnection, int)
: allow the process hosting the bound
service to go through its normal memory management. It will be
treated more like a running service, allowing the system to
(temporarily) expunge the process if low on memory or for some other
whim it may have, and being more aggressive about making it a candidate
to be killed (and restarted) if running for a long time.
public static final int BIND_AUTO_CREATE
Flag for bindService(Intent, ServiceConnection, int)
: automatically create the service as long
as the binding exists. Note that while this will create the service,
its onStartCommand(Intent, int, int)
method will still only be called due to an
explicit call to startService(Intent)
. Even without that, though,
this still provides you with access to the service object while the
service is created.
Note that prior to ICE_CREAM_SANDWICH
,
not supplying this flag would also impact how important the system
consider's the target service's process to be. When set, the only way
for it to be raised was by binding from a service in which case it will
only be important when that activity is in the foreground. Now to
achieve this behavior you must explicitly supply the new flag
BIND_ADJUST_WITH_ACTIVITY
. For compatibility, old applications
that don't specify BIND_AUTO_CREATE
will automatically have
the flags BIND_WAIVE_PRIORITY
and
BIND_ADJUST_WITH_ACTIVITY
set for them in order to achieve
the same result.
public static final int BIND_DEBUG_UNBIND
Flag for bindService(Intent, ServiceConnection, int)
: include debugging help for mismatched
calls to unbind. When this flag is set, the callstack of the following
unbindService(ServiceConnection)
call is retained, to be printed if a later
incorrect unbind call is made. Note that doing this requires retaining
information about the binding that was made for the lifetime of the app,
resulting in a leak -- this should only be used for debugging.
public static final int BIND_IMPORTANT
Flag for bindService(Intent, ServiceConnection, int)
: this service is very important to
the client, so should be brought to the foreground process level
when the client is. Normally a process can only be raised to the
visibility level by a client, even if that client is in the foreground.
public static final int BIND_NOT_FOREGROUND
Flag for bindService(Intent, ServiceConnection, int)
: don't allow this binding to raise
the target service's process to the foreground scheduling priority.
It will still be raised to at least the same memory priority
as the client (so that its process will not be killable in any
situation where the client is not killable), but for CPU scheduling
purposes it may be left in the background. This only has an impact
in the situation where the binding client is a foreground process
and the target service is in a background process.
public static final int BIND_WAIVE_PRIORITY
Flag for bindService(Intent, ServiceConnection, int)
: don't impact the scheduling or
memory management priority of the target service's hosting process.
Allows the service's process to be managed on the background LRU list
just like a regular application process in the background.