在 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