Android网络编程

1.XML和JSON格式数据

通常情况下,每一个需要访问网络的应用程序都会有一个自己的服务器,应用可以向服务器提交数据,也可以从服务器上获取数据。应用(客户端)和服务器之间 的数据传输常见格式有XML和JSON格式。
i.下面是XML格式的一个例子

<apps>
<app>
    <id>1id>
    <name>Google Mapsname>
    <version>1.0version>
app>
<app>
    <id>2id>
    <name>Chromename>
    <version>1.0version>
app>
<app>
    <id>3id>
    <name>Google Playname>
    <version>1.0version>
app>
apps>

语法如下:

a)、任何的起始标签都必须有一个结束标签。
b)、可以采用另一种简化语法,可以在一个标签中同时表示起始和结束标签。这种语法是在大于符号之前紧跟一个斜线(/),例如<百度百科词条/>。XML解析器会将其翻译成<百度百科词条>百度百科词条>。
c)、标签必须按合适的顺序进行嵌套,所以结束标签必须按镜像顺序匹配起始标签,例如这是一串百度百科中的样例字符串。这好比是将起始和结束标签看作是数学中的左右括号:在没有关闭所有的内部括号之前,是不能关闭外面的括号的。
d)、所有的特性都必须有值。
e)、所有的特性都必须在值的周围加上双引号。

ii.JSON例子

[{"id":"1","version":"1.2","name":"Tom"},
{"id":"2","version":"2.2","name":"Jack"},
{"id":"3","version":"1.6","name":"Tomson"}]

语法如下:

JSON 语法是 JavaScript 对象表示语法的子集。
-数据在键值对中
-数据由逗号分隔
-花括号保存对象
-方括号保存数组

3.前期准备

i.OKhttp
这里使用Square公司的OKHTTP框架,添加依赖:

 compile 'com.squareup.okhttp3:okhttp:3.6.0'

ii.需要联网权限:

  <uses-permission android:name="android.permission.INTERNET" />

iii.Apache http 服务器准备
下载:链接:http://pan.baidu.com/s/1qXZGqmg 密码:rj7x
下载得到msi文件,点击安装,安装教程很多,我不赘述了。
然后再浏览器输入:127.0.0.1
Android网络编程_第1张图片
出现IT WORKS!说明服务器安装成功
最后是准备数据源:

新建data.xml包含数据:

<apps>
<app>
    <id>1id>
    <name>Google Mapsname>
    <version>1.0version>
app>
<app>
    <id>2id>
    <name>Chromename>
    <version>1.0version>
app>
<app>
    <id>3id>
    <name>Google Playname>
    <version>1.0version>
app>
apps>

在浏览器输入http://127.0.0.1/data.xml,出现如下如下界面,说明数据准备成功:
Android网络编程_第2张图片
新建 data.json:

[{"id":"1","version":"1.2","name":"Tom"},
{"id":"2","version":"2.2","name":"Jack"},
{"id":"3","version":"1.6","name":"Tomson"}]

在浏览器输入http://127.0.0.1/data.json,出现如下如下界面,说明数据准备成功:
Android网络编程_第3张图片

4.解析XML

解析XML主要有:PULL解析方法和SAX解析方法。
做好前期准备,新建一个项目。
i.PULL解析方式:
PullMainActivity .java

package com.example.geekp.internet.xml;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import android.widget.Toast;

import com.example.geekp.internet.R;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class PullMainActivity extends AppCompatActivity {
    private TextView text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = (TextView) findViewById(R.id.response_text);
        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendRequest();
            }
        });
    }

    private void sendRequest() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient httpclient = new OkHttpClient();
//                10.0.2.2对于模拟器来讲就是PC的IP地址
                Request request = new Request.Builder().url("http://10.0.2.2/data.xml").build();
                try {
                    Response response = httpclient.newCall(request).execute();
                    String bulider = response.body().string();
                    parseXMLWithPull(bulider);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void parseXMLWithPull(final String builder) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
                    XmlPullParser xmlPullParser = factory.newPullParser();
                    xmlPullParser.setInput(new StringReader(builder));
                    int eventType = xmlPullParser.getEventType();
                    String id = "";
                    String name = "";
                    String version = "";
                    while (XmlPullParser.END_DOCUMENT != eventType) {
                        String nodeName = xmlPullParser.getName();
                        switch (eventType) {
                            case XmlPullParser.START_TAG:
                                if ("id".equals(nodeName)) {
                                    id = xmlPullParser.nextText();
                                } else if ("name".equals(nodeName)) {
                                    name = xmlPullParser.nextText();
                                } else if ("version".equals(nodeName)) {
                                    version = xmlPullParser.nextText();
                                }
                                break;
                            //完成解析某个结点
                            case XmlPullParser.END_TAG:
                                if ("app".equals(nodeName)) {
                                    System.out.println(id);
                                    System.out.println(name);
                                    System.out.println(version);
                                    Toast.makeText(getApplicationContext(),"id is:"+id+"  name is:"+name+" version is:"+version,Toast.LENGTH_SHORT).show();
                                }
                                break;
                            default:
                                break;
                        }
                        eventType = xmlPullParser.next();
                    }
                } catch (XmlPullParserException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

    }
}

