Android 学习笔记——使用 HTTP 协议访问网络

在 Android 上发送 HTTP 请求一般有两种方式:HttpURLConnection 和 HttpClient,由于 HttpClient 存在 API 数量过多、扩展困难等问题,在 Android 6.0 已经被完全淘汰,因此官方建议使用 HttpConnetion。
除了 HttpConnection,还有许多出色的网络通信库可供我们使用,比如 Square 开发的 OktHttp,在接口封装上做的简单易用,便于满足我们开发时的网络通信需求。
OkHttp的项目地址:https://github.com/square/okhttp

下面开始介绍这两种 Android 访问网络工具的一些基本使用方法。

访问网络之前需要再在AndroidManifest.xml 文件中声明网络权限

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

1、使用 HttpURLConnection

1.1、向服务器请求数据

1、获取 HttpURLConnection 的实例,一般只需要 new 出一个 URL 对象,并传入目标的网络地址,再调用 URL 对象的 openConnection( ) 方法即可。

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

2、得到 HttpURLConnection 实例之后,可以设置 HTTP 请求所使用的方法,如 GET(从服务端获取数据) 和 POST(发送数据给服务端),写法如下:

connection.setRequestMethod("GET");

除此之外还可以进行一些自由的定制,如设置连接超时、读取超时等,根据自己的需求编写,如:

connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);

3、调用 getInputStream() 方法获取服务器返回的输入流,再对输入流进行处理。

InputStream inputStream = connection.getInputStream();

4、调用disconnect()方法还将 HTTP 连接关闭。

connection.disconnect();

demo:

public class MainActivity extends AppCompatActivity {

    private Button sendRequest;
    private TextView responseText;

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

            }
        });
    }

    private void sendRequestWithHttpURLConnection() {
        //网络访问需要在子线程内操作
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                BufferedReader reader = null;
                try {
                    URL url = new URL("www.baidu.com");
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(5000);
                    connection.setReadTimeout(5000);
                    InputStream inputStream = connection.getInputStream();
                    reader = new BufferedReader(new InputStreamReader(inputStream));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        response.append(line);
                    }
                    showResponse(response.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (reader != null) {
                        try {
                            reader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (connection != null) {
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }

    private void showResponse(final String response) {
        //Android不允许在子线程内进行UI操作,因此需要用这个方法切换到主线程进行UI操作
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                responseText.setText(response);
            }
        });
    }
}

1.2、向服务器提交数据

如果需要向服务器提交数据,只需将 HTTP 的请求方法改成 POST 即可,注意每条数据都要以键值对的形式存在,数据与数据之间用 "&" 隔开,如:

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

2、使用 OkHttp

准备工作:
使用 OkHttp 之前需要在项目中添加 OkHttp 库的依赖,修改 app/build.gradle 文件,在 dependencies 闭包中添加如下内容:

implementation 'com.squareup.okhttp3:okhttp:3.4.1'

添加完之后不要忘了点击 Sync Now 同步一下

OkHttp 的具体用法:

2.1、向服务器请求数据

1、创建一个 OkHttpClient 实例

OkHttpClient client = new OkHttpClient();

2、发起 HTTP 请求,需创建一个 Request 对象

 Request request = new Request.Builder().build();

这个对象是一个空的对象,还需要在 build() 方法前连缀其他的方法,如设置目标的网络地址:

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

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

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

response 对象就是服务器返回的数据,可以通过如下方法来获取返回的具体内容:

 String responseData = response.body().string();

demo:

package com.mattyang.httptest;

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

import java.io.IOException;

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

public class MainActivity extends AppCompatActivity {

    private Button sendRequest;
    private TextView responseText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sendRequest = (Button) findViewById(R.id.btn_send_request);
        responseText = (TextView) findViewById(R.id.tv_respnse_text);
        sendRequest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendRequestWithHttpURLConnection();
            }
        });
    }

    private void sendRequestWithHttpURLConnection() {
        //网络访问需要在子线程内操作
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder().
                            url("http://www.baidu.com")
                            .build();
                    Response response = client.newCall(request).execute();
                    String responseData = response.body().string();
                    showResponse(responseData);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void showResponse(final String response){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                responseText.setText(response);
            }
        });
    }

}

相较于 HttpURLConnection ,OkHttp 的代码量更少,犯错率也大大降低,因此更为推荐使用 OkHttp 来作为网络通信库。

2.2、向服务器发送数据

1、构建一个 RequestBody 对象来存放待提交的参数:

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

2、在 Request.Builder 中调用 post() 方法,并将 RequestBody 对象传入:

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

3、接下来的操作同 GET ,调用 execute() 方法来发送请求并获取服务器返回的数据。

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

在 Android 9.0 中,为保证用户数据和设备的安全,Google针对下一代 Android 系统(Android P)
的应用程序,将要求默认使用加密连接,这意味着 Android P 将禁止 App 使用所有未加密的连接,因此运行 Android P
系统的安卓设备无论是接收或者发送流量,未来都不能明码传输,需要使用下一代(Transport Layer
Security)传输层安全协议,而 Android Nougat 和 Oreo 则不受影响。 因此,在Android
P系统的设备上,如果应用使用的是非加密的明文流量的 HTTP 网络请求,则会导致该应用无法进行网络请求,HTTPS
则不会受影响,同样地,如果应用嵌套了 WebView,WebView 也只能使用 HTTPS 请求。

面对这种问题,有一下三种解决方法:

(1)APP改用https请求

(2)targetSdkVersion 降到27以下

(3)更改网络安全配置

详情请戳Android高版本联网失败报错:Cleartext HTTP traffic to xxx not permitted解决方法

相关资料:
《第一行代码》第二版——郭霖 人民邮电出版社
https://blog.csdn.net/gengkui9897/article/details/82863966

猜你喜欢

转载自blog.csdn.net/yangzhaopeng3/article/details/83382564
今日推荐