segmentfault 对 mackdown 语法的支持不是很好,有些图片都显示不出来,大家可以去我的掘金查看这篇文章。

一、Android 网络知识简介

Android 程序最重要的模块就是网络部分,如何从网络上下载数据,如何将处理过的数据上传至网络,往往是 Android 程序的关键环节。Android 中对于网络操作的有很多很好用的框架,如 OkHttp、Velloy、Retrofit 等。但是今天我们来重点讲解一下 HttpURLConnection 这个抽象类。

二、利用 HttpURLConnection 实现 Get 和 Post 请求

1、权限申请

Android 中要做跟网络相关的操作,一定需要在清单文件中申请网络权限,如下所示:

Android 9.0 之前,只需要在清单文件中加上这句话就可以了,但是Android 9.0对 http 请求进行了限制,所以仅仅上面这一句话是不够的。为了解除这个限制,我们需要创建安全配置文件,具体步骤如下:

  1. 在 res 文件夹下创建xml/network-security-config 文件

Android 中的网络操作(HttpURLConnection)_第1张图片

  1. 增加 cleartextTrafficPermitted 属性

    <?xml version="1.0" encoding="utf-8"?>   
  2. 在 AndroidManifest.xml 的 Application 节点中申请

    android:networkSecurityConfig="@xml/network_security_config"

2、get 请求

我们从玩Android上面随便找一个 GET 请求的 API。json 数据格式如下所示:
Android 中的网络操作(HttpURLConnection)_第2张图片
现在我们来利用 HttpURLConnection 的 GET 请求来将上面这段 json 数据打印出来,具体代码如下所示:

 private final String URL = "https://wanandroid.com/wxarticle/chapters/json";  // HttpURLConnectionprivate void get() {    try {        // 1.实例化一个URL对象        URL url = new URL(URL);        // 2.获取HttpURLConnection实例        HttpURLConnection conn = (HttpURLConnection) url.openConnection();        // 3.设置和请求相关的属性        // 请求方式        conn.setRequestMethod("GET");        // 请求超时时间        conn.setConnectTimeout(10 * 1000);        // 4.获取响应码  200:成功  404:未请求到指定资源  500:服务器异常        if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {            // 5.判断响应码并获取响应数据(响应的正文)            // 获取响应的流            // IO 操作            InputStream in = conn.getInputStream();            byte[] b = new byte[1024];            int len;            ByteArrayOutputStream baos = new ByteArrayOutputStream();            while ((len = in.read(b)) > -1) {                baos.write(b, 0, len);            }            String msg = baos.toString();            Log.e("MainActivityTAG", msg);        }    } catch (Exception e) {        e.printStackTrace();    }}public void myClick(View v) {    switch (v.getId()) {        // Android4.0 以后网络操作必须放在子线程中        case R.id.btn_get:            new Thread(){                @Override                public void run() {                    super.run();                    get();                }            }.start();            break;    }}

控制台上面的数据如下,我们已经成功的打印出来了。
Android 中的网络操作(HttpURLConnection)_第3张图片
通过上述代码我们需要注意一下三点:

  1. 在清单文件中申请 INTERNET 权限
  2. 如果是 http 请求,需要创建安全配置文件 network-security-config
  3. Android4.0 以后网络操作必须放在子线程中

3、post 请求

我们从玩Android上面找一个 POST 请求的 API。然后我们可以利用 HttpURLConnection 的 POST 请求来实现一个登陆功能。
Android 中的网络操作(HttpURLConnection)_第4张图片
具体代码实现如下所示:

