-
-
Save tonykwok/634ec184de03deb2804a6ea833f1e3e4 to your computer and use it in GitHub Desktop.
Android service bind helper class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.ComponentName; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.content.ServiceConnection; | |
import android.os.IBinder; | |
import android.support.annotation.Nullable; | |
/** | |
* This class based on official | |
* <a href="http://developer.android.com/guide/components/bound-services.html">documentation</a> | |
* and <a href="http://stackoverflow.com/questions/26127129/doubts-about-bindservice">this discussion</a>. | |
* <p>This class is a simple service bind helper, that controls state of binding and | |
* determines when {@link Context#bindService} or {@link Context#unbindService} should be actually called. | |
* <p>This class is not thread-safe and intended to be used in main thread only. | |
*/ | |
public abstract class ServiceBindHelper<T> { | |
private final Context mContext; | |
private final ServiceConnection mServConn = new ServiceConnectionImpl(); | |
private State mState = State.NONE; | |
private T mService; | |
public ServiceBindHelper(Context context) { | |
this.mContext = context; | |
} | |
/** | |
* @return Intent, used to bind a service | |
*/ | |
protected abstract Intent createBindIntent(); | |
/** | |
* This method is called when the service successfully connected. | |
* @param name | |
* @param service | |
* @return object of type <code>T</code>, representing usable service itself. | |
*/ | |
protected abstract T onServiceConnected(ComponentName name, IBinder service); | |
/** | |
* This method is called only in case of an accident, for example, when the service was killed by OS. | |
*/ | |
protected void onServiceDisconnected(ComponentName name) { | |
} | |
@Nullable | |
public T getService() { | |
return mService; | |
} | |
public final void bind() { | |
if (mState == State.BINDING || mState == State.CONNECTED) { | |
return; | |
} | |
if (mState == State.DISCONNECTED) { | |
// in case of accident with the service we should unbind first. | |
unbind(); | |
} | |
mState = State.BINDING; | |
mContext.bindService(createBindIntent(), mServConn, Context.BIND_AUTO_CREATE); | |
} | |
public final void unbind() { | |
if (mState == State.NONE || mState == State.UNBOUND) { | |
return; | |
} | |
mState = State.UNBOUND; | |
mService = null; | |
mContext.unbindService(mServConn); | |
} | |
private enum State { | |
NONE, | |
BINDING, | |
CONNECTED, | |
UNBOUND, | |
DISCONNECTED // extreme situation | |
} | |
private class ServiceConnectionImpl implements ServiceConnection { | |
@Override | |
public void onServiceConnected(ComponentName name, IBinder service) { | |
mState = State.CONNECTED; | |
mService = ServiceBindHelper.this.onServiceConnected(name, service); | |
} | |
@Override | |
public void onServiceDisconnected(ComponentName name) { | |
// Text from official documentation (link is above in class description): | |
// The Android system calls this when the connection to the service is unexpectedly lost, | |
// such as when the service has crashed or has been killed. This is not called when the client unbinds. | |
mState = State.DISCONNECTED; | |
mService = null; | |
ServiceBindHelper.this.onServiceDisconnected(name); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment