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); } }
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); }}java