xml:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.geekp.internet.xml.PullMainActivity">

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send request" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/response_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    ScrollView>
LinearLayout>

运行结果:
Android网络编程_第4张图片
从上面的代码中,我们可以看到PULL关键的代码是:

 XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
                    XmlPullParser xmlPullParser = factory.newPullParser();
                    xmlPullParser.setInput(new StringReader(builder));
                    int eventType = xmlPullParser.getEventType();
                    String id = "";
                    String name = "";
                    String version = "";
                    while (XmlPullParser.END_DOCUMENT != eventType) {
                        String nodeName = xmlPullParser.getName();
                        switch (eventType) {
                            case XmlPullParser.START_TAG:
                                if ("id".equals(nodeName)) {
                                    id = xmlPullParser.nextText();
                                } else if ("name".equals(nodeName)) {
                                    name = xmlPullParser.nextText();
                                } else if ("version".equals(nodeName)) {
                                    version = xmlPullParser.nextText();
                                }
                                break;
                            //完成解析某个结点
                            case XmlPullParser.END_TAG:
                                if ("app".equals(nodeName)) {
                                    System.out.println(id);
                                    System.out.println(name);
                                    System.out.println(version);
                                    Toast.makeText(getApplicationContext(),"id is:"+id+"  name is:"+name+" version is:"+version,Toast.LENGTH_SHORT).show();
                                }
                                break;
                            default:
                                break;
                        }
                        eventType = xmlPullParser.next();
                    }

首先要获取一个XmlPullParserFactory的实例,并借助这个实例得到XMLPullparser对象,然后调用setInput的方法将服务器返回的数据设置进去就可以开始解析了。
ii.SAX解析方式
通常需要写一个DefaultHandler的子类并实现下面的五个方法:


class MH extends DefaultHandler {
    //开始解析XML时调用
    @Override
    public void startDocument() throws SAXException {
    }

    //开始解析某个结点的时候调用
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

    }

    //获取结点中的内容调用
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {

    }

    //完成解析某个结点的时候调用
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {

    }

    //完成整个xml的时候调用
    @Override
    public void endDocument() throws SAXException {

    }
}

下面来看个例子:
ContentHandler .java

package com.example.geekp.internet.xml;

//import jdk.internal.org.xml.sax.helpers.DefaultHandler;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Created by geekp on 2017/2/24.
 * Email:[email protected]
 */

public class ContentHandler extends DefaultHandler {
    private StringBuffer id;
    private StringBuilder name;
    private StringBuilder version;
    private String nodeName;

    @Override
    public void startDocument() throws SAXException {
        id=new StringBuffer();
        name=new StringBuilder();
        version=new StringBuilder();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        //记录当前节点的名字
        nodeName=localName;
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if("id".equals(nodeName))
        {
            id.append(ch,start,length);
        }else if("name".equals(nodeName))
        {
            name.append(ch,start,length);
        }else if("version".equals(nodeName))
        {
            version.append(ch,start,length);
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {

        if("app".equals(localName))
        {
            System.out.println("id is: "+id.toString().trim());
            System.out.println("name is :" +name.toString().trim());
            System.out.println("version is :"+version.toString().trim());
            //最后要stringbuilder清空
            id.setLength(0);
            name.setLength(0);
            version.setLength(0);
        }
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }
}

SAXainActivity .java

package com.example.geekp.internet.xml;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.example.geekp.internet.R;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.IOException;
import java.io.StringReader;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class SAXainActivity extends AppCompatActivity {
private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        button=(Button)findViewById(R.id.btnrequest);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendRequestwithOkhttp();
            }
        });
    }
    private void sendRequestwithOkhttp() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient httpclient = new OkHttpClient();
