importandroid.content.ComponentName;importandroid.content.Context;importandroid.content.Intent;importandroid.content.ServiceConnection;importandroid.os.Handler;importandroid.os.IBinder;importandroid.os.Message;importandroid.util.Log;/**
* The type Service bind helper.
*/publicclassServiceBindHelper{privatestaticfinalString TAG ="ServiceBindHelper";privateBindPolicy mBindPolicy;privateIntent mIntent;privatefinalContext mContext;privateServiceConnection mUserCallback;privatestaticfinalint MSG_RETRY_BIND_SERVICE =201;/**
* The constant STATE_DISCONNECTED.
*/publicstaticfinalint STATE_DISCONNECTED =0;/**
* The constant STATE_CONNECTING.
*/publicstaticfinalint STATE_CONNECTING =1;/**
* The constant STATE_CONNECTED.
*/publicstaticfinalint STATE_CONNECTED =2;/**
* The constant STATE_RETRYING.
*/publicstaticfinalint STATE_RETRYING =3;privateint mConnectionState;privateint mRetryCount;privateHandler mHandler;privatefinalServiceConnection mServiceConnection =newServiceConnection(){@OverridepublicvoidonServiceConnected(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);}}@OverridepublicvoidonServiceDisconnected(ComponentName name){Log.d(TAG,"onServiceDisconnected() called with: name = ["+ name +"]");
mUserCallback.onServiceDisconnected(name);
mContext.unbindService(mServiceConnection);
mConnectionState = STATE_DISCONNECTED;requestAutoReBind();}};/**
* Instantiates a new Service bind helper.
*
* @param context the context
* @param userCallback the user callback
*/publicServiceBindHelper(Context context,ServiceConnection userCallback){this(context, userCallback,newDefaultBindPolicy());}/**
* Instantiates a new Service bind helper.
*
* @param context the context
* @param userCallback the user callback
* @param bindPolicy the bind policy
*/publicServiceBindHelper(Context context,ServiceConnection userCallback,BindPolicy bindPolicy){Log.d(TAG,"ServiceBindHelper() called with: context = ["+ context +"], userCallback = ["+ userCallback
+"], bindPolicy = ["+ bindPolicy +"]");if(context ==null){thrownewNullPointerException("context is null");}if(userCallback ==null){thrownewNullPointerException("userCallback is null");}if(bindPolicy ==null){thrownewNullPointerException("bindPolicy is null");}
mContext = context;
mUserCallback = userCallback;
mBindPolicy = bindPolicy;initHandler();}privatevoidinitHandler(){if(mHandler ==null){
mHandler =newHandler(mContext.getMainLooper()){@OverridepublicvoidhandleMessage(Message msg){super.handleMessage(msg);switch(msg.what){case MSG_RETRY_BIND_SERVICE:if(reBind()){
mRetryCount =0;}else{
mRetryCount++;requestAutoReBind();}break;default:break;}}};}}/**
* Bind.
*
* @param intent the intent
*/publicvoidbind(Intent intent){Log.d(TAG,"bind() called with: intent = ["+ intent +"]");if(intent ==null){thrownewNullPointerException("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();}}/**
* Unbind.
*/publicvoidunbind(){
mHandler.removeCallbacksAndMessages(null);
mContext.unbindService(mServiceConnection);
mConnectionState = STATE_DISCONNECTED;
mIntent =null;}privatevoidrequestAutoReBind(){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());}}privatebooleanreBind(){Log.d(TAG,"reBind() called");if(mConnectionState == STATE_CONNECTED){returntrue;}
mConnectionState = STATE_RETRYING;boolean bindRes = mContext.bindService(mIntent, mServiceConnection, mBindPolicy.getBindFlags());Log.d(TAG,"reBind() returned: "+ bindRes);returnfalse;}/**
* Gets connection state.
*
* @return the connection state
*/publicintgetConnectionState(){return mConnectionState;}/**
* The type Bind policy.
*/publicabstractstaticclassBindPolicy{/**
* Gets re bind interval.
*
* @return the re bind interval
*/publicabstractlonggetReBindInterval();/**
* Gets bind flags.
*
* @return the bind flags
*/publicabstractintgetBindFlags();/**
* Is auto re bind boolean.
*
* @return the boolean
*/publicabstractbooleanisAutoReBind();/**
* Gets retry limit.
*
* @return the retry limit
*/publicabstractintgetRetryLimit();}/**
* The type Default bind policy.
*/publicstaticclassDefaultBindPolicyextendsBindPolicy{/**
* The constant RETRY_LIMIT.
*/publicstaticfinalint RETRY_LIMIT =3;privatestaticfinalint RETRY_INTERVAL =2000;@OverridepubliclonggetReBindInterval(){return RETRY_INTERVAL;}@OverridepublicintgetBindFlags(){returnContext.BIND_AUTO_CREATE;}@OverridepublicbooleanisAutoReBind(){returntrue;}@OverridepublicintgetRetryLimit(){return RETRY_LIMIT;}}}
使用DEMO
publicclassTest{privatefinalContext mContext;privateServiceBindHelper mServiceBindHelper;...privatefinalServiceConnection mServiceConnection =newServiceConnection(){@OverridepublicvoidonServiceConnected(ComponentName name,IBinder service){Log.d(TAG,"onServiceConnected() called with: name = ["+ name +"], service = ["+ service +"]");}@OverridepublicvoidonServiceDisconnected(ComponentName name){Log.d(TAG,"onServiceDisconnected() called with: name = ["+ name +"]");}};privatevoidbind(){
mServiceBindHelper =newServiceBindHelper(mContext,mServiceConnection);Intent intent =newIntent();
intent.setAction(..);
intent.setComponent(newComponentName(...,...));
mServiceBindHelper.bind(intent);}publicvoiddestory(){Log.d(TAG,"destory() called");
mServiceBindHelper.unbind();
mServiceBindHelper =null;
sInstance =null;}....}