android socket通信之—生成xml上传到服务器并解析xml数据

需求描述:将测试数据封装成xml形式并上传到指定的服务端
android socket通信之—生成xml上传到服务器并解析xml数据_第1张图片

本文实现:

  1. 生成指定形式的xml
  2. socket将xml数据上传到服务端
  3. 服务端对xml数据进行解析,验证接收到的xml和发送的数据是否一致

第一步:生成xml数据

  • xml数据的格式:



    8802

    123456789

    0c:12:05:01:25:25

    pqc

    

        CameraTest

        Success

        
    

    

        EarphoneTest

        Fail

        Fail
    

说明:前面规定了产品的一些参数,后面是具体测试项test部分,这里只列举了两个test

  • 根据xml的形式,新建一个实体类ryd:
public class ryd {
    private String pro_name;

    private String pro_SN;

    private String pro_Mac;

    private String test_mode;

    private String name;

    private String result;

    private String errmsg;

    public String getPro_name() {
        return pro_name;
    }

    public void setPro_name(String pro_name) {
        this.pro_name = pro_name;
    }

    public String getPro_SN() {
        return pro_SN;
    }

    public void setPro_SN(String pro_SN) {
        this.pro_SN = pro_SN;
    }

    public String getPro_Mac() {
        return pro_Mac;
    }

    public void setPro_Mac(String pro_Mac) {
        this.pro_Mac = pro_Mac;
    }


    public String getTest_mode() {
        return test_mode;
    }

    public void setTest_mode(String test_mode) {
        this.test_mode = test_mode;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public String getErrmsg() {
        return errmsg;
    }

    public void setErrmsg(String errmsg) {
        this.errmsg = errmsg;
    }
}

说明:test部分的get和set基本没用到,因为test部分都是key-value形式,所以用map来保存和读取

初始化产品参数部分:

    /**
     * 初始化xml数据
     */
    private void init_xml() {
        //[1]初始化我们要备份的数据
        smsLists = new ArrayList();
        sms = new ryd();
        //在这里可以获取你想设置的数据,这里举例设置sn
        String serial = Build.SERIAL;//获取SN
        sms.setPro_name("8802");
        sms.setPro_SN(serial);
        sms.setPro_Mac("0c:12:05:01:25:25");
        sms.setTest_mode("pqc");
    }

在初始化test部分之前,先模拟生成测试结果:
测试项:保存在value文件夹下的stringarrays.xml




    
        MIC测试
        Camera输入测试
    

    
        com.android.nirvana.tools.HeadsetMicTestActivity
        com.android.nirvana.tools.HdmiTestActivity
    


说明:所有的测试项都保存string-array中,通过SP的put来保存测试结果,大家可以根据实际的测试结果设置,这里只是简单模拟。

    private void init_data() {
        Resources res = getResources();
        names = res.getStringArray(R.array.listview_item_name);

        sharedPreferencesHelper = new SharedPreferencesHelper(this);
        //在这里模拟测试结果,camera测试成功,mic测试失败
        sharedPreferencesHelper.put("MIC测试", TEST_RESULT_FAIL);
        sharedPreferencesHelper.put("Camera输入测试", TEST_RESULT_SUCC);

    }

初始化test数据部分:

    /**
     * 获取测试结果,补充test部分
     */
    private void get_testresult() {
        for (String str : names) {
            int result = (int) sharedPreferencesHelper.get(str, TEST_RESULT_NONE);

            //在这里可以将测试的中文名称改成英文名称,因为接收中文很可能导致报错,因为数据不匹配,最好用英文
            switch (str.trim()) {
                case "MIC测试":
                    str = "EarphoneTest";
                    break;
                case "Camera输入测试":
                    str = "Camera Test";
                    break;
            }

            if (result == TEST_RESULT_SUCC) {
                map.put(str, "Success");
            } else if (result == TEST_RESULT_NONE) {
                map.put(str, "Fail");
            } else if (result == TEST_RESULT_FAIL) {
                map.put(str, "Fail");
            }
        }

        //放入测试项
        smsLists.add(sms);
    }

说明:这里将中文的测试名称强制转换为英文名称,并根据测试结果,put了对应的value