//                10.0.2.2对于模拟器来讲就是PC的IP地址
                Request request = new Request.Builder().url("http://10.0.2.2/data.xml").build();
                try {
                    Response response = httpclient.newCall(request).execute();
                    String data = response.body().string();
                    parseXMLWithSAX(data);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void parseXMLWithSAX(final String data) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                SAXParserFactory factory=SAXParserFactory.newInstance();
                try {
                    XMLReader reader=factory.newSAXParser().getXMLReader();
                    ContentHandler contentHandler=new ContentHandler();
                    //将contentHandler的实例设置到XMLreader中
                    reader.setContentHandler(contentHandler);
                    reader.parse(new InputSource(new StringReader(data)));
                } catch (SAXException e) {
                    e.printStackTrace();
                } catch (ParserConfigurationException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

    }
}

xml:


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main2"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.geekp.internet.xml.SAXainActivity">

    <Button
        android:id="@+id/btnrequest"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="请求" />
RelativeLayout>

效果图:
Android网络编程_第5张图片

得到服务器的数据之后,首先创建了一个SAXParserFactory的实例然后再获取XMLReader对象,接着将我们编好的DefaultHandler子类设置到XMLReader中,最后调用parse().

整个工程的源码,请点击这里下载

5.解析JSon格式的数据

解析JSon格式的数据通常有JSONObject和GSON两种方式:

i.JSONObject

package com.example.geekp.json;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;


import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class JSONObjectMainActivity extends AppCompatActivity {

    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.btnsend);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                sendRequestwithOkhttp();
            }
        });
    }

    private void sendRequestwithOkhttp() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient httpclient = new OkHttpClient();
//                10.0.2.2对于模拟器来讲就是PC的IP地址
                Request request = new Request.Builder()
                        .url("http://10.0.2.2/data.json")
                        .build();
                try {
                    Response response = httpclient.newCall(request).execute();
                    String data = response.body().string();

                    parseJSonWithJsonObject(data);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void parseJSonWithJsonObject(final String data) {
        try {
            JSONArray jsonArray = new JSONArray(data);
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject object = jsonArray.getJSONObject(i);
                System.out.println("id is:" + object.getString("id"));
                System.out.println("name is :" + object.getString("name"));
                System.out.println("version is:" + object.getString("version"));
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

}

xml:


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.geekp.json.JSONObjectMainActivity">

    <Button
        android:id="@+id/btnsend"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="请求" />
RelativeLayout>

效果:

Android网络编程_第6张图片

由于我们在服务器中定义的是一个JSon数组,因此我们需要先将返回的数组传到一个JSONArray对象中,然后再遍历这个数组。
ii.GSON方式
GSON是一个开源库,使用它首先得添加依赖:

 compile 'com.google.code.gson:gson:2.8.0'

Bean.java

package com.example.geekp.json.gson;

/**
 * Created by geekp on 2017/2/24.
 * Email:[email protected]
 */

public class Bean {
    private String id;
    private  String name;
    private  String version;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }
}

GsonMainActivity .java

package com.example.geekp.json.gson;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.example.geekp.json.R;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.List;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class GsonMainActivity extends AppCompatActivity {

    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gson_main);
        button = (Button) findViewById(R.id.btnsendre);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                sendRequestwithOkhttp();
            }
        });
    }

    private void sendRequestwithOkhttp() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient httpclient = new OkHttpClient();
//                10.0.2.2对于模拟器来讲就是PC的IP地址
                Request request = new Request.Builder()
                        .url("http://10.0.2.2/data.json")
                        .build();
                try {
                    Response response = httpclient.newCall(request).execute();
                    String data = response.body().string();
                    parseJSonWithGSON(data);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void parseJSonWithGSON(final String data) {
        Gson gson = new Gson();
        List beanlist = gson.fromJson(data, new TypeToken>() {
        }.getType());
        for(Bean bean:beanlist)
        {
            System.out.println("id is :"+bean.getId());
            System.out.println("name is:"+bean.getName());
            System.out.println("vesrsion is :"+bean.getVersion());
        }
    }
}

xml:


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_gson_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.geekp.json.gson.GsonMainActivity">

    <Button
        android:id="@+id/btnsendre"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="请求" />
RelativeLayout>

这样也可以成功地解析JSON数据了;
Android网络编程_第7张图片
源码在这里,点击进入GitHub下载

你可能感兴趣的:(Android)