SocketService.java 11.9 KB
package com.qnbar.smc.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import com.gimi.common.cinema.model.MessageEvent;
import com.gimi.common.cinema.utils.SystemUtils;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.xgimi.gimicinema.BuildConfig;
import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.net.Socket;
import java.util.Arrays;

public class SocketService extends Service {
    private static final String TAG = "BackService";
    private static final long HEART_BEAT_RATE = 10 * 1000;

    public static final int OPEN_DOOR_CMD = 1701;

    private static final int SUCESS_MESSAGE = 0;
    private static final int ROOM_HAS_REGISTERED = 1001;
    private static final int ROOM_NOT_EXIST_M = 1002;
    private static final int HEAT_BEAT_RTN = 1003;

    public static final String HOST = "121.43.189.162";// "192.168.1.21";//
    public static final int PORT = 9501;

    public static final String END_SYMBOL = "\\r\\n\\r\\n";//心跳包内容
    public String testRoomSn = "000003";

    private ReadThread mReadThread;
    private HeatBeatThread mHeatBeatThread;
    private Gson gson;

//    private LocalBroadcastManager mLocalBroadcastManager;

    private WeakReference<Socket> mSocket;

    // For heart Beat
//    private Handler mHandler = new Handler();
//    private Runnable heartBeatRunnable = new Runnable() {
//
//        @Override
//        public void run() {
//            if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
//                Log.d(TAG, "heart beat");
//                boolean isSuccess = sendMsg(new Gson().toJson(new SocketSendMsg().contractHeartBeatMsg(testRoomSn)) + END_SYMBOL);//就发送一个HEART_BEAT_STRING过去 如果发送失败,就重新初始化一个socket
//                if (!isSuccess) {
//                    Log.d(TAG, "heart beat error restart");
//                    mHandler.removeCallbacks(heartBeatRunnable);
//                    mReadThread.release();
//                    mHeatBeatThread.release();
//                    releaseLastSocket(mSocket);
//                    new InitSocketThread().start();
//                }
//            } else {
//                Log.d(TAG, "heart beat less than beat rate");
//            }
//            mHandler.postDelayed(this, HEART_BEAT_RATE);
//        }
//    };

    private long sendTime = 0L;
    private Context context;

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        gson = new Gson();
        context = this;
        //TODO change the room sn
        if (!"LETEST".equals(SystemUtils.getPid(context, BuildConfig.MACHINE_TYPE))) {
            testRoomSn = "000002";
        }
        new InitSocketThread().start();
        Log.d(TAG, "socket service onCreate");
    }

    public boolean sendMsg(String msg) {
        if (null == mSocket || null == mSocket.get()) {
            return false;
        }
        Log.d(TAG, "send msg:" + msg);
        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() throws IOException {//初始化Socket
        Socket so = new Socket(HOST, PORT);
        mSocket = new WeakReference<Socket>(so);
        mReadThread = new ReadThread(so);
        mReadThread.start();
//            new Thread(heartBeatRunnable).start();
//            mHandler.post(heartBeatRunnable);//初始化成功后,就准备发送心跳包
        mHeatBeatThread = new HeatBeatThread(so);
        mHeatBeatThread.start();//上面的 one plus 3t NetworkOnMainThreadException!!!
    }

    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 {
        @Override
        public void run() {
            super.run();
            try {
                initSocket();
            } catch (IOException e) {
                e.printStackTrace();
                Log.d(TAG, "init socket thread error,restart again after 10's");
                try {
                    Thread.sleep(HEART_BEAT_RATE);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
                this.run();
            }
        }
    }

    // Thread to read content from Socket
    class 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);
        }

        @Override
        public void run() {
            super.run();
            Socket socket = mWeakSocket.get();
            if (null != socket) {
                try {
                    if (!sendRegister) {
                        Log.d(TAG, "send register mes");
                        SocketSendMsg ssm = new SocketSendMsg().contractRegisterMsg(testRoomSn);
                        String msg = gson.toJson(ssm) + END_SYMBOL;
                        sendMsg(msg);
                        Log.d(TAG, "" + msg);
                        sendRegister = true;
                    }
                    Log.d(TAG, "send register mes end");
                    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.d(TAG, "end:" + message.contains(END_SYMBOL) + "");
                            Log.d(TAG, "recv msg:" + message);
                            try {
                                SocketResponse socketResponse = gson.fromJson(message.trim(), SocketResponse.class);
                                switch (socketResponse.getCode()) {
                                    case SUCESS_MESSAGE:
                                        Log.d(TAG, "success:" + socketResponse.getCmd());
                                        break;
                                    case ROOM_HAS_REGISTERED:
                                        SocketSendMsg ssm = new SocketSendMsg().contractReconnectMsg(testRoomSn);
                                        String msg = gson.toJson(ssm) + END_SYMBOL;
                                        sendMsg(msg);
                                        Log.d(TAG, "send reconnect mes: " + msg);
                                        break;
                                    case ROOM_NOT_EXIST_M:
                                        Log.d(TAG, "re init socket");
                                        //sendRegister = false;
                                        releaseLastSocket(mWeakSocket);
                                        initSocket();
                                        break;
                                    case HEAT_BEAT_RTN:
                                        Log.d(TAG, "HEAT_BEAT_RTN");
                                        sendTime = System.currentTimeMillis();
                                        break;
                                }
                                if (("openDoor").equals(socketResponse.getCmd())) {
                                    MessageEvent messageEvent = new MessageEvent();
                                    messageEvent.setEventId(OPEN_DOOR_CMD);
                                    messageEvent.setMessage("click item");
                                    EventBus.getDefault().post(messageEvent);
                                }
                            } catch (JsonSyntaxException e) {
                                Log.d(TAG, message);
                                e.printStackTrace();
                            }
                            //收到服务器过来的消息,就通过Broadcast发送出去
//                            if (message.equals(END_SYMBOL)) {//处理心跳回复
//                                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();
                }
            }
        }
    }

    boolean sendRegister = false;


    // Thread to read content from Socket
    class HeatBeatThread extends Thread {
        private WeakReference<Socket> mWeakSocket;
        private boolean isStart = true;

        public HeatBeatThread(Socket socket) {
            mWeakSocket = new WeakReference<Socket>(socket);
        }

        public void release() {
            isStart = false;
            releaseLastSocket(mWeakSocket);
        }

        @Override
        public void run() {
            super.run();
            Socket socket = mWeakSocket.get();
            if (null != socket) {
                while (isStart) {
                    if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
                        Log.d(TAG, "heart beat:" + Thread.currentThread().getId());
                        boolean isSuccess = sendMsg(new Gson().toJson(new SocketSendMsg().contractHeartBeatMsg(testRoomSn)) + END_SYMBOL);//就发送一个HEART_BEAT_STRING过去 如果发送失败,就重新初始化一个socket
                        if (!isSuccess) {
                            Log.d(TAG, "heart beat error restart:" + Thread.currentThread().getId());
//                            mHandler.removeCallbacks(heartBeatRunnable);
                            mReadThread.release();
                            mHeatBeatThread.release();
                            sendRegister = false;
                            releaseLastSocket(mSocket);
                            new InitSocketThread().start();
                        }
                    } else {
                        Log.d(TAG, "heart beat less than beat rate:" + Thread.currentThread().getId());
                    }
                    try {
                        Thread.sleep(HEART_BEAT_RATE);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "socket service destroy");
    }
}