AndroidV5包源码解析

2022 年 4 月 26 日 星期二(已编辑)
/
289
这篇文章上次修改于 2022 年 5 月 5 日 星期四,可能部分内容已经不适用,如有疑问可询问作者。

AndroidV5包源码解析

今年智能家居安装与维护中职组省赛还有1个多月就要开始了,作为一名负责Android开发的蒟蒻,来介绍一下刚更新的SmartHomeV5包源码吧~

其实V5包的源码并不难理解,结合代码片段的注释是很好理解的,我先给出我所写好的示例

示例

public class MainActivity extends AppCompatActivity {
    String name,time;
    double temperature,humidity,illumination;
    Handler handler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findView();
    }

    private void findView() {
        //连接服务器
        ControlUtils.setUser("bizideal", "123456", "127.0.0.1");
        SocketClient.getInstance().creatConnect();
        SocketClient.getInstance().login(new LoginCallback() {
            @Override
            public void onEvent(String var1) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (var1.equals(ConstantUtil.Success)) {
                            Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_SHORT).show();
                        } else if (var1.equals(ConstantUtil.Reconnect)){
                            Toast.makeText(MainActivity.this, "重新连接", Toast.LENGTH_SHORT).show();
                        }else {
                            Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        });
        
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                //单控
                ControlUtils.control("WarningLight", "10", ConstantUtil.CmdCode_1, ConstantUtil.Channel_ALL, ConstantUtil.Open);

                //获取数据
                ControlUtils.getData();
                ControlUtils.getFaceData();
                SocketClient.getInstance().getData(new DataCallback<DeviceBean>() {
                    @SuppressLint("HandlerLeak")
                    @Override
                    public void onResult(DeviceBean deviceBean) {
                        try {
                            if (!TextUtils.isEmpty(deviceBean.getTime())){
                                time = deviceBean.getTime();
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        try {
                            if (!TextUtils.isEmpty(deviceBean.getName())){
                                name = deviceBean.getName();
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        if (deviceBean.getDevice().size() > 0){
                            for (int i = 0; i < deviceBean.getDevice().size(); i++) {
                                try {
                                    if (deviceBean.getDevice().get(i).getBoardId().equals("1")){
                                        if (deviceBean.getDevice().get(i).getSensorType().equals(ConstantUtil.Illumination)){
                                            temperature = Double.parseDouble(deviceBean.getDevice().get(i).getValue());
                                        }else{
                                            humidity = Double.parseDouble(deviceBean.getDevice().get(i).getValue());
                                        }
                                    }
                                } catch (NumberFormatException e) {
                                    e.printStackTrace();
                                }

                                try {
                                    if (deviceBean.getDevice().get(i).getBoardId().equals("2")){
                                        illumination = Double.parseDouble(deviceBean.getDevice().get(i).getValue());
                                    }
                                } catch (NumberFormatException e) {
                                    e.printStackTrace();
                                }
                            }
                        }

                    }
                });
            }
        },500);
    }
}

连接服务器代码解析

好了话不多说,我们看看连接服务器的代码

