2014年6月19日 星期四

Android 使用Volley發送RESTful request

Android Volley建置一文中筆者建立了Volley的jar檔但卻沒有提說怎麼使用,接下來說明如何使用Volley發送RESTful request吧

流程說明

1. 建立Volley的RequestQueue: 使用者將request放到RequestQueue後Volley會自動將request以非同步方式發送出去

2. 建立JsonObjectRequest, JsonArrayRequest或StringRequest: 依照target的RESTful service規格決定要用JSONObject, JSONArray或String其中之一吧~
註: 筆者採用 使用CodeIgniter架設RESTful Web Service 一文中架設的RESTful web service當做練習對象,其index.php同時提供GET, POST, PUT和DELETE的範例

3. 將第2步中產生的request放到RequestQueue中

4. 等待server的回應並進行處理


實作

1. 建立Android application project



2. 加入volley.jar到專案中

  建置volley.jar可參考Android Volley建置

3. 建立RequestQueue

  此處採用Singleton pattern建立Singleton class,其名稱為ApplicationController,詳細程式碼可參考"參考資料1",以下的程式碼筆者針對Singlegon做簡單的說明
public class ApplicationController extends Application {

    /**
     * Log or request TAG
     */
    public static final String TAG = "VolleyPatterns";

    /**
     * Global request queue for Volley
     */
    private RequestQueue mRequestQueue;

    /**
     * A singleton instance of the application class for easy access in other places
     * Singleton物件,簡單的說就是整個app只會有這一個ApplicationController物件,理想上不會產生第二份ApplicationController物件
     */
    private static ApplicationController sInstance;

    @Override
    public void onCreate() {
        super.onCreate();

        // initialize the singleton
        sInstance = this;
    }

    /**
     * @return ApplicationController singleton instance
     * 要使用ApplicationController一定要先透過此method取得ApplicationController物件
     */
    public static synchronized ApplicationController getInstance() {
        return sInstance;
    }

    /**
     * @return The Volley Request queue, the queue will be created if it is null
     */
    public RequestQueue getRequestQueue() {
        // lazy initialize the request queue, the queue instance will be
        // created when it is accessed for the first time
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }

        return mRequestQueue;
    }

    /**
     * Adds the specified request to the global queue, if tag is specified
     * then it is used else Default TAG is used.
     * 
     * @param req
     * @param tag
     */
    public  void addToRequestQueue(Request req, String tag) {
        // set the default tag if tag is empty
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);

        VolleyLog.d("Adding request to queue: %s", req.getUrl());

        getRequestQueue().add(req);
    }

    /**
     * Adds the specified request to the global queue using the Default TAG.
     * 
     * @param req
     * @param tag
     */
    public  void addToRequestQueue(Request req) {
        // set the default tag if tag is empty
        req.setTag(TAG);

        getRequestQueue().add(req);
    }

    /**
     * Cancels all pending requests by the specified TAG, it is important
     * to specify a TAG so that the pending/ongoing requests can be cancelled.
     * 
     * @param tag
     */
    public void cancelPendingRequests(Object tag) {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        }
    }
}

4. 修改AndroidManifest.xml

  加入網路存取權限以及開啟app自動啟動ApplicationController
    <!-- 加入網路存取權限 -->
    <uses-permission android:name="android.permission.INTERNET" />
       
    <!-- 加入android:name這項屬性讓ApplicationController能在開啟app後自動建立ApplicationController-->
    <application
        android:name=".ApplicationController"
        android:allowBackup="true"
        .......
    />

5. 建立request

i. GET
private void doGet(){
    // Service的URL
    String url = "http://192.168.11.13/~shiun/ws/service/index";
    // 建立期望收到JsonObject的request
    // 若new JsonObjectRequest的第二個參數為null則代表是GET,反之若為JSONObject則為POST
    JsonObjectRequest request = new JsonObjectRequest(url, null, 
        new Listener<JSONObject>() {
            // 若server回傳HTTP status 200或204則會進入onResponse method 
            // 註:根據官網Issue 57527的討論,最新版應該是2xx都算request success
            @Override
            public void onResponse(JSONObject response) {
                Log.i(tag, response.toString());
            }
        }, new ErrorListener() { // Request失敗處理
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(tag, error.getMessage());
            }
    });
    // 將request放到RequestQueue,Volley會以非同步方式送出request
    ApplicationController.getInstance().addToRequestQueue(request);
}

GET成功~

ii. POST: POST的關鍵在於new JsonObjectRequest時要將POST的資料放到第二個參數中
private void doPost() throws JSONException {
    // Service的URL
    String url = "http://192.168.11.13/~shiun/ws/service/index";
    JSONObject param = new JSONObject();
    param.put("key1", "POST_value1");
    param.put("key2", "POST_value2");
    // 建立期望收到JsonObject的request
    // 因為第二個參數不是null,所以Volley把request當做POST傳送
    JsonObjectRequest request = new JsonObjectRequest(url, param, 
        new Listener<JSONObject>()
        // Request成功
            @Override
            public void onResponse(JSONObject response) {
                Log.i(tag, response.toString());
            }
        }, new ErrorListener() { // Request失敗處理
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(tag, error.getMessage());
            }
    });
    // 將request放到RequestQueue,Volley會以非同步方式送出request
    ApplicationController.getInstance().addToRequestQueue(request);
}

POST成功~

iii. PUT: PUT的關鍵點在於要new有method版本的JsonObjectRequest
private void doPut() throws JSONException
{
    String url = "http://192.168.11.13/~shiun/ws/service/index";
    JSONObject param = new JSONObject();
    param.put("key1", "PUT_value1");
    param.put("key2", "PUT_value2");
    // 這次的關鍵點在於使用Request.Method.PUT
    JsonObjectRequest request = new JsonObjectRequest(Request.Method.PUT, url, param,
        new Listener() {
            @Override
            public void onResponse(JSONObject response) {
                Log.i(tag, response.toString());
            }
        }, new ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(tag, error.getMessage());
            }
        });
    ApplicationController.getInstance().addToRequestQueue(request);
}

PUT成功~

iv. DELETE: DELETE時只需要把Method換成Request.Method.DELETE並配合service提供的URL即可
private void doDelete() throws JSONException
{
    String url = "http://192.168.11.13/~shiun/ws/service/index/1";
    JsonObjectRequest request = new JsonObjectRequest(Request.Method.DELETE, url, null,
        new Listener() {
            @Override
            public void onResponse(JSONObject response) {
                Log.i(tag, response.toString());
            }
        }, new ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(tag, error.getMessage());
            }
        });
    ApplicationController.getInstance().addToRequestQueue(request);
}

DELETE成功~


參考資料

1. Asynchronous HTTP Requests in Android Using Volley

2. Android Volley Tutorial - Making HTTP GET, POST, PUT, DELETE Requests

3. Application-element: "Android:name"

沒有留言:

張貼留言