Android HTTP協議請求網路(三)之HttpURLConnection方式
阿新 • • 發佈:2018-12-31
為了演示HttpURLConnection的常見用法,我做了一個App,介面如下所示:
主介面MainActivity有四個按鈕,分別表示用GET傳送請求、用POST傳送鍵值對資料、用POST傳送XML資料以及用POST傳送JSON資料,點選對應的按鈕會啟動NetworkActivity並執行相應的操作。
NetworkActivity的原始碼如下所示,此處先貼出程式碼,後面會詳細說明。
package com.ispring.httpurlconnection;
import android.content.Intent;
import android.content.res.AssetManager;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class NetworkActivity extends AppCompatActivity {
private NetworkAsyncTask networkAsyncTask = new NetworkAsyncTask();
private TextView tvUrl = null;
private TextView tvRequestHeader = null;
private TextView tvRequestBody = null;
private TextView tvResponseHeader = null;
private TextView tvResponseBody = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network);
tvUrl = (TextView) findViewById(R.id.tvUrl);
tvRequestHeader = (TextView) findViewById(R.id.tvRequestHeader);
tvRequestBody = (TextView) findViewById(R.id.tvRequestBody);
tvResponseHeader = (TextView) findViewById(R.id.tvResponseHeader);
tvResponseBody = (TextView) findViewById(R.id.tvResponseBody);
Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {
String networkAction = intent.getStringExtra("action");
networkAsyncTask.execute(networkAction);
}
}
//用於進行網路請求的AsyncTask
class NetworkAsyncTask extends AsyncTask<String, Integer, Map<String, Object>> {
//NETWORK_GET表示傳送GET請求
public static final String NETWORK_GET = "NETWORK_GET";
//NETWORK_POST_KEY_VALUE表示用POST傳送鍵值對資料
public static final String NETWORK_POST_KEY_VALUE = "NETWORK_POST_KEY_VALUE";
//NETWORK_POST_XML表示用POST傳送XML資料
public static final String NETWORK_POST_XML = "NETWORK_POST_XML";
//NETWORK_POST_JSON表示用POST傳送JSON資料
public static final String NETWORK_POST_JSON = "NETWORK_POST_JSON";
@Override
protected Map<String, Object> doInBackground(String... params) {
Map<String,Object> result = new HashMap<>();
URL url = null;//請求的URL地址
HttpURLConnection conn = null;
String requestHeader = null;//請求頭
byte[] requestBody = null;//請求體
String responseHeader = null;//響應頭
byte[] responseBody = null;//響應體
String action = params[0];//http請求的操作型別
try {
if (NETWORK_GET.equals(action)) {
//傳送GET請求
url = new URL("http://192.168.31.200:8080/HttpServer/MyServlet?name=孫群&age=27");
conn = (HttpURLConnection) url.openConnection();
//HttpURLConnection預設就是用GET傳送請求,所以下面的setRequestMethod可以省略
conn.setRequestMethod("GET");
//HttpURLConnection預設也支援從服務端讀取結果流,所以下面的setDoInput也可以省略
conn.setDoInput(true);
//用setRequestProperty方法設定一個自定義的請求頭:action,由於後端判斷
conn.setRequestProperty("action", NETWORK_GET);
//禁用網路快取
conn.setUseCaches(false);
//獲取請求頭
requestHeader = getReqeustHeader(conn);
//在對各種引數配置完成後,通過呼叫connect方法建立TCP連線,但是並未真正獲取資料
//conn.connect()方法不必顯式呼叫,當呼叫conn.getInputStream()方法時內部也會自動呼叫connect方法
conn.connect();
//呼叫getInputStream方法後,服務端才會收到請求,並阻塞式地接收服務端返回的資料
InputStream is = conn.getInputStream();
//將InputStream轉換成byte陣列,getBytesByInputStream會關閉輸入流
responseBody = getBytesByInputStream(is);
//獲取響應頭
responseHeader = getResponseHeader(conn);
} else if (NETWORK_POST_KEY_VALUE.equals(action)) {
//用POST傳送鍵值對資料
url = new URL("http://192.168.31.200:8080/HttpServer/MyServlet");
conn = (HttpURLConnection) url.openConnection();
//通過setRequestMethod將conn設定成POST方法
conn.setRequestMethod("POST");
//呼叫conn.setDoOutput()方法以顯式開啟請求體
conn.setDoOutput(true);
//用setRequestProperty方法設定一個自定義的請求頭:action,由於後端判斷
conn.setRequestProperty("action", NETWORK_POST_KEY_VALUE);
//獲取請求頭
requestHeader = getReqeustHeader(conn);
//獲取conn的輸出流
OutputStream os = conn.getOutputStream();
//獲取兩個鍵值對name=孫群和age=27的位元組陣列,將該位元組陣列作為請求體
requestBody = new String("name=孫群&age=27").getBytes("UTF-8");
//將請求體寫入到conn的輸出流中
os.write(requestBody);
//記得呼叫輸出流的flush方法
os.flush();
//關閉輸出流
os.close();
//當呼叫getInputStream方法時才真正將請求體資料上傳至伺服器
InputStream is = conn.getInputStream();
//獲得響應體的位元組陣列
responseBody = getBytesByInputStream(is);
//獲得響應頭
responseHeader = getResponseHeader(conn);
} else if (NETWORK_POST_XML.equals(action)) {
//用POST傳送XML資料
url = new URL("http://192.168.31.200:8080/HttpServer/MyServlet");
conn = (HttpURLConnection) url.openConnection();
//通過setRequestMethod將conn設定成POST方法
conn.setRequestMethod("POST");
//呼叫conn.setDoOutput()方法以顯式開啟請求體
conn.setDoOutput(true);
//用setRequestProperty方法設定一個自定義的請求頭:action,由於後端判斷
conn.setRequestProperty("action", NETWORK_POST_XML);
//獲取請求頭
requestHeader = getReqeustHeader(conn);
//獲取conn的輸出流
OutputStream os = conn.getOutputStream();
//讀取assets目錄下的person.xml檔案,將其位元組陣列作為請求體
requestBody = getBytesFromAssets("person.xml");
//將請求體寫入到conn的輸出流中
os.write(requestBody);
//記得呼叫輸出流的flush方法
os.flush();
//關閉輸出流
os.close();
//當呼叫getInputStream方法時才真正將請求體資料上傳至伺服器
InputStream is = conn.getInputStream();
//獲得響應體的位元組陣列
responseBody = getBytesByInputStream(is);
//獲得響應頭
responseHeader = getResponseHeader(conn);
} else if (NETWORK_POST_JSON.equals(action)) {
//用POST傳送JSON資料
url = new URL("http://192.168.31.200:8080/HttpServer/MyServlet");
conn = (HttpURLConnection) url.openConnection();
//通過setRequestMethod將conn設定成POST方法
conn.setRequestMethod("POST");
//呼叫conn.setDoOutput()方法以顯式開啟請求體
conn.setDoOutput(true);
//用setRequestProperty方法設定一個自定義的請求頭:action,由於後端判斷
conn.setRequestProperty("action", NETWORK_POST_JSON);
//獲取請求頭
requestHeader = getReqeustHeader(conn);
//獲取conn的輸出流
OutputStream os = conn.getOutputStream();
//讀取assets目錄下的person.json檔案,將其位元組陣列作為請求體
requestBody = getBytesFromAssets("person.json");
//將請求體寫入到conn的輸出流中
os.write(requestBody);
//記得呼叫輸出流的flush方法
os.flush();
//關閉輸出流
os.close();
//當呼叫getInputStream方法時才真正將請求體資料上傳至伺服器
InputStream is = conn.getInputStream();
//獲得響應體的位元組陣列
responseBody = getBytesByInputStream(is);
//獲得響應頭
responseHeader = getResponseHeader(conn);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//最後將conn斷開連線
if (conn != null) {
conn.disconnect();
}
}
result.put("url", url.toString());
result.put("action", action);
result.put("requestHeader", requestHeader);
result.put("requestBody", requestBody);
result.put("responseHeader", responseHeader);
result.put("responseBody", responseBody);
return result;
}
@Override
protected void onPostExecute(Map<String, Object> result) {
super.onPostExecute(result);
String url = (String)result.get("url");//請求的URL地址
String action = (String) result.get("action");//http請求的操作型別
String requestHeader = (String) result.get("requestHeader");//請求頭
byte[] requestBody = (byte[]) result.get("requestBody");//請求體
String responseHeader = (String) result.get("responseHeader");//響應頭
byte[] responseBody = (byte[]) result.get("responseBody");//響應體
//更新tvUrl,顯示Url
tvUrl.setText(url);
//更新tvRequestHeader,顯示請求頭
if (requestHeader != null) {
tvRequestHeader.setText(requestHeader);
}
//更新tvRequestBody,顯示請求體
if(requestBody != null){
try{
String request = new String(requestBody, "UTF-8");
tvRequestBody.setText(request);
}catch (UnsupportedEncodingException e){
e.printStackTrace();
}
}
//更新tvResponseHeader,顯示響應頭
if (responseHeader != null) {
tvResponseHeader.setText(responseHeader);
}
//更新tvResponseBody,顯示響應體
if (NETWORK_GET.equals(action)) {
String response = getStringByBytes(responseBody);
tvResponseBody.setText(response);
} else if (NETWORK_POST_KEY_VALUE.equals(action)) {
String response = getStringByBytes(responseBody);
tvResponseBody.setText(response);
} else if (NETWORK_POST_XML.equals(action)) {
//將表示xml的位元組陣列進行解析
String response = parseXmlResultByBytes(responseBody);
tvResponseBody.setText(response);
} else if (NETWORK_POST_JSON.equals(action)) {
//將表示json的位元組陣列進行解析
String response = parseJsonResultByBytes(responseBody);
tvResponseBody.setText(response);
}
}
//讀取請求頭
private String getReqeustHeader(HttpURLConnection conn) {
//https://github.com/square/okhttp/blob/master/okhttp-urlconnection/src/main/java/okhttp3/internal/huc/HttpURLConnectionImpl.java#L236
Map<String, List<String>> requestHeaderMap = conn.getRequestProperties();
Iterator<String> requestHeaderIterator = requestHeaderMap.keySet().iterator();
StringBuilder sbRequestHeader = new StringBuilder();
while (requestHeaderIterator.hasNext()) {
String requestHeaderKey = requestHeaderIterator.next();
String requestHeaderValue = conn.getRequestProperty(requestHeaderKey);
sbRequestHeader.append(requestHeaderKey);
sbRequestHeader.append(":");
sbRequestHeader.append(requestHeaderValue);
sbRequestHeader.append("\n");
}
return sbRequestHeader.toString();
}
//讀取響應頭
private String getResponseHeader(HttpURLConnection conn) {
Map<String, List<String>> responseHeaderMap = conn.getHeaderFields();
int size = responseHeaderMap.size();
StringBuilder sbResponseHeader = new StringBuilder();
for(int i = 0; i < size; i++){
String responseHeaderKey = conn.getHeaderFieldKey(i);
String responseHeaderValue = conn.getHeaderField(i);
sbResponseHeader.append(responseHeaderKey);
sbResponseHeader.append(":");
sbResponseHeader.append(responseHeaderValue);
sbResponseHeader.append("\n");
}
return sbResponseHeader.toString();
}
//根據位元組陣列構建UTF-8字串
private String getStringByBytes(byte[] bytes) {
String str = "";
try {
str = new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return str;
}
//從InputStream中讀取資料,轉換成byte陣列,最後關閉InputStream
private byte[] getBytesByInputStream(InputStream is) {
byte[] bytes = null;
BufferedInputStream bis = new BufferedInputStream(is);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(baos);
byte[] buffer = new byte[1024 * 8];
int length = 0;
try {
while ((length = bis.read(buffer)) > 0) {
bos.write(buffer, 0, length);
}
bos.flush();
bytes = baos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bytes;
}
//根據檔名,從asserts目錄中讀取檔案的位元組陣列
private byte[] getBytesFromAssets(String fileName){
byte[] bytes = null;
AssetManager assetManager = getAssets();
InputStream is = null;
try{
is = assetManager.open(fileName);
bytes = getBytesByInputStream(is);
}catch (IOException e){
e.printStackTrace();
}
return bytes;
}
//將表示xml的位元組陣列進行解析
private String parseXmlResultByBytes(byte[] bytes) {
InputStream is = new ByteArrayInputStream(bytes);
StringBuilder sb = new StringBuilder();
List<Person> persons = XmlParser.parse(is);
for (Person person : persons) {
sb.append(person.toString()).append("\n");
}
return sb.toString();
}
//將表示json的位元組陣列進行解析
private String parseJsonResultByBytes(byte[] bytes){
String jsonString = getStringByBytes(bytes);
List<Person> persons = JsonParser.parse(jsonString);
StringBuilder sb = new StringBuilder();
for (Person person : persons) {
sb.append(person.toString()).append("\n");
}
return sb.toString();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358