|
|
@@ -0,0 +1,339 @@
|
|
|
+package com.qy.agv.receiver;
|
|
|
+
|
|
|
+import static com.qy.agv.util.Constant.TIME_FORMATE;
|
|
|
+
|
|
|
+import android.app.Service;
|
|
|
+import android.content.Intent;
|
|
|
+import android.os.Binder;
|
|
|
+import android.os.Handler;
|
|
|
+import android.os.IBinder;
|
|
|
+import android.os.Looper;
|
|
|
+import android.util.Log;
|
|
|
+import android.widget.Toast;
|
|
|
+
|
|
|
+import com.qy.agv.util.Constant;
|
|
|
+import com.qy.agv.util.DateUtil;
|
|
|
+import com.qy.agv.util.StringUtils;
|
|
|
+
|
|
|
+import org.apache.log4j.Logger;
|
|
|
+import java.io.BufferedReader;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStreamReader;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.net.ConnectException;
|
|
|
+import java.net.InetSocketAddress;
|
|
|
+import java.net.NoRouteToHostException;
|
|
|
+import java.net.Socket;
|
|
|
+import java.net.SocketException;
|
|
|
+import java.net.SocketTimeoutException;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.Timer;
|
|
|
+import java.util.TimerTask;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * <p>
|
|
|
+ * socket连接服务
|
|
|
+ */
|
|
|
+public class SocketService extends Service {
|
|
|
+
|
|
|
+ /*socket*/
|
|
|
+ private Socket socket;
|
|
|
+ /*连接线程*/
|
|
|
+ private Thread connectThread;
|
|
|
+ private Timer timer = new Timer();
|
|
|
+ private OutputStream outputStream;
|
|
|
+
|
|
|
+ private final SocketBinder sockerBinder = new SocketBinder();
|
|
|
+ private TimerTask task;
|
|
|
+
|
|
|
+ /*默认重连*/
|
|
|
+ private boolean isReConnect = true;
|
|
|
+ private final Handler handler = new Handler(Looper.getMainLooper());
|
|
|
+ public static Logger mylog =Logger.getLogger(SocketService.class);
|
|
|
+ private final Intent intent = new Intent(Constant.RECEIVER_MSG);
|
|
|
+ private Long lastTime = 0L;
|
|
|
+ private int socket_port;
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public IBinder onBind(Intent intent) {
|
|
|
+ return sockerBinder;
|
|
|
+ }
|
|
|
+
|
|
|
+ public class SocketBinder extends Binder {
|
|
|
+ /*返回SocketService 在需要的地方可以通过ServiceConnection获取到SocketService */
|
|
|
+ public SocketService getService() {
|
|
|
+ return SocketService.this;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onCreate() {
|
|
|
+ super.onCreate();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int onStartCommand(Intent intent, int flags, int startId) {
|
|
|
+ /*初始化socket*/
|
|
|
+ try {
|
|
|
+ if(Constant.robotModel != null
|
|
|
+ && !StringUtils.isEmpty(Constant.robotModel.getRobotIp())) {
|
|
|
+ initSocket();
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return super.onStartCommand(intent, flags, startId);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*初始化socket*/
|
|
|
+ private void initSocket() {
|
|
|
+ if (socket == null && connectThread == null) {
|
|
|
+ connectThread = new Thread(new Runnable() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+
|
|
|
+ socket = new Socket();
|
|
|
+ try {
|
|
|
+ /*超时时间为2秒*/
|
|
|
+ socket.connect(new InetSocketAddress(Constant.robotModel.getRobotIp(), Constant.robotModel.getPort()), 5000);
|
|
|
+ /*连接成功的话 发送心跳包*/
|
|
|
+ if (socket.isConnected()) {
|
|
|
+ /*因为Toast是要运行在主线程的 这里是子线程 所以需要到主线程哪里去显示toast*/
|
|
|
+ toastMsg("网络连接成功");
|
|
|
+ System.out.println("==========注册信息==========");
|
|
|
+ sendOrder("register:" + Constant.robotModel.getRobotId());
|
|
|
+ /*发送心跳数据*/
|
|
|
+ System.out.println("==========发送心跳==========");
|
|
|
+ lastTime = System.currentTimeMillis();
|
|
|
+ sendBeatData();
|
|
|
+
|
|
|
+ new Thread(new Runnable() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ rec();
|
|
|
+ }
|
|
|
+ }).start();
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ if (e instanceof SocketTimeoutException) {
|
|
|
+ mylog.error("连接超时,正在重连");
|
|
|
+ showMsg("连接失败");
|
|
|
+ try {
|
|
|
+ Thread.sleep(1000);
|
|
|
+ } catch (InterruptedException ex) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ releaseSocket();
|
|
|
+
|
|
|
+ } else if (e instanceof NoRouteToHostException) {
|
|
|
+ mylog.error("地址不存在,请检查");
|
|
|
+ showMsg("连接失败");
|
|
|
+ stopSelf();
|
|
|
+
|
|
|
+ } else if (e instanceof ConnectException) {
|
|
|
+ mylog.error("连接异常或被拒绝,请检查");
|
|
|
+ showMsg("连接失败");
|
|
|
+ try {
|
|
|
+ Thread.sleep(5000);
|
|
|
+ } catch (InterruptedException ex) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ releaseSocket();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ /*启动连接线程*/
|
|
|
+ connectThread.start();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void showMsg(String msg){
|
|
|
+// intent.putExtra("msg", msg);
|
|
|
+// intent.putExtra("json","");
|
|
|
+// sendBroadcast(intent);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void showCommand(String msg){
|
|
|
+ intent.putExtra("json", msg);
|
|
|
+ sendBroadcast(intent);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*因为Toast是要运行在主线程的 所以需要到主线程哪里去显示toast*/
|
|
|
+ private void toastMsg(final String msg) {
|
|
|
+ handler.post(new Runnable() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public void sendToRobot(String toRobot, String msg){
|
|
|
+ msg = toRobot + ":" + msg;
|
|
|
+ sendOrder(msg);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void sendToServer(String msg){
|
|
|
+ msg = "execute:" + msg;
|
|
|
+ sendOrder(msg);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*发送数据*/
|
|
|
+ public void sendOrder(final String json) {
|
|
|
+ if (socket != null && socket.isConnected()) {
|
|
|
+ /*发送指令*/
|
|
|
+ new Thread(new Runnable() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ try {
|
|
|
+ tcpClient(json, 0);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).start();
|
|
|
+ } else {
|
|
|
+ toastMsg("机器人连接错误,请重试");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*定时发送数据*/
|
|
|
+ private void sendBeatData() {
|
|
|
+ if (timer == null) {
|
|
|
+ timer = new Timer();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (task == null) {
|
|
|
+ task = new TimerTask() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ try {
|
|
|
+ outputStream = socket.getOutputStream();
|
|
|
+ /*这里的编码方式根据你的需求去改*/
|
|
|
+ long longTime = System.currentTimeMillis() - lastTime;
|
|
|
+ if(longTime > 70000){
|
|
|
+ releaseSocket();
|
|
|
+ }
|
|
|
+ String msg = "ping:" + DateUtil.getCurrDate(TIME_FORMATE);
|
|
|
+ outputStream.write((msg+"\n").getBytes(StandardCharsets.UTF_8));
|
|
|
+ outputStream.flush();
|
|
|
+ showMsg("连接成功");
|
|
|
+ } catch (Exception e) {
|
|
|
+ /*发送失败说明socket断开了或者出现了其他错误*/
|
|
|
+ toastMsg("连接断开,正在重连");
|
|
|
+ showMsg("连接中断");
|
|
|
+ /*重连*/
|
|
|
+ releaseSocket();
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+ timer.schedule(task, 0, 10000);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void rec(){
|
|
|
+ try{
|
|
|
+ while (true) {
|
|
|
+ if(socket!=null && !socket.isInputShutdown()) {
|
|
|
+ try {
|
|
|
+ BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
|
|
+ String inMsg = in.readLine();//服务器返回的数据
|
|
|
+ if (StringUtils.isEmpty(inMsg)) {
|
|
|
+ socket = null;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ inMsg = inMsg + System.getProperty("line.separator");
|
|
|
+ inMsg = inMsg.replace("\n", "");
|
|
|
+ if (inMsg.equals("pong")
|
|
|
+ || inMsg.equals("ok")) {
|
|
|
+ lastTime = System.currentTimeMillis();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ mylog.info("received: " + inMsg);
|
|
|
+ if (!StringUtils.isEmpty(inMsg)) {
|
|
|
+ showCommand(inMsg);
|
|
|
+ }
|
|
|
+ }catch (Exception ex){
|
|
|
+ mylog.error(ex);
|
|
|
+ ex.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void tcpClient(String json, int flag){
|
|
|
+ try{
|
|
|
+ outputStream = socket.getOutputStream();
|
|
|
+ outputStream.write((json+"\n").getBytes(StandardCharsets.UTF_8));
|
|
|
+ outputStream.flush();
|
|
|
+ mylog.info("发送数据有效");
|
|
|
+ }catch (SocketException ex){
|
|
|
+ System.out.println("发送异常,重新连接网络");
|
|
|
+ releaseSocket();
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*释放资源*/
|
|
|
+ private void releaseSocket() {
|
|
|
+
|
|
|
+ if (task != null) {
|
|
|
+ task.cancel();
|
|
|
+ task = null;
|
|
|
+ }
|
|
|
+ if (timer != null) {
|
|
|
+ timer.purge();
|
|
|
+ timer.cancel();
|
|
|
+ timer = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (outputStream != null) {
|
|
|
+ try {
|
|
|
+ outputStream.close();
|
|
|
+
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ outputStream = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (socket != null) {
|
|
|
+ try {
|
|
|
+ socket.close();
|
|
|
+
|
|
|
+ } catch (IOException e) {
|
|
|
+ }
|
|
|
+ socket = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (connectThread != null) {
|
|
|
+ connectThread = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*重新初始化socket*/
|
|
|
+ if (isReConnect) {
|
|
|
+ initSocket();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onDestroy() {
|
|
|
+ super.onDestroy();
|
|
|
+ Log.i("SocketService", "onDestroy");
|
|
|
+ isReConnect = false;
|
|
|
+ releaseSocket();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|