  • 将数据拼接成xml形式:

说明:(推荐)通过StringBuffer直接以追加字符串的方式生成XML文件(工程里还有用XmlSerializer生成的方式)

    /**
     * 生成xml数据
     */
    private void get_xml() {
        //[1]创建sb对象
        StringBuffer sb = new StringBuffer();

        //[2]开始组拼xml文件头
        sb.append("");
        //[3]开始组拼xml根节点
        sb.append("");
        //[4]开始组拼sms节点
        for (ryd sms : smsLists) {
            //sb.append("");

            //[5]开始组拼pro_name节点
            sb.append("");
            sb.append(sms.getPro_name());
            sb.append("");

            //[6]开始组拼pro_SN节点
            sb.append("");
            sb.append(sms.getPro_SN());
            sb.append("");

            //[7]开始组拼pro_Mac节点
            sb.append("");
            sb.append(sms.getPro_Mac());
            sb.append("");


            //[7]开始组拼test_mode节点
            sb.append("");
            sb.append(sms.getTest_mode());
            sb.append("");

            //遍历出map的值
            Iterator iter = map.entrySet().iterator();
            while (iter.hasNext()) {
                Map.Entry entry = (Map.Entry) iter.next();
                String key = (String) entry.getKey();
                String value = (String) entry.getValue();

                //[7]开始组拼节点
                sb.append("");

                sb.append("");
                sb.append(key);
                sb.append("");

                sb.append("");
                sb.append(value);
                sb.append("");

                sb.append("");
                if (value.contains("Fail")) {
                    sms.setErrmsg("Fail");
                } else {
                    sms.setErrmsg("");
                }
                sb.append(sms.getErrmsg());
                sb.append("");

                sb.append("");
            }
        }

        sb.append("");
        //[8]把数据保存到sd卡中
        try {
            File file = new File(Environment.getExternalStorageDirectory().getPath(), "MesXml.xml");
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(sb.toString().getBytes());
            fos.close();//关闭流
            Log.i("yyy", "文件已经保存到sd卡: ");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

不要忘了添加权限:

    
    
    
    

最后查看sdcard下的MesXml.xml,发现与规定生成xml数据一致,生成xml数据到此结束

adb pull /sdcard/MesXml.xml C:\1\MesXml.xml

第二步:通过socket将xml上传到服务器

客户端创建一个Socket对象,指定服务器端的ip地址和端口号(socket = new Socket(HOST, PORT); ),通过inputstream读取数据,获取服务器发出的数据(outStream = socket.getOutputStream(); ),最后将要发送的数据写入到outputstream即可进行TCP协议的socket数据传输

    
    

    
    

    
    

    
    

    
    

下面是socket发送线程,注意:此段代码应在生成xml之后


    //服务端的IP是:192.168.1.x(这里用我的电脑当服务器)
    //手机当做是客户端,端口号可以任意设定,双方一致就OK
    private static final String HOST = "192.168.1.x";
    private static final int PORT = 12333;

    /***
     * 线程
     */
    public class socketThread extends Thread {
        public void run() {
            while (!exit0) {
                try {
                    Log.i("yyy", "进入socketThread----------: ");
                    // 开启与服务器的socket连接
                    socket = new Socket(HOST, PORT);
                    // in:读入  out:写出
                    in = new BufferedReader(new InputStreamReader(
                            socket.getInputStream()));

                    //获取输出流
                    outStream = socket.getOutputStream();
                    out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outStream)), true);


                    try {
                        File file = new File(Environment.getExternalStorageDirectory().getPath(), "MesXml.xml");
                        //创建SAXReader,读取指定文件
                        System.out.println(file);//D:\1\1.txt
                        Log.i("yyy", "file:-----------: " + file);
                        if (file.exists()) {
                            SAXReader reader = new SAXReader();
                            Document doc = null;
                            doc = reader.read(file);
                            //创建XML输出流
                            XMLWriter writer = new XMLWriter();
                            writer.setOutputStream(outStream);
                            writer.write(doc);
                        } else {
                            Log.i("yyy", "MesXml文件还没有生成: ");
                        }


                    } catch (DocumentException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        if (socket != null) {
                            msocketThread.stopDownload();
                            try {
                                out.flush();
                                out.close();
                                System.out.println("socket已关闭---");
                                socket.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }

            }
        }

        public void stopDownload() {
            Log.i("yyy", "线程已经停止------------: ");
            exit0 = true;
        }
    }

说明:这里生成xml和解析xml都是使用SAX解析方式,需要先导入jar包才可以,具体可以参考文末

第三步:服务端解析xml数据

服务器端首先声明一个ServerSocket对象并且指定端口号,然后调用Serversocket的accept()方法接收客户端的数据。accept()方法在没有数据进行接收的处于堵塞状态。一旦接收到数据,通过socket.getInputStream()读取接收的数据。

服务端完整代码如下:

/**
 * 服务端
 */
public class Server {
    private ServerSocket server;

    //这里的端口号必须和客户端的保持一致,
    public Server() throws IOException {
        server = new ServerSocket(12333);
    }

    public void start() {
        try {
            //监听客户端,建立连接
            System.out.println("等待连接..........");
            Socket socket = server.accept();
            System.out.println("服务端连接成功!");
            //获取输入流   写出  读入
            InputStream in = socket.getInputStream();
            //创建SAXReader,读取指定文件
            SAXReader reader = new SAXReader();
            Document doc = reader.read(in);
            //获取根节点
            Element root = doc.getRootElement();
            getNodes(root);//遍历根节点下的所有节点,也就是整个xml文件的所有节点
            System.out.println("解析完毕!");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (server != null) {
                try {
                    server.close();
                    System.out.println("服务端已关闭!");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 从指定节点开始,递归遍历所有子节点,这个方法很好用
     */
    public void getNodes(Element node) {
        System.out.println("--------------------");

        //当前节点的名称、文本内容和属性
        System.out.println("当前节点名称:" + node.getName());//当前节点名称
        System.out.println("当前节点的内容:" + node.getTextTrim());//当前节点内容

        //递归遍历当前节点所有的子节点
        List listElement = node.elements();//所有一级子节点的list
        for (Element e : listElement) {//遍历所有一级子节点
            this.getNodes(e);//递归
        }
    }


    public static void main(String[] args) {
        try {
            Server s = new Server();
            s.start();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("初始化服务端失败!");
        }
    }
}

说明:服务端是一个java程序,鼠标右击下图开始运行
在这里插入图片描述
正确接收的数据:

等待连接..........
服务端连接成功!
--------------------
当前节点名称:ryd
当前节点的内容:
--------------------
当前节点名称:pro_name
当前节点的内容:8802
--------------------
当前节点名称:pro_SN
当前节点的内容:000000000000
--------------------
当前节点名称:pro_Mac
当前节点的内容:0c:12:05:01:25:25
--------------------
当前节点名称:test_mode
当前节点的内容:pqc
--------------------
当前节点名称:test
当前节点的内容:
--------------------
当前节点名称:name
当前节点的内容:Camera Test
--------------------
当前节点名称:result
当前节点的内容:Success
--------------------
当前节点名称:errmsg
当前节点的内容:
--------------------
当前节点名称:test
当前节点的内容:
--------------------
当前节点名称:name
当前节点的内容:EarphoneTest
--------------------
当前节点名称:result
当前节点的内容:Fail
--------------------
当前节点名称:errmsg
当前节点的内容:Fail
解析完毕!
服务端已关闭!

说明:可以看到每一个节点的名称,sn是根据具体板子获取的,不用纠结这个。

至此:一个完整的工程结束,从生成xml到上传到服务器并且解析xml。

github地址:https://github.com/felicity520/xmlTosocket.git

作者:鸣人的修炼场
出处:https://blog.csdn.net/baidu_33693586

参考博客:
Android 生成xml文件
Android XML解析的三种方式

你可能感兴趣的:(Android)