Android网络技术

Android网络技术

一、WebView

webView.getSettings().setJavaScriptEnabled(true);   //使webView支持JavaScript脚本
webView.setWebViewClient(new WebViewClient());      //使跳转网页时目标网页仍在WebView中显示,而不打开浏览器
webView.loadUrl("http://www.baidu.com");            //加载网页

二、使用HTTP协议访问网络

1、使用HttpURLConnection

(1)获取HttpURLConnection的实例。

URL url = new URL("http://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();

(2)设置HTTP请求所使用的方法。常用的方法有GET和POST。

connection.setRequestMethod("GET");
  • 向服务器提交用户名和密码:

    connection.setRequestMethod("POST");
    DataOutputStream out = new DataOutputStream(connection.getOutputStream());
    out.writeBytes("username=admin&password=123456");
    

(3)设置连接超时、读取超时的毫秒数、以及服务器希望得到的一些消息头等。这部分根据需求进行编写。

connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);

(4)调用getInputStream()方法获取服务器返回的输入流。

InputStream in = connection.getInputStream();

(5)对输入流进行读取

(6)调用disconnect()将这个HTTP连接关闭。

2、使用OkHttp

(1)添加OkHttp库依赖

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

(2)创建一个OkHttpClient的实例

OkHttpClient client = new OkHttpClient();
  • 发起一条HTTP请求:

(3)创建一个Request对象(在build()方法之前连缀其他方法来丰富这个request对象)

Request request = new Request.Builder().url("http://www.baidu.com").build();

(4)调用OkHttpClient的newCall()方法来创建一个call对象,并调用它的execute()方法来发送请求并获取服务器返回的数据。

Response response = client.newCall(request).execute();

(5)Response对象就是服务器返回的数据。

String responseData = response.body().string();
  • 发起一条POST请求:

(3)构建一个RequestBody对象来存放待提交的参数

RequestBody requestBody = new FormBody.Builder()
        .add("username", "admin")
        .add("password", "123456")
        .build();

(4)在Request.Builer中调用post()方法,并将RequestBody对象传入

Request request = new Request.Builder()
        .url("http://www.baidu.com")
        .post(requestBody)
        .build();

(5)发送请求并获取服务器返回的数据

Response response = client.newCall(request).execute();
String responseData = response.body().string();     

三、解析XML格式数据

1、Pull解析方式

(1)获取XmlPullParserFactory的实例,然后借助这个实例得到XmlPullParser对象。

XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();

(2)调用XmlPullParser的setInput()方法将服务器返回的XML数据设置进去。

xmlPullParser.setInput(new StringReader(xmlData));

(3)通过getEventType()得到当前的解析事件

int eventType = xmlPullParser.getEventType();

(4)在while中进行解析。如果当前的解析事件不等于XmlPullParser.END_DOCUMENT,说明解析工作还没完成,该while循环最后调用next()可以获取下一个解析事件。

  在while循环中,通过getName()获取当前节点的名字,如果发现结点名为开始标记,就可以调用nextText()方法获取结点内具体的内容。

代码示例:

private void parseXMLWithPull(String responseData) {
    try {

        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        XmlPullParser xmlPullParser = factory.newPullParser();
        xmlPullParser.setInput(new StringReader(responseData));
        int eventType = xmlPullParser.getEventType();

        String id = "";
        String name = "";
        String version = "";

        while (eventType != XmlPullParser.END_DOCUMENT) {
            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)) {
                        Log.d("MainActivity", "id is " + id);
                        Log.d("MainActivity", "name is " + name);
                        Log.d("MainActivity", "version is " + version);
                    }
                    break;
                default:
                    break;
            }
            eventType = xmlPullParser.next();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

2、SAX解析方式

  新建一个类继承自DefaultHandler,重写父类的5个方法。其中,startDocument()会在开始XML解析时调用;startElement()会在开始解析某个结点的时候调用;characters()会在获取结点中内容时调用;endElement()会在完成解析某个节点时调用;endDocument()会在完成整个XML解析时调用。

ContentHandler.java

public class ContentHandler extends DefaultHandler{

    private String nodeName;

    private StringBuilder id;

    private StringBuilder name;

    private StringBuilder version;

