乐趣区

关于android:Android-中的网络操作HttpURLConnection

segmentfault 对 mackdown 语法的反对不是很好,有些图片都显示不进去,大家能够去我的掘金查看这篇文章。

一、Android 网络常识简介

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

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

1、权限申请

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

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

Android 9.0 之前,只须要在清单文件中加上这句话就能够了,然而 Android 9.0 对 http 申请进行了限度,所以仅仅下面这一句话是不够的。为了解除这个限度,咱们须要创立平安配置文件,具体步骤如下:

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

  1. 减少 cleartextTrafficPermitted 属性

    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
       <base-config cleartextTrafficPermitted="true"/>
    </network-security-config>
  2. 在 AndroidManifest.xml 的 Application 节点中申请

    android:networkSecurityConfig="@xml/network_security_config"

2、get 申请

咱们从玩 Android 下面轻易找一个 GET 申请的 API。json 数据格式如下所示:

当初咱们来利用 HttpURLConnection 的 GET 申请来将下面这段 json 数据打印进去,具体代码如下所示:

 private final String URL = "https://wanandroid.com/wxarticle/chapters/json";
 
 // HttpURLConnection
private 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;
    }
}

控制台下面的数据如下,咱们曾经胜利的打印进去了。

通过上述代码咱们须要留神一下三点:

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

3、post 申请

咱们从玩 Android 下面找一个 POST 申请的 API。而后咱们能够利用 HttpURLConnection 的 POST 申请来实现一个登陆性能。

具体代码实现如下所示:

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 解析


当初咱们要在以上 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 属性对应的值就能够了。

具体的成果如下所示:

残缺代码如下:

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)


我能依据下面的一个 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 字符串了。

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

咱们利用 fromJson 办法将上述 json 对象中的 name 都输入进去,咱们须要创立一个 Test 对象,具体代码如下所示:

public class Test {

    private List<Wxarticle> data;
    private int errorCode;
    private String errorMsg;

    public Test() {}

    public Test(List<Wxarticle> data, int errorCode, String errorMsg) {
        this.data = data;
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }

    public List<Wxarticle> getData() {return data;}

    public void setData(List<Wxarticle> 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;}
}

具体解析代码如下所示:

 // fromJson
new 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 数据中所有的名字都解析进去了。

四、我的项目源码

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

退出移动版