Socket + 前台service

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/a136447572/article/details/87161581
package com.example.test;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;


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;

import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v4.content.LocalBroadcastManager;
import android.util.EventLog;
import android.util.Log;

import com.example.demo_play.R;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONException;
import org.json.JSONObject;

import static android.app.PendingIntent.getActivity;

/**
 * Created by dawish on 2017/7/24.
 * 由于移动设备的网络的复杂性,经常会出现网络断开,如果没有心跳包的检测,
 * 客户端只会在需要发送数据的时候才知道自己已经断线,会延误,甚至丢失服务器发送过来的数据。
 */

public class BackService extends Service {
    private static final String TAG = "info";
    /**
     * 心跳频率
     */
    private static final long HEART_BEAT_RATE = 3 * 1000;
    /**
     * 服务器ip地址
     */
    public static final String HOST = "192.168.1.21";// "192.168.1.21";//
    /**
     * 服务器端口号
     */
    public static final int PORT = 8080;
    /**
     * 服务器消息回复广播
     */
    public static final String MESSAGE_ACTION = "message_ACTION";
    /**
     * 服务器心跳回复广播
     */
    public static final String HEART_BEAT_ACTION = "heart_beat_ACTION";
    /**
     * 读线程
     */
    private ReadThread mReadThread;

    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) {

                try {
                    JSONObject json = new JSONObject();
                    json.put("a", "1");
                    json.put("b", "2");
                    json.put("c", "3");

                    boolean isSuccess = sendMsg(json.toString());//就发送一个\r\n过去 如果发送失败,就重新初始化一个socket
                    if (!isSuccess) {
                        mHandler.removeCallbacks(heartBeatRunnable);
                        mReadThread.release();
                        releaseLastSocket(mSocket);
                        new InitSocketThread().start();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            mHandler.postDelayed(this, HEART_BEAT_RATE);
        }
    };

    private Runnable LoginBeatRunnable = new Runnable() {

        @Override
        public void run() {
            if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {

                try {
                    JSONObject json = new JSONObject();
                    json.put("a", "1");
                    json.put("b", "2");
                    json.put("c", "3");

                    boolean isSuccess = sendMsg(json.toString());//就发送一个\r\n过去 如果发送失败,就重新初始化一个socket
                    if (!isSuccess) {
                        mHandler.removeCallbacks(heartBeatRunnable);
                        mReadThread.release();
                        releaseLastSocket(mSocket);
                        new InitSocketThread().start();
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }


        }
    };

    private Runnable SendBeatRunnable = new Runnable() {
        @Override
        public void run() {
            boolean isSuccess = sendMsg(lastMsgString);//就发送一个\r\n过去 如果发送失败,就重新初始化一个socket
            if (!isSuccess) {
                mHandler.removeCallbacks(heartBeatRunnable);
                mReadThread.release();
                releaseLastSocket(mSocket);
                new InitSocketThread().start();
            }
        }
    };

    private long sendTime = 0L;
//    /**
//     * aidl通讯回调 主要用于与activity 交互 
//     */
//    private IBackService.Stub iBackService = new IBackService.Stub() {
//
//        /**
//         * 收到内容发送消息
//         * @param message 需要发送到服务器的消息
//         * @return
//         * @throws RemoteException
//         */
//        @Override
//        public boolean sendMessage(String message) throws RemoteException {
//            return sendMsg(message);
//        }
//    };

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

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "------------------------onCreate");
        new InitSocketThread().start();
        EventBus.getDefault().register(this);
        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);

    }

    public boolean sendMsg(final String msg) {
        if (null == mSocket || null == mSocket.get()) {
            return false;
        }
        final Socket soc = mSocket.get();
        if (!soc.isClosed() && !soc.isOutputShutdown()) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        OutputStream os = soc.getOutputStream();
                        String message = msg + "\r\n";
                        os.write(message.getBytes());
                        os.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            sendTime = System.currentTimeMillis();//每次发送成数据,就改一下最后成功发送的时间,节省心跳间隔时间
        } else {
            return false;
        }
        return true;
    }

    private void initSocket() {//初始化Socket
        try {
            Socket so = new Socket(HOST, PORT);
            mSocket = new WeakReference<Socket>(so);
            mReadThread = new ReadThread(so);
            mReadThread.start();
            mHandler.post(LoginBeatRunnable);//初始化成功后,就准备登陆socket
            mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//初始化成功后,就准备发送心跳包
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 心跳机制判断出socket已经断开后,就销毁连接方便重新创建连接
     *
     * @param mSocket
     */
    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();
            initSocket();
        }
    }

    // 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 {
                    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);
                            //收到服务器过来的消息,就通过EventBus发送出去

                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 在API11之后构建Notification的方式
        Notification.Builder builder = new Notification.Builder(this.getApplicationContext()); //获取一个Notification构造器
        Intent nfIntent = new Intent(this, MainActivity.class);
        builder.setContentIntent(PendingIntent.getActivity(this, 0, nfIntent, 0))
                .setLargeIcon(BitmapFactory.decodeResource(this.getResources(), R.drawable.icon_1)) // 设置下拉列表中的图标(大图标)
                .setContentTitle("标题") // 设置下拉列表里的标题
                .setSmallIcon(R.drawable.icon_1)// 设置状态栏内的小图标
                .setContentText("内容") // 设置上下文内容
                .setWhen(System.currentTimeMillis()); // 设置该通知发生的时间

        Notification notification = builder.build(); // 获取构建好的Notification
        notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音
        startForeground(110, notification);// 开始前台服务
        return super.onStartCommand(intent, flags, startId);
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
        stopForeground(true);// 停止前台服务--参数:表示是否移除之前的通知
        mHandler.removeCallbacks(heartBeatRunnable);
        mReadThread.release();
        releaseLastSocket(mSocket);
        Log.e(TAG, "------------------------onDestroy");
    }
}

猜你喜欢

转载自blog.csdn.net/a136447572/article/details/87161581