Advertisement
pedrohcdo

Untitled

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