Skip to content

Instantly share code, notes, and snippets.

@attacco
Created January 4, 2016 22:44
Show Gist options
  • Save attacco/987c55556a2275f62a16 to your computer and use it in GitHub Desktop.
Save attacco/987c55556a2275f62a16 to your computer and use it in GitHub Desktop.
Android service bind helper class
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