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. Chromium Graphics: HW Video Acceleration in Chrom{e,ium}{,OS}

    HW Video Acceleration in Chrom{e,ium}{,OS} Ami Fischman <fischman@chromium.org> Status as of 2 ...

  2. PHP获取随机字符串的两种方法

    <?php /** * 随机返回字符串 * @param number 返回字符串长度 * @param string 从哪些字符串中随机返回,已设置默认字符串,可空 * @return str ...

  3. PHP date()获取某时间段以周、月、季度为粒度的时间段数组

    date()函数: PHP date()  参考:https://www.hi-docs.com/php/date.html Linux date()参考:http://www.cnblogs.com ...

  4. fgrep---指定的输入文件中的匹配模式的行

    fgrep命令是用来搜索 file 参数指定的输入文件(缺省为标准输入)中的匹配模式的行.fgrep 命令特别搜索 Pattern 参数,它们是固定的字符串.如果在 File 参数中指定一个以上的文件 ...

  5. PHP设置30秒内对页面的访问次数

    <?php //Calculate 60 days in the future //seconds * minutes * hours * days + current time $intime ...

  6. 控制div固定在页面的某个位置 ,用js感觉很麻烦 CSS更好一些

    CSS代码:<style type="text/css"> html,body { width:100%; height:100%; margin:0px; paddi ...

  7. sigprocmask, sigpending, sigsuspend的用法

    sigset_t set sigemptyset(&set) :清空阻塞信号集合变量 sigfillset(&set) :添加所有的信号到阻塞集合变量里 sigaddset(& ...

  8. hdu1533Going Home KM算法

    //给一个n*m的图, //m表示人,h表示房子 //问全部人走回家的最小步数 //每一个人仅仅能进一间房 //非常明显的最大带权匹配 //每一个人到每每间房的距离即为权值 //因为是求最小,仅仅要改 ...

  9. Eclipse怎么导入外来项目

    从File中点击------>import----->General------>然后按下面的图片显示

  10. js插件---JS表格组件BootstrapTable行内编辑解决方案x-editable

    js插件---JS表格组件BootstrapTable行内编辑解决方案x-editable 一.总结 一句话总结:bootstrap能够做为最火的框架,绝对不仅仅只有我看到的位置,它应该还有很多位置可 ...