private void post(String account, String password) {    try {        // 1.实例化一个URL对象        URL url = new URL("https://www.wanandroid.com/user/login");        // 2.获取HttpURLConnection实例        HttpURLConnection conn = (HttpURLConnection) url.openConnection();        // 3.设置和请求相关的属性        // 请求方式        conn.setRequestMethod("POST");        // 请求超时时间        conn.setConnectTimeout(10 * 1000);        // 设置允许输出        conn.setDoOutput(true);        // 设置提交数据的类型        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");        //获取输出流(请求正文)        OutputStream out = conn.getOutputStream();        //写数据        out.write(("username=" + account + "&password=" + password).getBytes());        //4.获取响应码       200:成功   404:未请求到指定资源  500:服务器异常        if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {            //5.判断响应码并获取响应数据(响应的正文)            //获取响应的流            InputStream in = conn.getInputStream();            byte[] b = new byte[1024];            int len;            ByteArrayOutputStream baos = new ByteArrayOutputStream();            //在循环中读取输入流            // in.read(b);   // 该方法返回值是int类型数据,代表的是实际读到的数据长度            while ((len = in.read(b)) > -1) {                //将字节数组里面的内容存/写入缓存流                //参数1:待写入的数组                //参数2:起点                //参数3:长度                baos.write(b, 0, len);            }            String msg = new String(baos.toByteArray());            Log.e("MainActivityTAG", msg);        }    } catch (Exception e) {        e.printStackTrace();    }}public void myClick(View v) {    switch (v.getId()) {        // Android4.0 以后网络操作必须放在子线程中        case R.id.btn_post:            final String account = etAccount.getText().toString().trim();            final String password = etPassword.getText().toString().trim();            new Thread() {                @Override                public void run() {                    super.run();                    post(account, password);                }            }.start();            break;    }}

控制台上面的数据如下,我们已经成功的登陆了。
登陆

三、JSON 数据解析

Json 是一种轻量级的数据交互格式,具有良好的可读和便于快速编写的特性。业内主流结束为其提供了完整的解决方案(有点类似于正则表达式,获得了当今大部分语言的支持),从而可以在不同平台间进行数据交换。

1、利用JSONObject 解析

Android 中的网络操作(HttpURLConnection)_第5张图片
现在我们要在以上 JSON 数据中解析出 "郭霖" 这个字符串,利用 JSONObject 要怎么做呢?

具体解析的方法如下:

JSONObject jsonObject = new JSONObject(str);final int errorCode = jsonObject.getInt("errorCode");final String errorMsg = jsonObject.getString("errorMsg");final String name = jsonObject.getJSONArray("data").getJSONObject(1).getString("name");

首先要获取 data 列表,然后获取第二个对象,在第二个对象中获取 name 属性对应的值就可以了。

具体的效果如下所示:
Android 中的网络操作(HttpURLConnection)_第6张图片

完整代码如下:

private void paresByJSONObject() {    new Thread(){        @Override        public void run() {            super.run();            String str = get();            // 解析            // JSONObject            // 参数:满足 Json 格式要求的字符串            try {                if (str != null) {                    JSONObject jsonObject = new JSONObject(str);                    final int errorCode = jsonObject.getInt("errorCode");                    final String errorMsg = jsonObject.getString("errorMsg");                    final String name = jsonObject.getJSONArray("data").getJSONObject(1).getString("name");                    runOnUiThread(new Runnable() {                        @Override                        public void run() {                            tv1.setText("errorCode: " + errorCode);                            tv2.setText(name);                        }                    });                }            } catch (JSONException e) {                e.printStackTrace();            }        }    }.start();}private String get() {    try {        // 1.实例化一个URL对象        URL url = new URL("https://wanandroid.com/wxarticle/chapters/json");        // 2.获取HttpURLConnection实例        HttpURLConnection conn = (HttpURLConnection) url.openConnection();        // 3.设置和请求相关的属性        // 请求方式        conn.setRequestMethod("GET");        // 请求超时时间        conn.setConnectTimeout(10 * 1000);        // 4.获取响应码  200:成功  404:未请求到指定资源  500:服务器异常        if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {            // 5.判断响应码并获取响应数据(响应的正文)            // 获取响应的流            // IO 操作            InputStream in = conn.getInputStream();            byte[] b = new byte[1024];            int len;            ByteArrayOutputStream baos = new ByteArrayOutputStream();            while ((len = in.read(b)) > -1) {                baos.write(b, 0, len);            }            return baos.toString();        }    } catch (Exception e) {        e.printStackTrace();    }    return null;}

2、利用 GSON 解析

可以看到,用 JSONObject 解析 json数据相对来说是比较麻烦的,所以在日常工作中我们是不会用 JSONObject 去解析的。目前比较流行的 json解析工具有 gson,jackson,fastjson 等。这里我们就挑 gson来简单讲解一下吧。

1)、将对象转成 json 字符串(toJson )

Android 中的网络操作(HttpURLConnection)_第7张图片
我能根据上面的一个 JSON 数据创建一个对象 Wxarticle。

public class Wxarticle {    private int courseId;    private int id;    private String name;    private int order;    private int parentChapterId;    private boolean userControlSetTop;    private int visible;    public Wxarticle() {    }    public Wxarticle(int courseId, int id, String name, int order, int parentChapterId, boolean userControlSetTop, int visible) {        this.courseId = courseId;        this.id = id;        this.name = name;        this.order = order;        this.parentChapterId = parentChapterId;        this.userControlSetTop = userControlSetTop;        this.visible = visible;    }    public int getCourseId() {        return courseId;    }    public void setCourseId(int courseId) {        this.courseId = courseId;    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getOrder() {        return order;    }    public void setOrder(int order) {        this.order = order;    }    public int getParentChapterId() {        return parentChapterId;    }    public void setParentChapterId(int parentChapterId) {        this.parentChapterId = parentChapterId;    }    public boolean isUserControlSetTop() {        return userControlSetTop;    }    public void setUserControlSetTop(boolean userControlSetTop) {        this.userControlSetTop = userControlSetTop;    }    public int getVisible() {        return visible;    }    public void setVisible(int visible) {        this.visible = visible;    }    @Override    public String toString() {        return "wxarticle{" +                "courseId=" + courseId +                ", id=" + id +                ", name='" + name + '\'' +                ", order=" + order +                ", parentChapterId=" + parentChapterId +                ", userControlSetTop=" + userControlSetTop +                ", visible=" + visible +                '}';    }}

Gson 的 toJson 方法就是将一个对象转成 Json 字符串。我们来调用这个方法试一下。

Gson gson = new Gson();// 将对象变成 json 字符串Wxarticle wxarticle = new Wxarticle(13, 408, "鸿洋", 190000, 407, false, 1);String str = gson.toJson(wxarticle);Log.e("JSONActivity", str);

我们可以看到,对象已经成功的转成 Json 字符串了。
toJson

2)、将 json 字符串转成对象(fromJson)

我们利用 fromJson 方法将上述 json 对象中的 name 都输出出来,我们需要创建一个 Test 对象,具体代码如下所示:

public class Test {    private List data;    private int errorCode;    private String errorMsg;    public Test() {    }    public Test(List data, int errorCode, String errorMsg) {        this.data = data;        this.errorCode = errorCode;        this.errorMsg = errorMsg;    }    public List getData() {        return data;    }    public void setData(List data) {        this.data = data;    }    public int getErrorCode() {        return errorCode;    }    public void setErrorCode(int errorCode) {        this.errorCode = errorCode;    }    public String getErrorMsg() {        return errorMsg;    }    public void setErrorMsg(String errorMsg) {        this.errorMsg = errorMsg;    }}

具体解析代码如下所示:

 // fromJsonnew Thread(){    @Override    public void run() {        super.run();        String str = get();        Test test = gson.fromJson(str, Test.class);        for (int i = 0; i < test.getData().size(); i++) {            Log.e("JSONActivityTag", test.getData().get(i).getName() + "");        }    }}.start();

如下所示,我们已经成功的将 json 数据中所有的名字都解析出来了。
Android 中的网络操作(HttpURLConnection)_第8张图片

四、项目源码

项目源码下载地址。直接下载项目到本地然后导入就可以直接运行了,以上所有的 API 都是通过玩Android获取到的。

更多相关文章

  1. 20172323 2017-2018-2《程序设计与数据结构》第十一周学习总结
  2. Android多文件断点续传(二)——实现数据库储存下载信息
  3. Android数据存储方式:SharePreference、SQLite、ContentProvider
  4. android以后台service的方式获取GPRS数据
  5. Android 数据库对比
  6. 20、从头学Android之Android的数据存储--File

随机推荐

  1. 如何强制删除或恢复SQLServer正在使用的
  2. 清除SQLServer日志的两种方法
  3. SQL Server连接失败错误及解决第1/5页
  4. 最长用最基本的MSSQL数据库备份与还原
  5. 如何创建SQL Server 2000故障转移群集
  6. SQL Server 中调整自增字段的当前初始值
  7. MDF文件在SQL Server中的恢复技术
  8. MS-SQL Server 中单引号的两种处理方法
  9. sql数据库不能直接用instr函数
  10. 显示 Sql Server 中所有表中的信息