    @Override
    public void startDocument() throws SAXException {
        id = new StringBuilder();
        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 {
        //根据当前节点名判断将内容添加到哪一个StringBuilder对象中
        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)) {
            Log.d("ContentHandler", "id is " + id.toString().trim());
            Log.d("ContentHandler", "name is " + name.toString().trim());
            Log.d("ContentHandler", "version is " + version.toString().trim());
            //最后将StringBuilder清空掉
            id.setLength(0);
            name.setLength(0);
            version.setLength(0);
        }
    }

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

}

解析过程:

private void parseXMLWithSAX(String xmlData) {
    try {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        XMLReader xmlReader = factory.newSAXParser().getXMLReader();
        ContentHandler handler = new ContentHandler();

        //将ContentHandler的实例设置到XMLReader中
        xmlReader.setContentHandler(handler);
        //开始执行解析
        xmlReader.parse(new InputSource(new StringReader(xmlData)));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

四、解析JSON格式数据

1、使用JSONObject

private void parseJSONWithJSONObject(String jsonData) {
    try {
        JSONArray jsonArray = new JSONArray(jsonData);
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);

            String id = jsonObject.getString("id");
            String name = jsonObject.getString("name");
            String version = jsonObject.getString("version");

            Log.d("MainActivity", "id is " + id);
            Log.d("MainActivity", "name is " + name);
            Log.d("MainActivity", "version is " + version);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

}

2、使用GSON

(1)添加GSON库依赖

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

(2)

  • GSON库将一段Json格式的字符串自动映射成一个对象。如一段Json数据:{“name”:”Tom”,”age”:20},解析这一段Json数据,就可以先定义一个Person类,加入name和age两个字段,然后调用如下代码:

    Gson gson = new Gson();
    Person person = gson.fromJson(jsonData, Person.class);
    
  • 解析一段Json数组,就需要借助TypeToken将期望解析成的数据类型传入到fromJson()方法中,如下:

    List<Person> people = gson.fromJson(jsonData, new TypeToken<List<Person>>(){}.getType());
    

实例:

新建App.java:

public class App {

    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;
    }
}

GSON解析Json:

private void parseJSONWithGSON(String jsonData) {
    Gson gson = new Gson();
    List<App> appList = gson.fromJson(jsonData, new TypeToken<List<App>>(){}.getType());
    for (App app : appList) {
        Log.d("MainActivity", "id is " + app.getId());
        Log.d("MainActivity", "name is " + app.getName());
        Log.d("MainActivity", "version is " + app.getVersion());
    }
}

五、Http请求工具类

public class HttpUtils {

    public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                StringBuilder response = new StringBuilder();
                try {
                    URL url = new URL(address);
                    connection = (HttpURLConnection) url.openConnection();

                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);

                    connection.setDoInput(true);
                    connection.setDoOutput(true);

                    InputStream in = connection.getInputStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                    String line;

                    while ((line = reader.readLine()) != null) {
                        response.append(line);
                    }

                    if (listener != null) {
                        //回调onFinish()方法
                        listener.onFinish(response.toString());
                    }

                } catch (Exception e) {
                    if (listener != null) {
                        //回调onError()方法
                        listener.onError(e);
                    }
                } finally {
                    if (connection != null) {
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }

    public static void sendOkHttpRequest(String address, Callback callback) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(address)
                .build();
        client.newCall(request).enqueue(callback);
    }
}

由于如果在以上方法内部不开启子线程可能会造成主线程阻塞,而开启子线程,Http请求方法会在服务器还没来得及响应的时候就执行结束了。所以此处需要利用Java的回调机制。实际使用时代码:

HttpUtils.sendHttpRequest("http://www.baidu.com", new HttpCallbackListener() {
    @Override
    public void onFinish(String response) {
        //在这里根据返回内容执行具体的逻辑
        ...
    }

    @Override
    public void onError(Exception e) {
        //在这里进行异常处理
    }
});


HttpUtils.sendOkHttpRequest("http://www.baidu.com", new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        //在这里进行异常处理
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        //得到服务器返回的具体内容
        String responseData = response.body().string();
    }
});

猜你喜欢

转载自blog.csdn.net/qq_32651225/article/details/56016636