package com.freer.infusion.module.service;

import android.app.ActivityManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Parcelable;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log; import com.freer.infusion.R;
import com.freer.infusion.config.AppConfig;
import com.freer.infusion.entity.SocketEntity;
import com.freer.infusion.model.SocketDataModel;
import com.freer.infusion.model.SocketDataProcess;
import com.freer.infusion.module.main.MainActivity;
import com.freer.infusion.util.JsonUtils;
import com.freer.infusion.util.NetUtils;
import com.freer.infusion.util.ScreenLockLocation;
import com.freer.infusion.util.ThreadManager;
import com.freer.infusion.util.ToastUtils;
import com.google.gson.FieldAttributes; import org.apache.http.conn.ConnectTimeoutException; import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.net.ConnectException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List; /**
* Created by 2172980000774 on 2016/5/12.
*/
public class SocketService extends Service { /* handler消息标志 */
private static final int HANDLER_DEBUG = ; //Debug数据
private static final int HANDLER_SERVER = ; //服务器数据
private static final int HANDLER_LOCAL = ; //本地数据
private static final int HANDLER_ERROR = ; //扫描服务器失败 private static final String CHECK_CONN = "{\"cate\":8,\"d\":[]}"; //连接确认
private static final String HEART_BEAT = "{\"cate\":9,\"d\":[]}"; //心跳检测 private static final long HEART_BEAT_RATE = * ; //心跳检测间隔时间
private static final long CONN_CHECK_RATE = * ; //扫描服务器超时时间 public static String HOST = null; //服务器IP地址
public static int PORT = ; //服务器端口号 public static final String MESSAGE_ACTION="message_action";
public static final String HEART_BEAT_ACTION="heart_beat_action";
public static final String CONN_CHECK_ACTION = "conn_check_action";
public static final String CONN_ERROR_ACTION = "conn_error_action";
public static final String NO_CONN_ACTION = "no_conn_action"; private ReadThread mReadThread; private LocalBroadcastManager mLocalBroadcastManager; private WeakReference<Socket> mSocket; private SocketDataProcess mSocketDataProcess = new SocketDataProcess();
private SocketDataModel mFollowModel = new SocketDataModel();
private SocketDataModel mAllModel = new SocketDataModel(); private ScreenLockLocation mScreenLockLocation; /** For Heart Beat */
private long sendTime = 0L;
private Handler mHeartBeatHandler = new Handler();
private Runnable heartBeatRunnable = new Runnable() { @Override
public void run() {
if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
if (!sendMsg(null)) { //就发送一个心跳数据过去 如果发送失败,就重新初始化一个socket
// 发送失败处理
release();
// 首先判断本地是否服务器记录,如果没有则已经做过遍历并连接失败,直接通知用户服务器连接失败
if (HOST == null) {
Message sendFail = mMsgHandler.obtainMessage();
sendFail.what = HANDLER_ERROR;
sendFail.sendToTarget();
} else {
ThreadManager.getInstance().addTask(new CheckConnRunnable(HOST));
// new Thread(new CheckConnRunnable(HOST)).start();
}
}
}
mHeartBeatHandler.postDelayed(this, HEART_BEAT_RATE);
}
}; /**
* 更新主界面数据接口
*/
public interface IReceiveMessage {
void receiveMessage(List<SocketEntity> followBedList, List<SocketEntity> allBedList);
}
private IReceiveMessage mIReceiveMessage; public class SocketBinder extends Binder {
public boolean sendMessage(SocketEntity message) {
return sendMsg(message);
} public void setOnReveiveMessage(IReceiveMessage iReceiveMessage) {
mIReceiveMessage = iReceiveMessage;
} public void reStart() {
// 释放之前的资源
release();
// 重新初始化socket
String ip = AppConfig.getInstance().getServerIp();
if (ip != null && !ip.equals("")) {
ThreadManager.getInstance().addTask(new CheckConnRunnable(ip));
// new Thread(new CheckConnRunnable(ip)).start();
} else {
if (HOST != null) {
ThreadManager.getInstance().addTask(new CheckConnRunnable(HOST));
// new Thread(new CheckConnRunnable(HOST)).start();
} else {
scanIpSegment();
}
}
}
} /**
* 开始连接服务器
*/
public void startWork() {
String ip = AppConfig.getInstance().getServerIp();
if (ip != null && !ip.equals("")) {
// new Thread(new CheckConnRunnable(ip)).start();
ThreadManager.getInstance().addTask(new CheckConnRunnable(ip));
} else {
scanIpSegment();
}
} public SocketBinder mSocketBinder; @Override
public IBinder onBind(Intent arg0) {
return mSocketBinder;
} @Override
public void onCreate() {
super.onCreate();
mScreenLockLocation = new ScreenLockLocation(this);
mScreenLockLocation.start(); Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); startForeground(,
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(SocketService.this.getString(R.string.navi_title))
.setContentText(SocketService.this.getString(R.string.navi_content))
.setShowWhen(false)
.setOngoing(true)
.setContentIntent(PendingIntent.getActivity(this, , intent, PendingIntent.FLAG_UPDATE_CURRENT))
.build()); mSocketBinder = new SocketBinder();
mLocalBroadcastManager=LocalBroadcastManager.getInstance(this); // new InitSocketThread().start();
startWork();
// ThreadManager.getInstance().addTask(new CheckConnRunnable("192.168.1.3"));
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("SocketService", "onStartCommand");
return super.onStartCommand(intent, flags, startId);
} @Override
public void onDestroy() {
Log.e("SocketService", "onDestroy");
mScreenLockLocation.stop();
stopForeground(true);
stopWork();
super.onDestroy();
} public boolean sendMsg(SocketEntity msg) {
if (null == mSocket || null == mSocket.get()) {
return false;
}
Socket soc = mSocket.get();
try {
if (!soc.isClosed() && !soc.isOutputShutdown()) {
OutputStream os = soc.getOutputStream();
// 如果为null,说明是心跳检测,否则就是本地主动设置的数据
String message =
msg == null ?
HEART_BEAT : "{\"cate\":0,\"d\":["+msg.toString()+"]}";
os.write(message.getBytes());
os.flush();
//发送成功处理
sendTime = System.currentTimeMillis(); //每次发送成数据,就改一下最后成功发送的时间,节省心跳间隔时间
if (msg != null) { //确认是本地主动修改发送给服务器的数据
Message sendSuccess = mMsgHandler.obtainMessage();
sendSuccess.what = HANDLER_LOCAL;
sendSuccess.obj = msg.toString();
sendSuccess.sendToTarget();
}
return true;
}
} catch (IOException e) {
System.out.println("发送失败");
}
return false;
} private void initSocket() { // 初始化Socket
try {
Socket so = new Socket(HOST, PORT);
mSocket = new WeakReference<>(so);
mReadThread = new ReadThread(so);
mReadThread.start();
mHeartBeatHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//初始化成功后,就准备发送心跳包
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} /**
* 在遍历ip之后,第一次连接调用
* @param socket
*/
private void initSocket(Socket socket) {
mSocket = new WeakReference<Socket>(socket);
mReadThread = new ReadThread(socket);
mReadThread.start();
mHeartBeatHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE); // 初始化成功后,就准备发送心跳包
} private void releaseLastSocket(WeakReference<Socket> mSocket) {
try {
if (null != mSocket) {
Socket sk = mSocket.get();
if (sk != null && !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> weakSocket;
private boolean isStart = true; public ReadThread(Socket socket) {
weakSocket = new WeakReference<Socket>(socket);
} public void release() {
isStart = false;
releaseLastSocket(weakSocket);
} @Override
public void run() {
super.run();
Socket socket = weakSocket.get();
receiveMsg(socket, isStart);
}
} public void receiveMsg(Socket socket, boolean isStart) {
if (null != socket) {
try {
InputStream is = socket.getInputStream();
byte[] buffer = new byte[ * ];
int length = ;
while (!socket.isClosed() && !socket.isInputShutdown()
&& isStart && ((length = is.read(buffer)) != -)) {
if (length > ) {
String message = new String(Arrays.copyOf(buffer,
length)).trim();
System.out.println("收到Socket服务器回复");
//收到服务器过来的消息,就通过Broadcast发送出去
if(message.contains("\"cate\":9")){//处理心跳回复
System.out.println("当前回复为心跳检测");
// Intent intent=new Intent(HEART_BEAT_ACTION);
// mLocalBroadcastManager.sendBroadcast(intent);
}else if (message.contains("\"cate\":0")){
System.out.println("当前回复为其他回复");
//其他消息回复
Message msg = mMsgHandler.obtainMessage();
msg.what = HANDLER_SERVER;
msg.obj = message;
msg.sendToTarget();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* 通过回调的方式通知activity
* 通过handler从子线程传递数据到主线程中
*/
private Handler mMsgHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == HANDLER_SERVER) { //收到服务器传递的数据
sendTime = System.currentTimeMillis(); //每一次成功接收到服务器主动发送的消息,更新时间
if (msg!=null && msg.obj != null) {
System.out.println("收到原始数据"+msg.obj.toString());
}
String data = (String) msg.obj;
// mSocketDataProcess.processData(data);
mFollowModel.processData(data, true);
mAllModel.processData(data, false);
//考虑一下,因为ReceiveMessage需要在成功绑定之后才能获取实例
//那么,如果在成功绑定之前,当前service就已经运行到这里
//就会出现数据丢失的情况
if (mIReceiveMessage != null) {
mIReceiveMessage.receiveMessage(mFollowModel.getData(), mAllModel.getData());
}
} else if (msg.what == HANDLER_LOCAL) { //收到本地需要修改的数据
SocketEntity socketEntity = JsonUtils.fromJson((String) msg.obj, SocketEntity.class);
mFollowModel.setDataNoAdd(socketEntity);
mAllModel.setDataNoAdd(socketEntity);
//考虑一下,因为ReceiveMessage需要在成功绑定之后才能获取实例
//那么,如果在成功绑定之前,当前service就已经运行到这里
//就会出现数据丢失的情况
if (mIReceiveMessage != null) {
mIReceiveMessage.receiveMessage(mFollowModel.getData(), mAllModel.getData());
}
} else if (msg.what == HANDLER_DEBUG) {
System.out.println(msg.obj.toString());
} else if (msg.what == HANDLER_ERROR) {
if (HOST == null) { //在扫描开始10秒后,结束到消息,判断此时是否有扫描结果
Intent intent=new Intent(CONN_ERROR_ACTION);
mLocalBroadcastManager.sendBroadcast(intent);
}
}
}
}; /**
* 跟服务器确认首次连接
* @param ip
* @return
*/
public Socket checkConn(String ip) {
if (AppConfig.getInstance().isDebug()) {
Message msg = mMsgHandler.obtainMessage();
msg.what = HANDLER_DEBUG;
msg.obj = "尝试跟服务器socket通信" + ip;
msg.sendToTarget();
}
Socket socket = null;
try {
socket = new Socket();
socket.connect(new InetSocketAddress(ip, PORT), );
socket.setSoTimeout( * ); //获取输出流
OutputStream os = socket.getOutputStream();
//发送连接确认消息
if (!socket.isClosed() && !socket.isOutputShutdown()) {
String message = CHECK_CONN;
os.write(message.getBytes());
os.flush(); //刷新输出流,使Server马上收到该字符串
} //获取输入流
InputStream is = socket.getInputStream();
byte[] buffer = new byte[ * ];
int length = ;
//接受连接确认消息
while (!socket.isClosed() && !socket.isInputShutdown()
&& ((length = is.read(buffer)) != -)) {
if (length > ) {
String message = new String(Arrays.copyOf(buffer, length)).trim();
if (message.contains("\"cate\":8")) {
return socket;
} else if (message.contains("\"cate\":0")) {
Message msg = mMsgHandler.obtainMessage();
msg.what = HANDLER_SERVER;
msg.obj = message;
msg.sendToTarget();
return socket;
}
}
}
} catch (SocketTimeoutException e) {
if (AppConfig.getInstance().isDebug()) {
Message msg = mMsgHandler.obtainMessage();
msg.what = HANDLER_DEBUG;
msg.obj = "socket服务器响应超时--->"+ip;
msg.sendToTarget();
}
} catch (ConnectException e) {
if (AppConfig.getInstance().isDebug()) {
Message msg = mMsgHandler.obtainMessage();
msg.what = HANDLER_DEBUG;
msg.obj = "socket服务器请求超时--->"+ip;
msg.sendToTarget();
}
} catch (InterruptedIOException e) {
if (AppConfig.getInstance().isDebug()) {
Message msg = mMsgHandler.obtainMessage();
msg.what = HANDLER_DEBUG;
msg.obj = "socket连接超时--->"+ip;
msg.sendToTarget();
}
} catch (UnknownHostException e) {
if (AppConfig.getInstance().isDebug()) {
Message msg = mMsgHandler.obtainMessage();
msg.what = HANDLER_DEBUG;
msg.obj = "socket尝试连接一个不存在的端口--->"+ip;
msg.sendToTarget();
}
} catch (IOException e) {
if (AppConfig.getInstance().isDebug()) {
Message msg = mMsgHandler.obtainMessage();
msg.what = HANDLER_DEBUG;
msg.obj = "socket IOException--->"+ip;
msg.sendToTarget();
}
} if (socket != null) {
try {
socket.close();
} catch (IOException e) {
if (AppConfig.getInstance().isDebug()) {
Message msg = mMsgHandler.obtainMessage();
msg.what = HANDLER_DEBUG;
msg.obj = "socket关闭失败--->"+ip;
msg.sendToTarget();
}
}
socket = null;
}
return null;
} /**
*跟服务器确认首次连接
*/
class CheckConnRunnable implements Runnable { private String currentIp = null;
private int ipSuff = ; //ip后缀 public CheckConnRunnable(String ip) { this(ip, ); } public CheckConnRunnable(String ip, int ipSuff) {
this.currentIp = ip;
this.ipSuff = ipSuff;
} @Override
public void run() {
if (ipSuff == ) { // 在ip后缀为1,即扫描开始后30秒,向消息队列发送一次消息
Message msgarg = new Message();
msgarg.what = HANDLER_ERROR;
mMsgHandler.sendMessageDelayed(msgarg, CONN_CHECK_RATE);
}
try {
Socket socket = null;
//向服务器发送验证信息,如果验证通过...
if ((socket = checkConn(currentIp)) != null) {
if (AppConfig.getInstance().isDebug()) {
Message msg = mMsgHandler.obtainMessage();
msg.what = HANDLER_DEBUG;
msg.obj = "socket通信成功"+currentIp;
msg.sendToTarget();
}
Intent intent = new Intent(CONN_CHECK_ACTION);
mLocalBroadcastManager.sendBroadcast(intent);
AppConfig.getInstance().setServerIp(currentIp);
HOST = currentIp;
socket.setSoTimeout();
initSocket(socket);
} else {
if (AppConfig.getInstance().isDebug()) {
Message msg = mMsgHandler.obtainMessage();
msg.what = HANDLER_DEBUG;
msg.obj = "socket通信失败"+currentIp;
msg.sendToTarget();
}
if (ipSuff == ) { //连接本地保存的服务器地址失败,开始遍历IP进行扫描
scanIpSegment();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* 扫描局域网IP段
*/
public void scanIpSegment(){
System.out.println("开始遍历局域网Ip段");
String locAddrPref = NetUtils.getIpByWifi(this); //获取本地ip前缀,比如192.168.1.
if(locAddrPref == null || locAddrPref.equals("")) {
Intent intent = new Intent(NO_CONN_ACTION);
mLocalBroadcastManager.sendBroadcast(intent);
return;
}
HOST = null;
for (int suff = ; suff < ; suff++) {//创建256个线程分别去连接服务器
ThreadManager.getInstance().addTask(
new CheckConnRunnable(locAddrPref + String.valueOf(suff), suff));
}
} /**
* 释放资源
*/
public void release() {
if (mHeartBeatHandler != null && heartBeatRunnable != null) {
mHeartBeatHandler.removeCallbacks(heartBeatRunnable);
}
if (mReadThread != null) {
mReadThread.release();
}
releaseLastSocket(mSocket);
} /**
* 停止整个service运行
*/
public void stopWork() {
release();
ThreadManager.getInstance().closeThreadPool(); // 关闭线程池
ActivityManager activityMgr= (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
activityMgr.killBackgroundProcesses(getPackageName());
android.os.Process.killProcess(android.os.Process.myPid());
System.exit();
}
}

package com.freer.infusion.module.service;
import android.app.ActivityManager;import android.app.PendingIntent;import android.app.Service;import android.content.Intent;import android.graphics.BitmapFactory;import android.os.Binder;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.os.Parcelable;import android.support.v4.app.NotificationCompat;import android.support.v4.app.NotificationManagerCompat;import android.support.v4.content.ContextCompat;import android.support.v4.content.LocalBroadcastManager;import android.util.Log;
import com.freer.infusion.R;import com.freer.infusion.config.AppConfig;import com.freer.infusion.entity.SocketEntity;import com.freer.infusion.model.SocketDataModel;import com.freer.infusion.model.SocketDataProcess;import com.freer.infusion.module.main.MainActivity;import com.freer.infusion.util.JsonUtils;import com.freer.infusion.util.NetUtils;import com.freer.infusion.util.ScreenLockLocation;import com.freer.infusion.util.ThreadManager;import com.freer.infusion.util.ToastUtils;import com.google.gson.FieldAttributes;
import org.apache.http.conn.ConnectTimeoutException;
import java.io.IOException;import java.io.InputStream;import java.io.InterruptedIOException;import java.io.OutputStream;import java.io.Serializable;import java.lang.ref.WeakReference;import java.net.ConnectException;import java.net.Inet4Address;import java.net.InetAddress;import java.net.InetSocketAddress;import java.net.NetworkInterface;import java.net.Socket;import java.net.SocketException;import java.net.SocketTimeoutException;import java.net.UnknownHostException;import java.util.ArrayList;import java.util.Arrays;import java.util.Enumeration;import java.util.List;
/** * Created by 2172980000774 on 2016/5/12. */public class SocketService extends Service {
    /* handler消息标志 */    private static final int HANDLER_DEBUG = 0; //Debug数据    private static final int HANDLER_SERVER = 1; //服务器数据    private static final int HANDLER_LOCAL = 2; //本地数据    private static final int HANDLER_ERROR = 3; //扫描服务器失败
    private static final String CHECK_CONN = "{\"cate\":8,\"d\":[]}"; //连接确认    private static final String HEART_BEAT = "{\"cate\":9,\"d\":[]}"; //心跳检测
    private static final long HEART_BEAT_RATE = 15 * 1000; //心跳检测间隔时间    private static final long CONN_CHECK_RATE = 5 * 1000; //扫描服务器超时时间
    public static String HOST = null; //服务器IP地址    public static int PORT = 2020; //服务器端口号
    public static final String MESSAGE_ACTION="message_action";    public static final String HEART_BEAT_ACTION="heart_beat_action";    public static final String CONN_CHECK_ACTION = "conn_check_action";    public static final String CONN_ERROR_ACTION = "conn_error_action";    public static final String NO_CONN_ACTION = "no_conn_action";
    private ReadThread mReadThread;
    private LocalBroadcastManager mLocalBroadcastManager;
    private WeakReference<Socket> mSocket;
    private SocketDataProcess mSocketDataProcess = new SocketDataProcess();    private SocketDataModel mFollowModel = new SocketDataModel();    private SocketDataModel mAllModel = new SocketDataModel();
    private ScreenLockLocation mScreenLockLocation;
    /** For Heart Beat */    private long sendTime = 0L;    private Handler mHeartBeatHandler = new Handler();    private Runnable heartBeatRunnable = new Runnable() {
        @Override        public void run() {            if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {                if (!sendMsg(null)) { //就发送一个心跳数据过去 如果发送失败,就重新初始化一个socket                    // 发送失败处理                    release();                    // 首先判断本地是否服务器记录,如果没有则已经做过遍历并连接失败,直接通知用户服务器连接失败                    if (HOST == null) {                        Message sendFail = mMsgHandler.obtainMessage();                        sendFail.what = HANDLER_ERROR;                        sendFail.sendToTarget();                    } else {                        ThreadManager.getInstance().addTask(new CheckConnRunnable(HOST));//                        new Thread(new CheckConnRunnable(HOST)).start();                    }                }            }            mHeartBeatHandler.postDelayed(this, HEART_BEAT_RATE);        }    };
    /**     * 更新主界面数据接口     */    public interface IReceiveMessage {        void receiveMessage(List<SocketEntity> followBedList, List<SocketEntity> allBedList);    }    private IReceiveMessage mIReceiveMessage;
    public class SocketBinder extends Binder {        public boolean sendMessage(SocketEntity message) {            return sendMsg(message);        }
        public void setOnReveiveMessage(IReceiveMessage iReceiveMessage) {            mIReceiveMessage = iReceiveMessage;        }
        public void reStart() {            // 释放之前的资源            release();            // 重新初始化socket            String ip = AppConfig.getInstance().getServerIp();            if (ip != null && !ip.equals("")) {                ThreadManager.getInstance().addTask(new CheckConnRunnable(ip));//                new Thread(new CheckConnRunnable(ip)).start();            } else {                if (HOST != null) {                    ThreadManager.getInstance().addTask(new CheckConnRunnable(HOST));//                    new Thread(new CheckConnRunnable(HOST)).start();                } else {                    scanIpSegment();                }            }        }    }
    /**     * 开始连接服务器     */    public void startWork() {        String ip = AppConfig.getInstance().getServerIp();        if (ip != null && !ip.equals("")) {//            new Thread(new CheckConnRunnable(ip)).start();            ThreadManager.getInstance().addTask(new CheckConnRunnable(ip));        } else {            scanIpSegment();        }    }
    public SocketBinder mSocketBinder;
    @Override    public IBinder onBind(Intent arg0) {        return mSocketBinder;    }
    @Override    public void onCreate() {        super.onCreate();        mScreenLockLocation = new ScreenLockLocation(this);        mScreenLockLocation.start();
        Intent intent =  new Intent(this, MainActivity.class);        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startForeground(1,                new NotificationCompat.Builder(this)                        .setSmallIcon(R.drawable.ic_launcher)                        .setContentTitle(SocketService.this.getString(R.string.navi_title))                        .setContentText(SocketService.this.getString(R.string.navi_content))                        .setShowWhen(false)                        .setOngoing(true)                        .setContentIntent(PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT))                        .build());
        mSocketBinder = new SocketBinder();        mLocalBroadcastManager=LocalBroadcastManager.getInstance(this);
//        new InitSocketThread().start();        startWork();//        ThreadManager.getInstance().addTask(new CheckConnRunnable("192.168.1.3"));    }
    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.e("SocketService", "onStartCommand");        return super.onStartCommand(intent, flags, startId);    }
    @Override    public void onDestroy() {        Log.e("SocketService", "onDestroy");        mScreenLockLocation.stop();        stopForeground(true);        stopWork();        super.onDestroy();    }
    public boolean sendMsg(SocketEntity msg) {        if (null == mSocket || null == mSocket.get()) {            return false;        }        Socket soc = mSocket.get();        try {            if (!soc.isClosed() && !soc.isOutputShutdown()) {                OutputStream os = soc.getOutputStream();                // 如果为null,说明是心跳检测,否则就是本地主动设置的数据                String message =                        msg == null ?                                HEART_BEAT : "{\"cate\":0,\"d\":["+msg.toString()+"]}";                os.write(message.getBytes());                os.flush();                //发送成功处理                sendTime = System.currentTimeMillis(); //每次发送成数据,就改一下最后成功发送的时间,节省心跳间隔时间                if (msg != null) { //确认是本地主动修改发送给服务器的数据                    Message sendSuccess = mMsgHandler.obtainMessage();                    sendSuccess.what = HANDLER_LOCAL;                    sendSuccess.obj = msg.toString();                    sendSuccess.sendToTarget();                }                return true;            }        } catch (IOException e) {            System.out.println("发送失败");        }        return false;    }
    private void initSocket() { // 初始化Socket        try {            Socket so = new Socket(HOST, PORT);            mSocket = new WeakReference<>(so);            mReadThread = new ReadThread(so);            mReadThread.start();            mHeartBeatHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);//初始化成功后,就准备发送心跳包        } catch (UnknownHostException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }    }
    /**     * 在遍历ip之后,第一次连接调用     * @param socket     */    private void initSocket(Socket socket) {        mSocket = new WeakReference<Socket>(socket);        mReadThread = new ReadThread(socket);        mReadThread.start();        mHeartBeatHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE); // 初始化成功后,就准备发送心跳包    }
    private void releaseLastSocket(WeakReference<Socket> mSocket) {        try {            if (null != mSocket) {                Socket sk = mSocket.get();                if (sk != null && !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> weakSocket;        private boolean isStart = true;
        public ReadThread(Socket socket) {            weakSocket = new WeakReference<Socket>(socket);        }
        public void release() {            isStart = false;            releaseLastSocket(weakSocket);        }
        @Override        public void run() {            super.run();            Socket socket = weakSocket.get();            receiveMsg(socket, isStart);        }    }
    public void receiveMsg(Socket socket, boolean isStart) {        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();                        System.out.println("收到Socket服务器回复");                        //收到服务器过来的消息,就通过Broadcast发送出去                        if(message.contains("\"cate\":9")){//处理心跳回复                            System.out.println("当前回复为心跳检测");//                            Intent intent=new Intent(HEART_BEAT_ACTION);//                            mLocalBroadcastManager.sendBroadcast(intent);                        }else if (message.contains("\"cate\":0")){                            System.out.println("当前回复为其他回复");                            //其他消息回复                            Message msg = mMsgHandler.obtainMessage();                            msg.what = HANDLER_SERVER;                            msg.obj = message;                            msg.sendToTarget();                        }                    }                }            } catch (IOException e) {                e.printStackTrace();            }        }    }
    /**     * 通过回调的方式通知activity     * 通过handler从子线程传递数据到主线程中     */    private Handler mMsgHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            if (msg.what == HANDLER_SERVER) { //收到服务器传递的数据                sendTime = System.currentTimeMillis(); //每一次成功接收到服务器主动发送的消息,更新时间                if (msg!=null && msg.obj != null) {                    System.out.println("收到原始数据"+msg.obj.toString());                }                String data = (String) msg.obj;//                mSocketDataProcess.processData(data);                mFollowModel.processData(data, true);                mAllModel.processData(data, false);                //考虑一下,因为ReceiveMessage需要在成功绑定之后才能获取实例                //那么,如果在成功绑定之前,当前service就已经运行到这里                //就会出现数据丢失的情况                if (mIReceiveMessage != null) {                    mIReceiveMessage.receiveMessage(mFollowModel.getData(), mAllModel.getData());                }            } else if (msg.what == HANDLER_LOCAL) { //收到本地需要修改的数据                SocketEntity socketEntity = JsonUtils.fromJson((String) msg.obj, SocketEntity.class);                mFollowModel.setDataNoAdd(socketEntity);                mAllModel.setDataNoAdd(socketEntity);                //考虑一下,因为ReceiveMessage需要在成功绑定之后才能获取实例                //那么,如果在成功绑定之前,当前service就已经运行到这里                //就会出现数据丢失的情况                if (mIReceiveMessage != null) {                    mIReceiveMessage.receiveMessage(mFollowModel.getData(), mAllModel.getData());                }            } else if (msg.what == HANDLER_DEBUG) {                System.out.println(msg.obj.toString());            } else if (msg.what == HANDLER_ERROR) {                if (HOST == null) { //在扫描开始10秒后,结束到消息,判断此时是否有扫描结果                    Intent intent=new Intent(CONN_ERROR_ACTION);                    mLocalBroadcastManager.sendBroadcast(intent);                }            }        }    };
    /**     * 跟服务器确认首次连接     * @param ip     * @return     */    public Socket checkConn(String ip) {        if (AppConfig.getInstance().isDebug()) {            Message msg = mMsgHandler.obtainMessage();            msg.what = HANDLER_DEBUG;            msg.obj = "尝试跟服务器socket通信" + ip;            msg.sendToTarget();        }        Socket socket = null;        try {            socket = new Socket();            socket.connect(new InetSocketAddress(ip, PORT), 500);            socket.setSoTimeout(1 * 1000);
            //获取输出流            OutputStream os = socket.getOutputStream();            //发送连接确认消息            if (!socket.isClosed() && !socket.isOutputShutdown()) {                String message = CHECK_CONN;                os.write(message.getBytes());                os.flush(); //刷新输出流,使Server马上收到该字符串            }
            //获取输入流            InputStream is = socket.getInputStream();            byte[] buffer = new byte[1024 * 4];            int length = 0;            //接受连接确认消息            while (!socket.isClosed() && !socket.isInputShutdown()                    && ((length = is.read(buffer)) != -1)) {                if (length > 0) {                    String message = new String(Arrays.copyOf(buffer, length)).trim();                    if (message.contains("\"cate\":8")) {                        return socket;                    } else if (message.contains("\"cate\":0")) {                        Message msg = mMsgHandler.obtainMessage();                        msg.what = HANDLER_SERVER;                        msg.obj = message;                        msg.sendToTarget();                        return socket;                    }                }            }        } catch (SocketTimeoutException e) {            if (AppConfig.getInstance().isDebug()) {                Message msg = mMsgHandler.obtainMessage();                msg.what = HANDLER_DEBUG;                msg.obj = "socket服务器响应超时--->"+ip;                msg.sendToTarget();            }        } catch (ConnectException e) {            if (AppConfig.getInstance().isDebug()) {                Message msg = mMsgHandler.obtainMessage();                msg.what = HANDLER_DEBUG;                msg.obj = "socket服务器请求超时--->"+ip;                msg.sendToTarget();            }        } catch (InterruptedIOException e) {            if (AppConfig.getInstance().isDebug()) {                Message msg = mMsgHandler.obtainMessage();                msg.what = HANDLER_DEBUG;                msg.obj = "socket连接超时--->"+ip;                msg.sendToTarget();            }        } catch (UnknownHostException e) {            if (AppConfig.getInstance().isDebug()) {                Message msg = mMsgHandler.obtainMessage();                msg.what = HANDLER_DEBUG;                msg.obj = "socket尝试连接一个不存在的端口--->"+ip;                msg.sendToTarget();            }        } catch (IOException e) {            if (AppConfig.getInstance().isDebug()) {                Message msg = mMsgHandler.obtainMessage();                msg.what = HANDLER_DEBUG;                msg.obj = "socket IOException--->"+ip;                msg.sendToTarget();            }        }
        if (socket != null) {            try {                socket.close();            } catch (IOException e) {                if (AppConfig.getInstance().isDebug()) {                    Message msg = mMsgHandler.obtainMessage();                    msg.what = HANDLER_DEBUG;                    msg.obj = "socket关闭失败--->"+ip;                    msg.sendToTarget();                }            }            socket = null;        }        return null;    }
    /**     *跟服务器确认首次连接     */    class CheckConnRunnable implements Runnable {
        private String currentIp = null;        private int ipSuff = 0; //ip后缀
        public CheckConnRunnable(String ip) { this(ip, 0); }
        public CheckConnRunnable(String ip, int ipSuff) {            this.currentIp = ip;            this.ipSuff = ipSuff;        }
        @Override        public void run() {            if (ipSuff == 255) { // 在ip后缀为1,即扫描开始后30秒,向消息队列发送一次消息                Message msgarg = new Message();                msgarg.what = HANDLER_ERROR;                mMsgHandler.sendMessageDelayed(msgarg, CONN_CHECK_RATE);            }            try {                Socket socket = null;                //向服务器发送验证信息,如果验证通过...                if ((socket = checkConn(currentIp)) != null) {                    if (AppConfig.getInstance().isDebug()) {                        Message msg = mMsgHandler.obtainMessage();                        msg.what = HANDLER_DEBUG;                        msg.obj = "socket通信成功"+currentIp;                        msg.sendToTarget();                    }                    Intent intent = new Intent(CONN_CHECK_ACTION);                    mLocalBroadcastManager.sendBroadcast(intent);                    AppConfig.getInstance().setServerIp(currentIp);                    HOST = currentIp;                    socket.setSoTimeout(0);                    initSocket(socket);                } else {                    if (AppConfig.getInstance().isDebug()) {                        Message msg = mMsgHandler.obtainMessage();                        msg.what = HANDLER_DEBUG;                        msg.obj = "socket通信失败"+currentIp;                        msg.sendToTarget();                    }                    if (ipSuff == 0) { //连接本地保存的服务器地址失败,开始遍历IP进行扫描                        scanIpSegment();                    }                }            } catch (IOException e) {                e.printStackTrace();            }        }    }
    /**     * 扫描局域网IP段     */    public void scanIpSegment(){        System.out.println("开始遍历局域网Ip段");        String locAddrPref = NetUtils.getIpByWifi(this); //获取本地ip前缀,比如192.168.1.        if(locAddrPref == null || locAddrPref.equals("")) {            Intent intent = new Intent(NO_CONN_ACTION);            mLocalBroadcastManager.sendBroadcast(intent);            return;        }        HOST = null;        for (int suff = 1; suff < 256; suff++) {//创建256个线程分别去连接服务器            ThreadManager.getInstance().addTask(                    new CheckConnRunnable(locAddrPref + String.valueOf(suff), suff));        }    }
    /**     * 释放资源     */    public void release() {        if (mHeartBeatHandler != null && heartBeatRunnable != null) {            mHeartBeatHandler.removeCallbacks(heartBeatRunnable);        }        if (mReadThread != null) {            mReadThread.release();        }        releaseLastSocket(mSocket);    }
    /**     * 停止整个service运行     */    public void stopWork() {        release();        ThreadManager.getInstance().closeThreadPool(); // 关闭线程池        ActivityManager activityMgr= (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);        activityMgr.killBackgroundProcesses(getPackageName());        android.os.Process.killProcess(android.os.Process.myPid());        System.exit(0);    }}

Android SocketService的更多相关文章

  1. 基于SuperSocket的IIS主动推送消息给android客户端

    在上一篇文章<基于mina框架的GPS设备与服务器之间的交互>中,提到之前一直使用superwebsocket框架做为IIS和APP通信的媒介,经常出现无法通信的问题,必须一天几次的手动回 ...

  2. android实现 服务器功能

    package com.weijia.tests; import java.io.IOException; import java.net.InetSocketAddress; import java ...

  3. Android网络编程之Socket

    Socket(套接字)是一种通信机制,可以实现单机或跨网络进行通信,其创建需要明确的区分C(客户端)/S(服务器端),支持多个客户端连接到同一个服务器.有两种传输模式: 1).面向连接的传输:基于TC ...

  4. android开发之socket快传文件以及消息返回

    应用场景: 两台android机器:一台自建wifi热点,另一台搜索到,连接该wifi热点.之后再通过socket传递消息,文件等,当服务器端接收到消息之后会返回对应的应答消息: 注意点:接收到消息之 ...

  5. android开发 socket接收图片并保存

    逻辑:接收到socket之后需要将socket发送的图片数据保存下来并通知handler更新界面 关键代码: public void readImage(Socket socket) { try { ...

  6. Android在如何建立一个WebServer

    今天老板交待任务最终完成了,感觉收获颇多,所以写一个关于它的记录,首先,看一下.老板的需求 需求: 希望移动端的用户标识(IMEI)和HTML页面的用户标识(Cookie)连接起来,当中HTML页面可 ...

  7. android端 socket长连接 架构

    看过包建强的<App研发录>之后对其中的基础Activity类封装感到惊讶,一直想找一种方式去解决关于app中使用socket长连接问题,如何实现简易的封装来达到主活动中涉及socket相 ...

  8. 【Android实战】Socket消息通信

    这篇博客的内容是基于http://my.oschina.net/fengcunhan/blog/178155进行改造的.所以须要先看完这篇博客,然后再来看以下的内容. 1.须要完毕的功能是直播间的so ...

  9. Android中如何搭建一个WebServer

    今天终于把老大交代的任务搞完了,感觉收获挺多的,所以就写一篇来记录一下吧,首先还是来看一下,老大们的需求 需求: 希望移动端的用户标识(IMEI)和HTML页面的用户标识(Cookie)连接起来,其中 ...

随机推荐

  1. Eight hdu 1043 poj 1077

    Description The 15-puzzle has been around for over 100 years; even if you don't know it by that name ...

  2. webstorm配置less解析的方法

    1.安装node.js 2.npm 安装less, npm install -g less 2.1 lessc style.less styles.css 编译 2.2 lessc –clean-cs ...

  3. python数据处理技巧二

    python数据处理技巧二(掌控时间) 首先简单说下关于时间的介绍其中重点是时间戳的处理,时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00 ...

  4. jq 克隆 移除table

    function addRow2(node){ var obj = $("tr[name='info']:last"); var objClone = $(obj).clone() ...

  5. Windows 操作系统与 .NET Framework

    Windos 2000 在单位的机房里好不easy才找到一台安装 Windows 2000 Server SP4 操作系统的server.这台硕果仅存的server到本月底也要退役了. Windows ...

  6. Erlang简单并行server

    Erlang简单并行服务器 (金庆的专栏) Erlang并行服务器为每一个Tcp连接创建相应的连接进程,处理client数据. 參考 Erlang程序设计(第2版)17.1.3 顺序和并行服务器 并行 ...

  7. UDP连接调用connect()函数

    UDP是一个无连接的协议,它没有像TCP中EOF之类的东西. 8.11 UDP的connect函数 除非套接字已连接,否则异步错误是不会反悔到UDP套接字的. 我们确实能够给UDP套接字调用conne ...

  8. jquery19 ajax()

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  9. Istio Service Mash管理微服务

    Istio Service Mash管理微服务 今天的文章通过Istio开源项目展示如何为Kubernetes管理的微服务提供可见性,弹性,安全性和控制. 服务是现代软件体系结构的核心.比起复杂庞大的 ...

  10. 如何才能正确的关闭Socket连接

    从TCP协议角度来看,一个已建立的TCP连接有两种关闭方式,一种是正常关闭,即四次挥手关闭连接:还有一种则是异常关闭,我们通常称之为连接重置(RESET).首先说一下正常关闭时四次挥手的状态变迁,关闭 ...