//连接服务器
ControlUtils.setUser("bizideal", "123456", "127.0.0.1");
SocketClient.getInstance().creatConnect();
SocketClient.getInstance().login(new LoginCallback() {
    @Override
    public void onEvent(String var1) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (var1.equals(ConstantUtil.Success)) {
                    Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_SHORT).show();
                } else if (var1.equals(ConstantUtil.Reconnect)){
                    Toast.makeText(MainActivity.this, "重新连接", Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
});

别看这只有几行代码,其实已经执行完V5包里几乎全部的代码了

creatConnect()方法

单例模式的运用

我们进入登录的SocketClient.getInstance().creatConnect();的里面,这里涉及到一个单例模式,实例化唯一的SocketClient对象。

//我们调用SocketClient.getInstance().XXXX()的时候这个方法都会被调用,也就是单例模式,用来实例化唯一的SocketClient对象
  public static SocketClient getInstance() {
      if (null == mInstance) {
          mInstance = new SocketClient();
      }
      return mInstance;
  }

启动InitSocketThread线程

接着我们看到如下,请仔细观看注释注意:通过源码我们可以看出,我们写代码每执行SocketClient.getInstance().creatConnect()就会断开一下与服务器的连接,因此请不要把这句话放在Fragment里或者多次执行

//如果之前已经连接过服务器,再次调用creatConnect()会断开现有连接再重新连接服务器,因此creatConnect()要谨慎调用
public boolean creatConnect() {
    //第一次创建则为空,因此会执行InitSocketThread()的线程
    if (this.mSocket == null) {
        //开启连接服务器线程
        (new SocketClient.InitSocketThread()).start();
    } else {
        //用来断开与服务器连接。
        this.release();
        //开启连接服务器线程
        (new SocketClient.InitSocketThread()).start();
    }

    return false;
}

我们假设初次调用creatConnect()方法,便会开启(new SocketClient.InitSocketThread()).start()线程,

如下我们进入这个线程,这个线程意义不大,直接调用了SocketClient.this.initSocket()方法

//执行initSocket()方法用的
class InitSocketThread extends Thread {
    InitSocketThread() {
    }

    public void run() {
        super.run();
        SocketClient.this.initSocket();
    }
}

V5包核心initSocket()方法

如下我们进入SocketClient.this.initSocket()方法,这是整个V5包的核心代码,请仔细仔细再仔细阅读注释

//V5源码的核心方法!!!!
private void initSocket() {
    try {
        //创建并实例化socket
        Socket socket = new Socket();
        //连接服务器,ip为我们之前 "ControlUtils.setUser("bizideal", "123456", "127.0.0.1");" 中的"127.0.0.1",端口号是定死的(6006)无法更改
        socket.connect(new InetSocketAddress(ip, this.port), 3000);
        //把已经连接服务器的socket赋值给全局的 mSocket。这里的mSocket和Socket是弱引用,不严谨的说可以直接理解为创建Socket实例对象
        this.mSocket = new WeakReference(socket);
        //把我们的之前 "ControlUtils.setUser("bizideal", "123456", "127.0.0.1");" 中的 "bizideal", "123456" 发送给服务器,可以去看sendData()
        ControlUtils.getData();
        //实例化ReadThread对象,ReadThread的线程是用来获取服务器数据的
        this.mReadThread = new SocketClient.ReadThread((Socket)this.mSocket.get());
        //启动实例化ReadThread线程,获取服务器数据的
        this.mReadThread.start();
        //执行心跳包,检测是否掉线
        this.mHandler.postDelayed(this.heartBeatRunnable, 10000L);
        //成功连接服务器则都不为空
        if (this.mSocket != null && this.mLoginCallback != null) {
            //根据ConstantUtil,会Toast连接成功
            this.mLoginCallback.onEvent("0");
        }
    } catch (IOException var2) {
        if (this.mLoginCallback != null) {
            //根据ConstantUtil,会Toast连接失败,无法连接服务器
            this.mLoginCallback.onEvent("1");
        }
        //断开服务器连接
        this.disConnect(this.mSocket);
    }
}

上面代码可能比较难理解,不过我们可以把它拆分成3部分

  1. ControlUtils.getData();请求数据

  2. this.mReadThread = new SocketClient.ReadThread((Socket)this.mSocket.get());this.mReadThread.start();接收数据

    1. this.mHandler.postDelayed(this.heartBeatRunnable, 10000L);心跳包检测连接服务器状态
请求数据

进入ControlUtils.getData()里,这里比较简单,就是发送JSON请求给服务器,表明需要得到数据

//数据采集
public static boolean getData() {
    try {
        JSONObject object = new JSONObject();
        object.put("Type", "GetDevicState");
        object.put("UserName", mUserName);
        object.put("Password", mPassword);
        object.put("CurrentTime", (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date()));
        //把JSON请求发送给服务器
        SocketClient.getInstance().sendData(object.toString());
    } catch (JSONException var1) {
        var1.printStackTrace();
    }
    return true;
}

接着进入SocketClient.getInstance().sendData(object.toString());仔细观看注释,发送数据给服务器其中 msg 是刚刚在ControlUtils中创建的 JSON 数据,最终会将这个数据发送给服务器。另外注意SocketClient.this.sendTime = System.currentTimeMillis()获取发送数据的时间,在第三部分心跳包检测会用的。OK非常简单,第一部分发送数据就是这个流程。

//发送数据给服务器其中 msg 是在ControlUtils中创建的 JSON 数据,这里的boolean返回值后续会用做“心跳包“检测
   public boolean sendData(final String msg) {
       //老规矩检查你是否连接了服务器
       if (null != this.mSocket && null != this.mSocket.get()) {
           //把全局 mSocket 赋值给局部的 soc
           final Socket soc = (Socket)this.mSocket.get();

           try {
               //老规矩检查你是否连接了服务器
               if (!soc.isClosed() && !soc.isOutputShutdown()) {
                   //用流来发送数据,不过多解释
                   (new Thread(new Runnable() {
                       public void run() {
                           try {
                               //用流来发送数据,不过多解释
                               PrintWriter DataWrite = new PrintWriter(soc.getOutputStream());
                               DataWrite.write(msg + "\r\n");
                               DataWrite.flush();
                               //isSocket是用来判断是否发送成功的
                               SocketClient.this.isSocket = true;
                               //sendTime获取发送数据的时间,会在另一个线程使用到,判断连接状态
                               SocketClient.this.sendTime = System.currentTimeMillis();
                           } catch (IOException var2) {
                               var2.printStackTrace();
                               //isSocket是用来判断是否发送成功的
                               SocketClient.this.isSocket = false;
                           }
                       }
                   })).start();
               } else {
                   //isSocket是用来判断是否发送成功的
                   this.isSocket = false;
               }
           } catch (Exception var4) {
               var4.printStackTrace();
               //isSocket是用来判断是否发送成功的
               this.isSocket = false;
           }
           //isSocket是用来判断是否发送成功的
           return this.isSocket;
       } else {
           return false;
       }
   }
接收数据

我们回到V5包的核心initSocket方法,看到如下代码,其中ReadThread就是用来接收数据的

//实例化ReadThread对象,ReadThread的线程是用来获取服务器数据的
this.mReadThread = new SocketClient.ReadThread((Socket)this.mSocket.get());
//启动实例化ReadThread线程,获取服务器数据的
this.mReadThread.start();

进入上方ReadThread这个线程,仔细观看注释,这个线程往往使用来响应刚才的请求数据,用来读取服务器发送给我们的数据,会得到一串服务器响应给我们的JSON数据,最后交给SocketClient.this.setData(obj)解析,最终赋值到DeviceBean这个类中,供我们直接使用。

//获取服务器数据
    private class ReadThread extends Thread {
        //弱引用局部Socket
        private WeakReference<Socket> mWeakSocket;
        private boolean isStart = true;

        public ReadThread(Socket socket) {
            //转移全局Socket
            this.mWeakSocket = new WeakReference(socket);
        }

        //断开服务器连接
        public void release() {
            this.isStart = false;
            //断开服务器连接
            SocketClient.this.disConnect(this.mWeakSocket);
        }
        //获取服务器数据
        public void run() {
            super.run();
            //梅开n度,把局部的mWeakSocket转移给线程内的socket
            Socket socket = (Socket)this.mWeakSocket.get();
            //判空
            if (socket != null) {
                try {
                    String response = "";
                    //读取服务器数据
                    BufferedReader DataRead = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    //判空
                    while(!socket.isClosed() && this.isStart && !socket.isInputShutdown()) {
                        //判空
                        while((response = DataRead.readLine()) != null) {
                            //获取服务器返回的JSON数据
                            JSONObject obj = new JSONObject(response);
                            //解析服务器JSON数据
                            SocketClient.this.setData(obj);
                        }
                    }
                } catch (JSONException var5) {
                    var5.printStackTrace();
                } catch (Exception var6) {
                    //未知异常就断开服务器连接
                    this.isStart = false;
                    SocketClient.this.mSocket = null;
                    var6.printStackTrace();
                }
            }

        }
    }

下方是SocketClient.this.setData(obj)解析我们收到的JSON数据,解析完成后,也就是我们MainActivity最终调用SocketClient.getInstance().getData()的数据

//解析服务器返回的JSON数据
public void setData(JSONObject obj) throws JSONException {
    DeviceBean bean = new DeviceBean();
    if (obj.has("Type")) {
        //判断数据是数据采集还是考勤机或心跳包的
        if (!obj.getString("Type").toString().equals("Upload") && !obj.getString("Type").toString().equals("GetDevicState")) {
            //判断是否为考勤机
            if (obj.getString("Type").toString().equals("UploadPersonInfo") || obj.getString("Type").toString().equals("GetCurrentAttendance")) {
                try {
                    if (obj.has("Name")) {
                        //考勤的姓名
                        DeviceBean.setName(obj.getString("Name"));
                    }
                } catch (JSONException var9) {
                }

                try {
                    if (obj.has("Time")) {
                        //考勤的日期
                        DeviceBean.setTime(obj.getString("Time"));
                    }
                } catch (JSONException var8) {
                }

                if (mDataCallback != null) {
                    mDataCallback.onResult(bean);
                }
            }
        } else {
            //这里是数据采集的JSON解析
            try {
                //具体怎么解析JSON就不说明了
                ArrayList<Devices> deviceList = new ArrayList();
                JSONArray array = new JSONArray(obj.get("Data").toString());

                for(int i = 0; i < array.length(); ++i) {
                    JSONObject jsonObject = array.getJSONObject(i);
                    Devices devices = new Devices();
                    //数据的值
                    devices.setValue(jsonObject.getString("Value"));
                    //类型
                    devices.setSensorType(jsonObject.getString("SensorType"));
                    //版号
                    devices.setBoardId(jsonObject.getString("BoardId"));

                    deviceList.add(devices);
                }
                //解析完的数据放进DeviceBean集合中
                DeviceBean.setDevice(deviceList);
            } catch (JSONException var10) {
            }

            //如果写了获取数据的回调,就执行可以拿到数据了
            if (mDataCallback != null) {
                mDataCallback.onResult(bean);
            }
        }
    } else if (obj.has("state") && obj.getString("state").toString().equals("Failure") && obj.has("msg") && this.mLoginCallback != null) {
        //未知错误
        this.mLoginCallback.onEvent("5");
    }

}
心跳包检测

我们回到V5包的核心initSocket方法,看到如下代码,这里开启heartBeatRunnable用于心跳包检测,当你超过10秒钟没有发送数据给服务器便会执行,应用服务器心跳检测,简称“心跳包”,检测你是否掉线,其中SocketClient.this.sendTime就是第一部分,请求数据接收的时间

//执行心跳包,检测是否掉线
this.mHandler.postDelayed(this.heartBeatRunnable, 10000L);
//用来开启下方 heartBeatRunnable 线程,详情看initSocket()方法
private Handler mHandler = new Handler();
//配合上方mHandler开启线程 详情看initSocket()方法
//判断你是否掉线
private Runnable heartBeatRunnable = new Runnable() {
    public void run() {
        try {
            //当你超过10秒钟没有发送数据给服务器变会执行,应用服务器心跳检测,简称“心跳包”,检测你是否掉线,SocketClient.this.sendTime就是第一部分,请求数据接收的时间
            if (System.currentTimeMillis() - SocketClient.this.sendTime >= 10000L) {
                //发送心跳包
                boolean isSuccess = SocketClient.this.sendData("{\"Type\": \"HeartBeat\"}");
                //如果掉线
                if (!isSuccess) {
                    //如果你调用了LoginCallback回调,就!=null
                    if (SocketClient.this.mLoginCallback != null) {
                        //根据ConstantUtil的  public static String Reconnect = "2"; 会Toast出“重新连接"
                        SocketClient.this.mLoginCallback.onEvent("2");
                    }
                    //停止这个heartBeatRunnable线程
                    SocketClient.this.mHandler.removeCallbacks(SocketClient.this.heartBeatRunnable);
                    //断开服务器连接
                    SocketClient.this.mReadThread.release();
                    //重新建立服务器连接
                    (SocketClient.this.new InitSocketThread()).start();
                }
            }
            //以每15秒频率重复执行心跳包
            SocketClient.this.mHandler.postDelayed(this, 15000L);
        } catch (Exception var2) {
            var2.printStackTrace();
        }

    }
};
心跳包

心跳包

总结&&源码

以上便是V5包源码的全部核心,剩下一部分没有提到的都很好理解,相信可以做到举一反三吧emmmmm,如果有什么不明白的可以发送邮件到1502972236zwj@gmail.com 与我联系,最后附上全部SocketClien类的源码注释。

package com.bizideal.smarthome.socket;

import android.os.Handler;
import com.bizideal.smarthome.socket.DeviceBean.Devices;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

//V5连接服务器核心类
public class SocketClient {
    //SocketClient(也就是自己)的实例对象
    private static SocketClient mInstance;

    //获取数据回调
    private static DataCallback mDataCallback;

    //创建全局Socket的弱引用,不严谨的说可以直接理解为创建Socket实例对象
    private WeakReference<Socket> mSocket;

   //创建ReadThread对象,ReadThread的线程是用来获取服务器数据的
    public SocketClient.ReadThread mReadThread;

    //每次向服务器发送数据的时间,详情看sendData()方法
    private long sendTime = 0L;

    //ip在 ControlUtils.setUser("bizideal", "123456", "127.0.0.1"); 会对其赋值
    public static String ip = "10.1.3.173";

    //定死的服务器断开号,无法更改
    int port = 6006;

    //登录回调
    private LoginCallback mLoginCallback;

    //没用
    private Boolean isSuccess = false;

    //用来开启下方 heartBeatRunnable 线程,详情看initSocket()方法
    private Handler mHandler = new Handler();
    //配合上方mHandler开启线程 详情看initSocket()方法
    //判断你是否掉线
    private Runnable heartBeatRunnable = new Runnable() {
        public void run() {
            try {
                //当你超过10秒钟没有发送数据给服务器便会执行,应用服务器心跳检测,简称“心跳包”,检测你是否掉线,
                if (System.currentTimeMillis() - SocketClient.this.sendTime >= 10000L) {
                    //发送心跳包
                    boolean isSuccess = SocketClient.this.sendData("{\"Type\": \"HeartBeat\"}");
                    //如果掉线
                    if (!isSuccess) {
                        //如果你调用了LoginCallback回调,就!=null
                        if (SocketClient.this.mLoginCallback != null) {
                            //根据ConstantUtil的  public static String Reconnect = "2"; 会Toast出“重新连接"
                            SocketClient.this.mLoginCallback.onEvent("2");
                        }
                        //停止这个heartBeatRunnable线程
                        SocketClient.this.mHandler.removeCallbacks(SocketClient.this.heartBeatRunnable);
                        //断开服务器连接
                        SocketClient.this.mReadThread.release();
                        //重新建立服务器连接
                        (SocketClient.this.new InitSocketThread()).start();
                    }
                }
                //以每15秒频率重复执行心跳包
                SocketClient.this.mHandler.postDelayed(this, 15000L);
            } catch (Exception var2) {
                var2.printStackTrace();
            }

        }
    };

    //这是一个 flag 用来判断是否成功发送数据给服务器
    private boolean isSocket = false;

    public SocketClient() {
    }

    //我们调用SocketClient.getInstance().XXXX()的时候这个方法都会被调用,也就是单例模式,用来实例化唯一的SocketClient对象
    public static SocketClient getInstance() {
        if (null == mInstance) {
            mInstance = new SocketClient();
        }

        return mInstance;
    }

    public boolean creatConnect() {
        //第一次创建则为空,因此会执行InitSocketThread()的线程
        if (this.mSocket == null) {
            //开启连接服务器线程
            (new SocketClient.InitSocketThread()).start();
        } else {
            //如果之前已经连接过服务器,再次调用creatConnect()会断开现有连接再重新连接服务器,因此creatConnect()要谨慎调用
            this.release();
            //开启连接服务器线程
            (new SocketClient.InitSocketThread()).start();
        }

        return false;
    }

    //V5源码的核心方法!!!!
    private void initSocket() {
        try {
            //创建并实例化socket
            Socket socket = new Socket();
            //连接服务器,ip为我们之前 "ControlUtils.setUser("bizideal", "123456", "127.0.0.1");" 中的"127.0.0.1",端口号是定死的(6006)无法更改
            socket.connect(new InetSocketAddress(ip, this.port), 3000);
            //把已经连接服务器的socket赋值给全局的 mSocket
            this.mSocket = new WeakReference(socket);
            //把我们的之前 "ControlUtils.setUser("bizideal", "123456", "127.0.0.1");" 中的 "bizideal", "123456" 发送给服务器,可以去看sendData()
            ControlUtils.getData();
            //实例化ReadThread对象,ReadThread的线程是用来获取服务器数据的
            this.mReadThread = new SocketClient.ReadThread((Socket)this.mSocket.get());
            //启动实例化ReadThread线程,获取服务器数据的
            this.mReadThread.start();
            //执行心跳包,检测是否掉线
            this.mHandler.postDelayed(this.heartBeatRunnable, 10000L);
            //成功连接服务器则都不为空
            if (this.mSocket != null && this.mLoginCallback != null) {
                //根据ConstantUtil,会Toast连接成功
                this.mLoginCallback.onEvent("0");
            }
        } catch (IOException var2) {
            if (this.mLoginCallback != null) {
                //根据ConstantUtil,会Toast连接失败,无法连接服务器
                this.mLoginCallback.onEvent("1");
            }
            //断开服务器连接
            this.disConnect(this.mSocket);
        }

    }

    //发送数据给服务器其中 msg 是在ControlUtils中创建的 JSON 数据,这里的boolean返回值后续会用做“心跳包“检测
    public boolean sendData(final String msg) {
        //老规矩检查你是否连接了服务器
        if (null != this.mSocket && null != this.mSocket.get()) {
            //把全局 mSocket 赋值给局部的 soc
            final Socket soc = (Socket)this.mSocket.get();

            try {
                //老规矩检查你是否连接了服务器
                if (!soc.isClosed() && !soc.isOutputShutdown()) {
                    //用流来发送数据,不过多解释
                    (new Thread(new Runnable() {
                        public void run() {
                            try {
                                //用流来发送数据,不过多解释
                                PrintWriter DataWrite = new PrintWriter(soc.getOutputStream());
                                DataWrite.write(msg + "\r\n");
                                DataWrite.flush();
                                //isSocket是用来判断是否发送成功的
                                SocketClient.this.isSocket = true;
                                //sendTime获取发送数据的时间,会在另一个线程使用到,判断连接状态
                                SocketClient.this.sendTime = System.currentTimeMillis();
                            } catch (IOException var2) {
                                var2.printStackTrace();
                                //isSocket是用来判断是否发送成功的
                                SocketClient.this.isSocket = false;
                            }
                        }
                    })).start();
                } else {
                    //isSocket是用来判断是否发送成功的
                    this.isSocket = false;
                }
            } catch (Exception var4) {
                var4.printStackTrace();
                //isSocket是用来判断是否发送成功的
                this.isSocket = false;
            }
            //isSocket是用来判断是否发送成功的
            return this.isSocket;
        } else {
            return false;
        }
    }

    //解析服务器返回的JSON数据
    public void setData(JSONObject obj) throws JSONException {
        DeviceBean bean = new DeviceBean();
        if (obj.has("Type")) {
            //判断数据是数据采集还是考勤机或心跳包的
            if (!obj.getString("Type").toString().equals("Upload") && !obj.getString("Type").toString().equals("GetDevicState")) {
                //判断是否为考勤机
                if (obj.getString("Type").toString().equals("UploadPersonInfo") || obj.getString("Type").toString().equals("GetCurrentAttendance")) {
                    try {
                        if (obj.has("Name")) {
                            //考勤的姓名
                            DeviceBean.setName(obj.getString("Name"));
                        }
                    } catch (JSONException var9) {
                    }

                    try {
                        if (obj.has("Time")) {
                            //考勤的日期
                            DeviceBean.setTime(obj.getString("Time"));
                        }
                    } catch (JSONException var8) {
                    }

                    if (mDataCallback != null) {
                        mDataCallback.onResult(bean);
                    }
                }
            } else {
                //这里是数据采集的JSON解析
                try {
                    //具体怎么解析JSON就不说明了
                    ArrayList<Devices> deviceList = new ArrayList();
                    JSONArray array = new JSONArray(obj.get("Data").toString());

                    for(int i = 0; i < array.length(); ++i) {
                        JSONObject jsonObject = array.getJSONObject(i);
                        Devices devices = new Devices();
                        //数据的值
                        devices.setValue(jsonObject.getString("Value"));
                        //类型
                        devices.setSensorType(jsonObject.getString("SensorType"));
                        //版号
                        devices.setBoardId(jsonObject.getString("BoardId"));

                        deviceList.add(devices);
                    }
                    //解析完的数据放进DeviceBean集合中
                    DeviceBean.setDevice(deviceList);
                } catch (JSONException var10) {
                }

                //如果写了获取数据的回调,就执行可以拿到数据了
                if (mDataCallback != null) {
                    mDataCallback.onResult(bean);
                }
            }
        } else if (obj.has("state") && obj.getString("state").toString().equals("Failure") && obj.has("msg") && this.mLoginCallback != null) {
            //未知错误
            this.mLoginCallback.onEvent("5");
        }

    }

    //断开服务器连接
    public void disConnect(WeakReference<Socket> mSocket) {
        try {
            if (mSocket != null) {
                Socket sk = (Socket)mSocket.get();
                if (!sk.isClosed()) {
                    sk.close();
                }

                sk = null;
                mSocket = null;
            }
        } catch (IOException var3) {
            var3.printStackTrace();
        }

    }

    //断开服务器连接
    public void release() {
        try {
            if (mInstance != null) {
                mInstance = null;
            }

            if (this.mReadThread != null) {
                this.mReadThread.release();
            }

            if (this.mHandler != null) {
                this.mHandler.removeCallbacks(this.heartBeatRunnable);
            }
        } catch (Exception var2) {
        }

    }

    //连接服务器的LoginCallback赋值给全局mLoginCallback
    public void login(LoginCallback callback) {
        this.mLoginCallback = callback;
    }

    public void getData(DataCallback callback) {
        mDataCallback = callback;
    }


    //获取服务器数据
    private class ReadThread extends Thread {
        //局部Socket
        private WeakReference<Socket> mWeakSocket;
        private boolean isStart = true;

        public ReadThread(Socket socket) {
            //转移全局Socket
            this.mWeakSocket = new WeakReference(socket);
        }

        //断开服务器连接
        public void release() {
            this.isStart = false;
            //断开服务器连接
            SocketClient.this.disConnect(this.mWeakSocket);
        }

        //获取服务器数据
        public void run() {
            super.run();
            //梅开n度,把局部的mWeakSocket转移给线程内的socket
            Socket socket = (Socket)this.mWeakSocket.get();
            //判空
            if (socket != null) {
                try {
                    String response = "";
                    //读取服务器数据
                    BufferedReader DataRead = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                    //判空
                    while(!socket.isClosed() && this.isStart && !socket.isInputShutdown()) {
                        //判空
                        while((response = DataRead.readLine()) != null) {
                            //获取服务器返回的JSON数据
                            JSONObject obj = new JSONObject(response);
                            //解析服务器JSON数据
                            SocketClient.this.setData(obj);
                        }
                    }
                } catch (JSONException var5) {
                    var5.printStackTrace();
                } catch (Exception var6) {
                    //未知异常就断开服务器连接
                    this.isStart = false;
                    SocketClient.this.mSocket = null;
                    var6.printStackTrace();
                }
            }

        }
    }

    //执行initSocket()方法用的
    class InitSocketThread extends Thread {
        InitSocketThread() {
        }

        public void run() {
            super.run();
            SocketClient.this.initSocket();
        }
    }
}
  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...