RESTful web service: Get and Post
Make request and get the response in the background
The Android platform does not allow you to run network operations on the main thread of the application Android From Scratch: Using REST APIs.
需要將執行 web service 的程式置於背景執行. 在 Android 中執行背景程式參考 AsyncTask.
Executing Get method
執行 Get 的步驟:
- 建立 URL 物件
- 利用 URL 物件 open 一個 HTTPURLConnection 物件.
- 設定 HTTPURLConnection 物件的 request property. Http 的預設方法為 Get.
- 執行 connect.
- 當 http status code 為 200 時, 從 Connection 物件取得 InputStream
- 將 InputStream wrap 成為 InputStreamReader (使用 UTF-8 編碼) 讀取的內容
- 將字串內容轉成 JSON Array 或者 JSON Object
Example
doGetRequest(String)
/**
* Do the HTTP Get request. 需要在背景執行.
*
* @param urlStr RESTful Web Service URL
* @return the JSON format string
*/
public String doGetRequest(String urlStr) {
URL targetURL = null;
String returnValue = null;
try {
targetURL = new URL(urlStr);
} catch (MalformedURLException e) {
e.printStackTrace();
}
HttpURLConnection conn;
try {
conn = (HttpURLConnection) targetURL.openConnection();
// prepare request header
conn.setRequestProperty("User-Agent", "Android_TicketCareDBClient");
conn.setRequestProperty("Accept", "application/json");
conn.connect();
int statusCode = conn.getResponseCode();
if (statusCode == 200){
InputStreamReader isr = new InputStreamReader(conn.getInputStream());
returnValue = this.getBodyContent(isr).get(0);
isr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return returnValue;
}
Executing Post method
執行 Post 的 Steps:
- Prepare your json object: 建議在 domain object 提供一個方法, 將 domain object 轉成 JSON object.
- Execute the POST request
- Open connection with post method: 使用
URL
class 建立 URL object, 並取得HttpURLConnection
物件. - Set request property: 在
httpURLConnection
物件上設定 request method 及 properties. - Execute connection: 呼叫
httpURLConnection
物件的connect()
執行 connection. - Get the output stream: 在
httpURLConnection
物件上取得outputStream
物件, 並再 wrap 成為DataOutputStream
物件, 以便後續寫入 binary data. - Write the the string of the json object: 使用
DataOutputStream
物件的writeBytes(String)
方法將 JSON object 的字串資料寫入到輸出串流中. 記得 flush 及 close 輸出串流.
- Open connection with post method: 使用
- Get the response code from connection: 利用
httpURLConnection
物件的getResponseCode()
及getResponseMessage()
取得 http 的 response code 及 message. Post 成功的 response code 為 204.
Reference: [Android POST request with JSON] (https://stackoverflow.com/questions/42767249/android-post-request-with-json)
Example
Domain Object: TicketCategoryEntity
package com.hychen39.restuful_test.domains;
import org.json.JSONException;
import org.json.JSONObject;
/**
* 票卷類別
* Created by steven on 11/30/2017.
*/
public class TicketCategoryEntity {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof TicketCategoryEntity)) {
// inconsistent type
return false;
}
TicketCategoryEntity other = (TicketCategoryEntity) obj;
if ((this.id == null && other.id != null) || this.id != null && !this.id.equals(other.id)) {
return false;
}
return true;
}
/**
* Conver the object to JSON object
*
* @return JSON object
*/
public JSONObject toJsonObject() {
// get bean property info
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("id", this.id);
jsonObject.put("name", this.name);
} catch (JSONException e) {
e.printStackTrace();
}
return jsonObject;
}
}
TicketCardDBClient 的 postTicketCategory() 方法
/**
* @param ticketCategory
* @see com.hychen39.restuful_test.domains.TicketCategoryEntity
*/
public String postTicketCategory(TicketCategoryEntity ticketCategory) {
// Prepare the JSON object
JSONObject jsonObject = ticketCategory.toJsonObject();
URL postURL = null;
try {
postURL = new URL(TICKET_CATEGORY_RES_URL);
} catch (MalformedURLException e) {
e.printStackTrace();
}
String status = "", msg="";
try {
// open connection
HttpURLConnection conn = (HttpURLConnection) postURL.openConnection();
// set request method and properties
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
conn.setDoOutput(true); // 使用 connection 進行 Output, set the DoOutput flag to true.
conn.setDoInput(true); // 使用 connection 進行 Input
conn.connect();
// get the output stream
DataOutputStream os = new DataOutputStream(conn.getOutputStream());
// write the content
os.writeBytes(jsonObject.toString());
// flush and close output stream
os.flush();
os.close();
// log response
status = String.valueOf(conn.getResponseCode());
msg = conn.getResponseMessage();
Log.i("STATUS", status);
Log.i("MSG", msg);
} catch (IOException e) {
e.printStackTrace();
}
// return status code.
return status;
}
測試碼
package com.hychen39.restuful_test;
import com.hychen39.restuful_test.domains.TicketCategoryEntity;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Created by steven on 11/30/2017.
*/
public class TicketCareDBClientTest {
@Test
public void postTicketCategory() throws Exception {
// Create the DB client
TicketCareDBClient client = new TicketCareDBClient();
//Create a new ticket category entity
TicketCategoryEntity ticketCategory = new TicketCategoryEntity();
ticketCategory.setId(new Long(11));
ticketCategory.setName("PostedCategory-11");
//
String status = client.postTicketCategory(ticketCategory);
assertEquals("204", status);
}
}
Testing Android Application
Training: Fundamentals of Testing Building Instrumented Unit Tests Test Your App