Advertisement
pedrohcdo

Untitled

Jul 21st, 2017
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 19.76 KB | None | 0 0
  1. package com.ecv.socketexample.socket;
  2.  
  3. import android.app.Service;
  4. import android.content.Intent;
  5. import android.os.Binder;
  6. import android.os.Handler;
  7. import android.os.HandlerThread;
  8. import android.os.IBinder;
  9. import android.util.Log;
  10.  
  11. import org.json.JSONException;
  12. import org.json.JSONObject;
  13.  
  14. import java.io.BufferedReader;
  15. import java.io.InputStreamReader;
  16. import java.io.PrintWriter;
  17. import java.net.InetSocketAddress;
  18. import java.net.Socket;
  19. import java.net.SocketAddress;
  20. import java.util.Iterator;
  21. import java.util.concurrent.ConcurrentLinkedQueue;
  22.  
  23. /**
  24.  * Created by pedro on 16/07/17.
  25.  */
  26.  
  27. public class ConnectionService extends Service {
  28.  
  29.     /**
  30.      * Binder
  31.      */
  32.     public class ConnectionBinder extends Binder {
  33.  
  34.         /**
  35.          * Get Service
  36.          * @return
  37.          */
  38.         public ConnectionService getService() {
  39.             return ConnectionService.this;
  40.         }
  41.     }
  42.  
  43.     /**
  44.      * Request Result
  45.      *
  46.      */
  47.     public interface RequestResult {
  48.  
  49.         /** On result */
  50.         public void onResult(int result, String message);
  51.     }
  52.  
  53.     /**
  54.      * Socket Listener
  55.      */
  56.     public interface SocketListener {
  57.  
  58.         /**
  59.          * On Disconnected
  60.          */
  61.         public void onDisconnected();
  62.  
  63.         /**
  64.          * On Received Data
  65.          *
  66.          * @param data
  67.          */
  68.         public void onReceivedData(String data);
  69.     }
  70.  
  71.     /**
  72.      * Message
  73.      */
  74.     public class Message {
  75.  
  76.         //
  77.         String message;
  78.         long dispatchTime;
  79.  
  80.         /**
  81.          * Constructor
  82.          *
  83.          * @param message
  84.          * @param dispatchTime
  85.          */
  86.         public Message(final String message, final long dispatchTime) {
  87.             this.message = message;
  88.             this.dispatchTime = dispatchTime;
  89.         }
  90.     }
  91.  
  92.     //
  93.     ConnectionBinder mBinder = new ConnectionBinder();
  94.     Socket mClientSocket = null;
  95.     volatile int mLoginControl = 0; /* To invalidate invalid connections */
  96.     Handler mHandler;
  97.     volatile SocketListener mSocketListener;
  98.     volatile boolean mConnected = false;
  99.  
  100.     //
  101.     private Socket socket;
  102.     private BufferedReader in = null;
  103.     private PrintWriter out = null;
  104.     private boolean close = true;
  105.     private Thread readThread;
  106.     private volatile long mPingAlarmClock;
  107.  
  108.     //
  109.     final private ConcurrentLinkedQueue<Message> mMessages = new ConcurrentLinkedQueue<>();
  110.  
  111.     /**
  112.      * On bind
  113.      * @param intent
  114.      * @return
  115.      */
  116.     @Override
  117.     public IBinder onBind(Intent intent) {
  118.         return mBinder;
  119.     }
  120.  
  121.     /**
  122.      * On created
  123.      */
  124.     @Override
  125.     public void onCreate() {
  126.         super.onCreate();
  127.         Log.d("LogTest", "Created service");
  128.         //
  129.         HandlerThread thread = new HandlerThread("ConnectionHT", android.os.Process.THREAD_PRIORITY_BACKGROUND);
  130.         thread.start();
  131.         mHandler = new Handler(thread.getLooper());
  132.     }
  133.  
  134.     /**
  135.      * Call runnable
  136.      *
  137.      * @param control
  138.      * @param runnable
  139.      */
  140.     public void callRunnable(final int control, final Runnable runnable) {
  141.         /**
  142.          * Post result to ui thread
  143.          */
  144.         mHandler.post(new Runnable() {
  145.             @Override
  146.             public void run() {
  147.                 if(mLoginControl == control)
  148.                     runnable.run();
  149.             }
  150.         });
  151.     }
  152.  
  153.     /**
  154.      * Dispatch Message
  155.      *
  156.      * @param message
  157.      * @param delayed
  158.      */
  159.     public void dispatchMessage(final String message, final int delayed, final int control) {
  160.         if(control == mLoginControl)
  161.           mMessages.add(new Message(message, System.currentTimeMillis() + delayed));
  162.     }
  163.  
  164.     /**
  165.      * Dispatch Message
  166.      *
  167.      * @param message
  168.      */
  169.     public void dispatchMessage(final String message, final int control) {
  170.         if(control == mLoginControl)
  171.             mMessages.add(new Message(message, System.currentTimeMillis()));
  172.     }
  173.  
  174.     /**
  175.      * Ping Socket
  176.      */
  177.     private void pingSocket(final PrintWriter out, final int control) {
  178.         // Heartbeat JSON
  179.         final JSONObject heartbeatJson = new JSONObject();
  180.         try {
  181.             heartbeatJson.put("action", "ping");
  182.         } catch (Exception e) {
  183.             Log.d("LogTest", "Error on make json.");
  184.         }
  185.         //
  186.         dispatchMessage(heartbeatJson.toString(), ConnectUtils.HEARTBEAT_TIME, control);
  187.         // Set Alarm
  188.         mPingAlarmClock = System.currentTimeMillis() + ConnectUtils.HEARTBEAT_ALARM_CLOCK;
  189.         //
  190.         final long setPing = mPingAlarmClock;
  191.         // Set Alarm Checker
  192.         mHandler.postDelayed(new Runnable() {
  193.             @Override
  194.             public void run() {
  195.                 if(mLoginControl == control && mPingAlarmClock <= setPing) {
  196.                     if(mSocketListener != null)
  197.                         mSocketListener.onDisconnected();
  198.                 }
  199.             }
  200.         }, ConnectUtils.HEARTBEAT_ALARM_CLOCK + 100);
  201.     }
  202.  
  203.     /**
  204.      * Start Receiver Thread
  205.      */
  206.     public void startSocketControlThread(final BufferedReader in, final PrintWriter out, final int control) {
  207.         //
  208.         new Thread(new Runnable() {
  209.  
  210.             /**
  211.              * Run
  212.              */
  213.             @Override
  214.             public void run() {
  215.                 // First Heartbeat
  216.                 Log.d("LogTest", "First ping");
  217.                 pingSocket(out, control);
  218.                 //
  219.                 while(true) {
  220.                     //
  221.                     if(mLoginControl != control) break;
  222.                     //
  223.                     try {
  224.                         // This if is to read if have mReceiver
  225.                         if(mSocketListener != null) {
  226.                             String data = ConnectUtils.readText(in, 10000);
  227.                             Log.d("LogTest", "Received data: " + data);
  228.                             // This if is to prevent read delay
  229.                             if(mSocketListener != null && mLoginControl == control) {
  230.                                 boolean consumed = false;
  231.                                 try {
  232.                                     JSONObject receivedJson = new JSONObject(data);
  233.                                     if(!receivedJson.isNull("messageType")) {
  234.                                         final String type = receivedJson.getString("messageType");
  235.                                         if (type.equals("pong")) {
  236.                                             Log.d("LogTest", "Received pong.");
  237.                                             pingSocket(out, control);
  238.                                             consumed = true;
  239.                                         }
  240.                                     }
  241.                                 } catch (Exception e) {}
  242.                                 if(!consumed) {
  243.                                     mSocketListener.onReceivedData(data);
  244.                                 } else {
  245.                                     Log.d("LogTest", "Consumed message " + data + " from server.");
  246.                                 }
  247.                             }
  248.                         }
  249.  
  250.                         // Dispatch messages
  251.                         while(mMessages.size() > 0) {
  252.                             Iterator<Message> itr = mMessages.iterator();
  253.                             while(itr.hasNext()) {
  254.                                 final Message m = itr.next();
  255.                                 if(System.currentTimeMillis() > m.dispatchTime) {
  256.                                     out.println(m.message);
  257.                                     out.flush();
  258.                                     itr.remove();
  259.                                     //
  260.                                     Log.d("LogTest", "Dispatched message to server " + m.message);
  261.                                 }
  262.                             }
  263.                         }
  264.                     } catch (Exception e) {
  265.  
  266.                     }
  267.  
  268.                     //
  269.                     try {
  270.                         Thread.sleep(10);
  271.                     } catch (Exception e) {
  272.                         // If error on sleep break this while(true){..}
  273.                         break;
  274.                     }
  275.                 }
  276.             }
  277.         }).start();
  278.     }
  279.  
  280.     /**
  281.      * It starts the login process, if this function is called twice or more times overlapping
  282.      * login processes that were in progress, it is prepared to ignore the previous results using
  283.      * the login control.
  284.      *
  285.      * @param accountNumber
  286.      * @param imei
  287.      * @param password
  288.      */
  289.     public void startLogin(final String accountNumber, final String imei, final String password, final RequestResult runnable) {
  290.         /** Invalidate others logins (if have) */
  291.         mLoginControl++;
  292.         final int control = mLoginControl;
  293.         mClientSocket = null;
  294.         mConnected = false;
  295.         /** Start new login thread */
  296.         new Thread(new Runnable() {
  297.  
  298.             /**
  299.              * Run
  300.              */
  301.             @Override
  302.             public void run() {
  303.                 try {
  304.                     Log.d("LogTest", "Created address");
  305.                     SocketAddress socketAddress = new InetSocketAddress(ConnectUtils.HOST, ConnectUtils.POST);
  306.                     socket = new Socket();
  307.                     Log.d("LogTest", "Start connecting");
  308.                     socket.connect(socketAddress, 10000);
  309.                     Log.d("LogTest", "End connecting");
  310.  
  311.                     //
  312.                     if(socket.isConnected()) {
  313.                         Log.d("LogTest", "A");
  314.  
  315.                         in = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
  316.                         out = new PrintWriter(socket.getOutputStream());
  317.  
  318.  
  319.                         Log.d("LogTest", "B");
  320.                         //
  321.                         JSONObject json = new JSONObject();
  322.                         json.put("action", "login");
  323.                         json.put("language", "zn_CN");
  324.                         json.put("accountNumber", accountNumber);
  325.                         json.put("imei", imei);
  326.                         json.put("password", password);
  327.  
  328.                         Log.d("LogTest", "C: " + json.toString());
  329.                         // Start login
  330.                         out.println(json.toString());
  331.                         out.flush();
  332.  
  333.                         Log.d("LogTest", "D");
  334.                         // Wait 20s
  335.                         final String received = ConnectUtils.readText(in, 100000);
  336.                         Log.d("LogTest", "E");
  337.                         //
  338.                         try {
  339.                             //
  340.                             Log.d("LogTest", "Received: " + received);
  341.  
  342.                             final JSONObject receivedJson = new JSONObject(received);
  343.                             Log.d("LogTest", "F");
  344.                             String flag = receivedJson.getString("flag");
  345.  
  346.                             if(flag.trim().equals("00")) {
  347.                                 //
  348.                                 callRunnable(control, new Runnable() {
  349.                                     @Override
  350.                                     public void run() {
  351.                                         mConnected = true;
  352.                                         mClientSocket = socket;
  353.                                         // Start receiver thread
  354.                                         startSocketControlThread(in, out, control);
  355.                                         // Ok
  356.                                         runnable.onResult(1, "Just here, okay: " + receivedJson);
  357.                                     }
  358.                                 });
  359.                             } else {
  360.                                 //
  361.                                 callRunnable(control, new Runnable() {
  362.                                     @Override
  363.                                     public void run() {
  364.                                         mConnected = false;
  365.                                         mClientSocket = null;
  366.                                         runnable.onResult(-1, "Wrong loging account: " + receivedJson);
  367.                                     }
  368.                                 });
  369.                             }
  370.                         } catch (JSONException jsonE) {
  371.                             Log.d("LogTest", "Error: " + jsonE);
  372.  
  373.                             callRunnable(control, new Runnable() {
  374.                                 @Override
  375.                                 public void run() {
  376.                                     runnable.onResult(-1, "Could not recognize data received after login: " + received);
  377.                                 }
  378.                             });
  379.                         }
  380.                         Log.d("LogTest", "G");
  381.                     } else {
  382.                         callRunnable(control, new Runnable() {
  383.                             @Override
  384.                             public void run() {
  385.                                 runnable.onResult(-1, "Could not connect to socket.");
  386.                             }
  387.                         });
  388.                     }
  389.  
  390.  
  391.                     //
  392.                 } catch (final Exception e) {
  393.                     callRunnable(control, new Runnable() {
  394.                         @Override
  395.                         public void run() {
  396.                             runnable.onResult(-1, "Error on connect (" + accountNumber + ", " + imei + ", " + password + ") with control " + control + " and global control " + mLoginControl + ". Error: " + e.getMessage());
  397.                         }
  398.                     });
  399.                 }
  400.             }
  401.         }).start();
  402.     }
  403.  
  404.     /**
  405.      * It starts the reconnection process, if this function is called twice or more times overlapping
  406.      * login processes that were in progress, it is prepared to ignore the previous results using
  407.      * the login control.
  408.      *
  409.      * @param accountNumber
  410.      * @param imei
  411.      * @param password
  412.      */
  413.     public void startReconnection(final String accountNumber, final String imei, final String password, final RequestResult runnable) {
  414.         /** Invalidate others logins (if have) */
  415.         mLoginControl++;
  416.         final int control = mLoginControl;
  417.         mClientSocket = null;
  418.         mConnected = false;
  419.         /** Start new login thread */
  420.         new Thread(new Runnable() {
  421.  
  422.             /**
  423.              * Run
  424.              */
  425.             @Override
  426.             public void run() {
  427.                 try {
  428.                     Log.d("LogTest", "Created address");
  429.                     SocketAddress socketAddress = new InetSocketAddress(ConnectUtils.HOST, ConnectUtils.POST);
  430.                     socket = new Socket();
  431.                     Log.d("LogTest", "Start connecting");
  432.                     socket.connect(socketAddress, 10000);
  433.                     Log.d("LogTest", "End connecting");
  434.  
  435.                     //
  436.                     if(socket.isConnected()) {
  437.                         Log.d("LogTest", "A");
  438.  
  439.                         in = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
  440.                         out = new PrintWriter(socket.getOutputStream());
  441.  
  442.  
  443.                         Log.d("LogTest", "B");
  444.                         //
  445.                         JSONObject json = new JSONObject();
  446.                         json.put("action", "reconnect");
  447.                         json.put("language", "zn_CN");
  448.                         json.put("accountNumber", accountNumber);
  449.                         json.put("imei", imei);
  450.                         json.put("password", password);
  451.  
  452.                         Log.d("LogTest", "C: " + json.toString());
  453.                         // Start login
  454.                         out.println(json.toString());
  455.                         out.flush();
  456.  
  457.                         Log.d("LogTest", "D");
  458.                         // Wait 20s
  459.                         final String received = ConnectUtils.readText(in, 100000);
  460.                         Log.d("LogTest", "E");
  461.                         //
  462.                         try {
  463.                             //
  464.                             Log.d("LogTest", "Received: " + received);
  465.  
  466.                             final JSONObject receivedJson = new JSONObject(received);
  467.                             Log.d("LogTest", "F");
  468.                             String flag = receivedJson.getString("flag");
  469.  
  470.                             if(flag.trim().equals("00")) {
  471.                                 //
  472.                                 callRunnable(control, new Runnable() {
  473.                                     @Override
  474.                                     public void run() {
  475.                                         mConnected = true;
  476.                                         mClientSocket = socket;
  477.                                         // Start receiver thread
  478.                                         startSocketControlThread(in, out, control);
  479.                                         // Ok
  480.                                         runnable.onResult(1, "Just here, okay: " + receivedJson);
  481.                                     }
  482.                                 });
  483.                             } else {
  484.                                 //
  485.                                 callRunnable(control, new Runnable() {
  486.                                     @Override
  487.                                     public void run() {
  488.                                         mConnected = false;
  489.                                         mClientSocket = null;
  490.                                         runnable.onResult(-1, "Wrong loging account: " + receivedJson);
  491.                                     }
  492.                                 });
  493.                             }
  494.                         } catch (JSONException jsonE) {
  495.                             Log.d("LogTest", "Error: " + jsonE);
  496.  
  497.                             callRunnable(control, new Runnable() {
  498.                                 @Override
  499.                                 public void run() {
  500.                                     runnable.onResult(-1, "Could not recognize data received after login: " + received);
  501.                                 }
  502.                             });
  503.                         }
  504.                         Log.d("LogTest", "G");
  505.                     } else {
  506.                         callRunnable(control, new Runnable() {
  507.                             @Override
  508.                             public void run() {
  509.                                 runnable.onResult(-1, "Could not connect to socket.");
  510.                             }
  511.                         });
  512.                     }
  513.  
  514.  
  515.                     //
  516.                 } catch (final Exception e) {
  517.                     callRunnable(control, new Runnable() {
  518.                         @Override
  519.                         public void run() {
  520.                             runnable.onResult(-1, "Error on connect (" + accountNumber + ", " + imei + ", " + password + ") with control " + control + " and global control " + mLoginControl + ". Error: " + e.getMessage());
  521.                         }
  522.                     });
  523.                 }
  524.             }
  525.         }).start();
  526.     }
  527.  
  528.     /**
  529.      * Logout
  530.      */
  531.     public void logout() {
  532.         mLoginControl++;
  533.         mClientSocket = null;
  534.         mConnected = false;
  535.         in = null;
  536.         out = null;
  537.     }
  538.  
  539.     /**
  540.      * Is connected
  541.      *
  542.      * @return
  543.      */
  544.     public boolean isConnected() {
  545.         return mConnected && mClientSocket != null;
  546.     }
  547.  
  548.     /**
  549.      * Set Receiver
  550.      *
  551.      * @param listener
  552.      */
  553.     public void setSocketListener(final SocketListener listener) {
  554.         mSocketListener = listener;
  555.     }
  556. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement