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