android端 socket长连接 架构
生活随笔
收集整理的這篇文章主要介紹了
android端 socket长连接 架构
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
看過包建強的《App研發錄》之后對其中的基礎Activity類封裝感到驚訝,一直想找一種方式去解決關于app中使用socket長連接問題,如何實現簡易的封裝來達到主活動中涉及socket相關的代碼量少的效果。正常的實現socket的基本方式都是新建一個Socket服務,在活動中綁定服務和注冊全局廣播,通過綁定服務中的函數去發送數據,通過全局廣播去接收數據。如果每個活動中都去寫綁定服務和注冊全局廣播等內容就會造成一大堆的代碼冗余且主活動中的其他業務不是很突出,故我借用包建強書中的相關封裝方式,新建了一個SocketBaseActivity類,去實現綁定服務與注冊全局廣播的內容,其中將全局廣播接收器中的接收函數做抽象,在主活動繼承SocketBaseActivity,在初始化時,實例化接收器中的接收函數,如果不實例化則不會進行綁定服務和注冊廣播操作,如果需要發送則掉父類中相關變量的發送函數即可。
下面是具體實現細節:
SocketService類
package com.splxtech.powermanagor.engine;import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.support.v4.content.LocalBroadcastManager; import android.util.Log;import com.splxtech.powermanagor.IBackService;import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.ref.WeakReference; import java.net.Socket; import java.net.UnknownHostException; import java.util.Arrays;/*** Created by li300 on 2016/10/7 0007.*/public class SocketService extends Service {private static final String TAG = "BackService";//心跳包頻率private static final long HEART_BEAT_RATE = 30 * 1000;public static final String HOST = "192.168.0.102";// // public static final int PORT = 51001;public static final String MESSAGE_ACTION="com.splxtech.powermanagor.engine.socket";public static final String HEART_BEAT_ACTION="com.splxtech.powermanagor.engine.socket.heart";public static final String HEART_BEAT_STRING="00";//心跳包內容private ReadThread mReadThread;private LocalBroadcastManager mLocalBroadcastManager;private WeakReference<Socket> mSocket;// For heart Beatprivate Handler mHandler = new Handler();private Runnable heartBeatRunnable = new Runnable() {@Overridepublic void run() {if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {boolean isSuccess = sendMsg(HEART_BEAT_STRING);//就發送一個HEART_BEAT_STRING過去 如果發送失敗,就重新初始化一個socketif (!isSuccess) {mHandler.removeCallbacks(heartBeatRunnable);mReadThread.release();releaseLastSocket(mSocket);new InitSocketThread().start();}}mHandler.postDelayed(this, HEART_BEAT_RATE);}};private long sendTime = 0L;private IBackService.Stub iBackService = new IBackService.Stub() {@Overridepublic boolean sendMessage(String message) throws RemoteException {return sendMsg(message);}};@Overridepublic IBinder onBind(Intent arg0) {return iBackService;}@Overridepublic void onCreate() {super.onCreate();new InitSocketThread().start();mLocalBroadcastManager=LocalBroadcastManager.getInstance(this);}public boolean sendMsg(String msg) {if (null == mSocket || null == mSocket.get()) {return false;}Socket soc = mSocket.get();try {if (!soc.isClosed() && !soc.isOutputShutdown()) {OutputStream os = soc.getOutputStream();String message = msg;os.write(message.getBytes());os.flush();sendTime = System.currentTimeMillis();//每次發送成數據,就改一下最后成功發送的時間,節省心跳間隔時間} else {return false;}} catch (IOException e) {e.printStackTrace();return false;}return true;}private void initSocket() {//初始化Sockettry {Socket so = new Socket(HOST, PORT);mSocket = new WeakReference<Socket>(so);mReadThread = new ReadThread(so);mReadThread.start();mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//初始化成功后,就準備發送心跳包} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}private void releaseLastSocket(WeakReference<Socket> mSocket) {try {if (null != mSocket) {Socket sk = mSocket.get();if (!sk.isClosed()) {sk.close();}sk = null;mSocket = null;}} catch (IOException e) {e.printStackTrace();}}class InitSocketThread extends Thread {@Overridepublic void run() {super.run();initSocket();}}// Thread to read content from Socketclass ReadThread extends Thread {private WeakReference<Socket> mWeakSocket;private boolean isStart = true;public ReadThread(Socket socket) {mWeakSocket = new WeakReference<Socket>(socket);}public void release() {isStart = false;releaseLastSocket(mWeakSocket);}@Overridepublic void run() {super.run();Socket socket = mWeakSocket.get();if (null != socket) {try {InputStream is = socket.getInputStream();byte[] buffer = new byte[1024 * 4];int length = 0;while (!socket.isClosed() && !socket.isInputShutdown()&& isStart && ((length = is.read(buffer)) != -1)) {if (length > 0) {String message = new String(Arrays.copyOf(buffer,length)).trim();Log.e(TAG, message);//收到服務器過來的消息,就通過Broadcast發送出去if(message.equals(HEART_BEAT_STRING)){//處理心跳回復Intent intent=new Intent(HEART_BEAT_ACTION);mLocalBroadcastManager.sendBroadcast(intent);}else{//其他消息回復Intent intent=new Intent(MESSAGE_ACTION);intent.putExtra("message", message);mLocalBroadcastManager.sendBroadcast(intent);}}}} catch (IOException e) {e.printStackTrace();}}}} }?上面有一個IBackService.aidl文件:
// IBackService.aidl package com.splxtech.powermanagor;// Declare any non-default types here with import statementsinterface IBackService {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/boolean sendMessage(String message); }下面是SocketBaseActivity類中的內容:
package com.splxtech.powermanagor.Base;import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.os.IBinder; import android.support.v4.content.LocalBroadcastManager;import com.splxtech.powermanagor.IBackService; import com.splxtech.powermanagor.engine.SocketService; import com.splxtech.splxapplib.activity.BaseActivity;/*** Created by li300 on 2016/10/7 0007.*/public abstract class SocketBaseActivity extends BaseActivity {//子類中完成抽象函數賦值//實體中通過實現該全局接收器方法來處理接收到消息public MessageBackReciver mReciver;private IntentFilter mIntentFilter;private Intent mServiceIntent;private LocalBroadcastManager localBroadcastManager;//通過調用該接口中的方法來實現數據發送public IBackService iBackService;//標記是否已經進行了服務綁定與全局消息注冊private boolean flag;private ServiceConnection conn = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {iBackService = IBackService.Stub.asInterface(iBinder);}@Overridepublic void onServiceDisconnected(ComponentName componentName) {iBackService = null;}};@Overridepublic void onStart(){flag = false;if(mReciver!=null){flag = true;initSocket();localBroadcastManager.registerReceiver(mReciver,mIntentFilter);bindService(mServiceIntent,conn,BIND_ABOVE_CLIENT);}super.onStart();}@Overridepublic void onDestroy(){if(flag==true) {unbindService(conn);localBroadcastManager.unregisterReceiver(mReciver);}super.onDestroy();}public void initSocket(){localBroadcastManager = LocalBroadcastManager.getInstance(this);//mReciver = new MessageBackReciver();mServiceIntent = new Intent(this,SocketService.class);mIntentFilter = new IntentFilter();mIntentFilter.addAction(SocketService.HEART_BEAT_ACTION);mIntentFilter.addAction(SocketService.MESSAGE_ACTION);}public abstract class MessageBackReciver extends BroadcastReceiver{@Overridepublic abstract void onReceive(Context context, Intent intent);} }在主activity中如何使用:
package com.splxtech.powermanagor.activity.dqjc;import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ListView;import com.splxtech.powermanagor.Base.SocketBaseActivity; import com.splxtech.powermanagor.R; import com.splxtech.powermanagor.adapter.DqItemAdapter; import com.splxtech.powermanagor.engine.SocketService; import com.splxtech.powermanagor.entity.Appliance; import com.splxtech.powermanagor.utils.Utils; import com.splxtech.splxapplib.activity.BaseActivity;import java.util.ArrayList;/*** Created by li300 on 2016/10/6 0006.*/public class DqActivity extends SocketBaseActivity {@Overrideprotected void initVariables(){//給全局消息接收器賦值,并進行消息處理mReciver = new MessageBackReciver(){@Overridepublic void onReceive(Context context, Intent intent){String action = intent.getAction();if(action.equals(SocketService.HEART_BEAT_ACTION)){Utils.toastShow(baseActivity,"Get a heart heat");}else{String message = intent.getStringExtra("message");}}};}@Overrideprotected void initViews(Bundle savedInstanceState){}@Overridepublic void loadData(){} }?
總結
以上是生活随笔為你收集整理的android端 socket长连接 架构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设置Eclipse的workspace路
- 下一篇: 虚拟存储器i