一、自动重连工具类
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
public class ServiceBindHelper {
private static final String TAG = "ServiceBindHelper";
private BindPolicy mBindPolicy;
private Intent mIntent;
private final Context mContext;
private ServiceConnection mUserCallback;
private static final int MSG_RETRY_BIND_SERVICE = 201;
public static final int STATE_DISCONNECTED = 0;
public static final int STATE_CONNECTING = 1;
public static final int STATE_CONNECTED = 2;
public static final int STATE_RETRYING = 3;
private int mConnectionState;
private int mRetryCount;
private Handler mHandler;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected() called with: name = [" + name + "], service = [" + service + "]");
if (mConnectionState != STATE_CONNECTED) {
mConnectionState = STATE_CONNECTED;
mUserCallback.onServiceConnected(name, service);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected() called with: name = [" + name + "]");
mUserCallback.onServiceDisconnected(name);
mContext.unbindService(mServiceConnection);
mConnectionState = STATE_DISCONNECTED;
requestAutoReBind();
}
};
public ServiceBindHelper(Context context,
ServiceConnection userCallback) {
this(context, userCallback, new DefaultBindPolicy());
}
public ServiceBindHelper(Context context, ServiceConnection userCallback,
BindPolicy bindPolicy) {
Log.d(TAG, "ServiceBindHelper() called with: context = [" + context + "], userCallback = [" + userCallback
+ "], bindPolicy = [" + bindPolicy + "]");
if (context == null) {
throw new NullPointerException("context is null");
}
if (userCallback == null) {
throw new NullPointerException("userCallback is null");
}
if (bindPolicy == null) {
throw new NullPointerException("bindPolicy is null");
}
mContext = context;
mUserCallback = userCallback;
mBindPolicy = bindPolicy;
initHandler();
}
private void initHandler() {
if (mHandler == null) {
mHandler = new Handler(mContext.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_RETRY_BIND_SERVICE:
if (reBind()) {
mRetryCount = 0;
} else {
mRetryCount++;
requestAutoReBind();
}
break;
default:
break;
}
}
};
}
}
public void bind(Intent intent) {
Log.d(TAG, "bind() called with: intent = [" + intent + "]");
if (intent == null) {
throw new NullPointerException("intent is null");
}
if (mConnectionState != STATE_DISCONNECTED) {
Log.e(TAG, "bind: isBinding");
return;
}
mConnectionState = STATE_CONNECTING;
mIntent = intent;
boolean bindRes = mContext.bindService(intent, mServiceConnection, mBindPolicy.getBindFlags());
if (!bindRes) {
requestAutoReBind();
}
}
public void unbind() {
mHandler.removeCallbacksAndMessages(null);
mContext.unbindService(mServiceConnection);
mConnectionState = STATE_DISCONNECTED;
mIntent = null;
}
private void requestAutoReBind() {
Log.d(TAG, "requestAutoReBind() called");
if (mBindPolicy.isAutoReBind() && mRetryCount < mBindPolicy.getRetryLimit()) {
if (mHandler.hasMessages(MSG_RETRY_BIND_SERVICE)) {
mHandler.removeMessages(MSG_RETRY_BIND_SERVICE);
}
mHandler.sendEmptyMessageDelayed(MSG_RETRY_BIND_SERVICE,
mBindPolicy.getReBindInterval());
}
}
private boolean reBind() {
Log.d(TAG, "reBind() called");
if (mConnectionState == STATE_CONNECTED) {
return true;
}
mConnectionState = STATE_RETRYING;
boolean bindRes = mContext.bindService(mIntent, mServiceConnection, mBindPolicy.getBindFlags());
Log.d(TAG, "reBind() returned: " + bindRes);
return false;
}
public int getConnectionState() {
return mConnectionState;
}
public abstract static class BindPolicy {
public abstract long getReBindInterval();
public abstract int getBindFlags();
public abstract boolean isAutoReBind();
public abstract int getRetryLimit();
}
public static class DefaultBindPolicy extends BindPolicy {
public static final int RETRY_LIMIT = 3;
private static final int RETRY_INTERVAL = 2000;
@Override
public long getReBindInterval() {
return RETRY_INTERVAL;
}
@Override
public int getBindFlags() {
return Context.BIND_AUTO_CREATE;
}
@Override
public boolean isAutoReBind() {
return true;
}
@Override
public int getRetryLimit() {
return RETRY_LIMIT;
}
}
}
二、实战使用
public class Test {
private final Context mContext;
private ServiceBindHelper mServiceBindHelper;
...
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected() called with: name = [" + name + "], service = [" + service + "]");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected() called with: name = [" + name + "]");
}
};
private void bind() {
mServiceBindHelper = new ServiceBindHelper(mContext,mServiceConnection);
Intent intent = new Intent();
intent.setAction(..);
intent.setComponent(new ComponentName(..., ...));
mServiceBindHelper.bind(intent);
}
public void destory() {
Log.d(TAG, "destory() called");
mServiceBindHelper.unbind();
mServiceBindHelper = null;
sInstance = null;
}
....
}
|