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;/**
* @ClassName : ServiceBindHelper.java
* @Function : 服务绑定助手
* @Description :
* @Idea :
* {@link }
* @Encourage :Do everything you can right now, and then decide.
* 全力以赴,历而后择。
* @date : 2021/8/30
*/
public class ServiceBindHelper {
private static final String TAG ="ServiceBindHelper";// 绑定策略
private BindPolicy mBindPolicy;
private Intent mIntent;
private final Context mContext;// 服务连接
private ServiceConnection mUserCallback;// MSG 重试绑定服务
private static final int MSG_RETRY_BIND_SERVICE =201;/**
* The constant STATE_DISCONNECTED.
* 常量 STATE_DISCONNECTED
*/
public static final int STATE_DISCONNECTED =0;/**
* The constant STATE_CONNECTING.
* 常量 STATE_CONNECTING
*/
public static final int STATE_CONNECTING =1;/**
* The constant STATE_CONNECTED.
* 常量 STATE_CONNECTED
*/
public static final int STATE_CONNECTED =2;/**
* The constant STATE_RETRYING.
* 常量 STATE_RETRYING
*/
public static final int STATE_RETRYING =3;//连接状态
private int mConnectionState;//重试次数
private int mRetryCount;
private Handler mHandler;//服务连接
private final ServiceConnection mServiceConnection = new ServiceConnection(){
@Override
public voidonServiceConnected(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);}}/**
* 在服务断开时
* @param name 组件名称
*/
@Override
public voidonServiceDisconnected(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.
* 实例化一个新的 Service 绑定助手
* @param context the context 上下文环境
* @param userCallback the user callback
*/
public ServiceBindHelper(Context context,
ServiceConnection userCallback){// DefaultBindPolicy :默认绑定策略this(context, userCallback, new DefaultBindPolicy());}/**
* Instantiates a new Service bind helper.
* 实例化一个新的 Service 绑定助手
* @param context the context
* @param userCallback the user callback
* @param bindPolicy the bind policy
*/
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 voidinitHandler(){if(mHandler == null){
mHandler = new Handler(mContext.getMainLooper()){
@Override
public voidhandleMessage(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
*/
public voidbind(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();}}/**
* Unbind.
* 解绑
*/
public voidunbind(){
mHandler.removeCallbacksAndMessages(null);
mContext.unbindService(mServiceConnection);
mConnectionState = STATE_DISCONNECTED;
mIntent = null;}/**
* 请求自动重新绑定
*/
private voidrequestAutoReBind(){
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());}}/**
* 重新绑定
* @return 链接状态 - ture 断开状态 - false
*/
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;}/**
* Gets connection state.
* 获取连接状态
* @return the connection state 连接状态
*/
public intgetConnectionState(){return mConnectionState;}/**
* The type Bind policy.
* 类型绑定策略
*/
public abstract static class BindPolicy {/**
* Gets re bind interval.
*
* @return the re bind interval
*/
public abstract longgetReBindInterval();/**
* Gets bind flags.
*
* @return the bind flags
*/
public abstract intgetBindFlags();/**
* Is auto re bind boolean.
*
* @return the boolean
*/
public abstract boolean isAutoReBind();/**
* Gets retry limit.
*
* @return the retry limit
*/
public abstract intgetRetryLimit();}/**
* The type Default bind policy.
*/
public static class DefaultBindPolicy extends BindPolicy {/**
* The constant RETRY_LIMIT.
*/
public static final int RETRY_LIMIT =3;
private static final int RETRY_INTERVAL =2000;
@Override
public longgetReBindInterval(){return RETRY_INTERVAL;}
@Override
public intgetBindFlags(){return Context.BIND_AUTO_CREATE;}
@Override
public boolean isAutoReBind(){return true;}
@Override
public intgetRetryLimit(){return RETRY_LIMIT;}}}
二、实战使用
public class Test {
private final Context mContext;
private ServiceBindHelper mServiceBindHelper;...
private final ServiceConnection mServiceConnection = new ServiceConnection(){
@Override
public voidonServiceConnected(ComponentName name, IBinder service){
Log.d(TAG,"onServiceConnected() called with: name = ["+ name +"], service = ["+ service +"]");}
@Override
public voidonServiceDisconnected(ComponentName name){
Log.d(TAG,"onServiceDisconnected() called with: name = ["+ name +"]");}};
private voidbind(){
mServiceBindHelper = new ServiceBindHelper(mContext,mServiceConnection);
Intent intent = new Intent();
intent.setAction(..);
intent.setComponent(new ComponentName(...,...));
mServiceBindHelper.bind(intent);}
public voiddestory(){
Log.d(TAG,"destory() called");
mServiceBindHelper.unbind();
mServiceBindHelper = null;
sInstance = null;}....}