본문 바로가기

안드로이드/러닝패스

[#A4 DEPRECATED] 내 앱에서 쉽게 외부와 JSON 데이터를 주고 받는 방법 <Volley>

VOLLEY는 현재 DEPRECATED 된 HTTP 라이브러리지만, 현재 사용되는 RETROFIT 2 만큼의 편리함을 가지고 있는 사용 가능한 HTTP 라이브러리입니다.


이를 이용하면 특히 데이터를 쉽게 불러오고 전송할 수 있습니다.



VOLLEY 를 라이브러리에 추가


1
2
3
4
5
6
//build.grade (Module: app)
 
dependencies {
    implementation 'com.mcxiaoke.volley:library-aar:1.0.1'
}
 
cs

성공적으로 추가했다면, 패키지 폴더에 Volley 폴더를 만든 후[옵션] AppController 클래스를 생성합니다.


AppController.java


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
public class AppController extends Application {
 
    public static final String TAG = AppController.class
            .getSimpleName();
 
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;
 
    private static AppController mInstance;
 
    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }
 
    public static synchronized AppController getInstance() {
        return mInstance;
    }
 
    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }
 
        return mRequestQueue;
    }
 
    public ImageLoader getImageLoader() {
        getRequestQueue();
        if (mImageLoader == null) {
            mImageLoader = new ImageLoader(this.mRequestQueue,
                    new LruBitmapCache());
        }
        return this.mImageLoader;
    }
 
    public <T> void addToRequestQueue(Request<T> req, String tag) {
        // set the default tag if tag is empty
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(req);
    }
 
    public <T> void addToRequestQueue(Request<T> req) {
        req.setTag(TAG);
        getRequestQueue().add(req);
    }
 
    public void cancelPendingRequests(Object tag) {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        }
    }
}
cs


두 개의 클래스를 성공적으로 추가했다면, AndroidManifest.xml 에 다음과 같이 인터넷 퍼미션과 android:name을 추가합니다.


1
2
3
4
<uses-permission android:name="android.permission.INTERNET"/>
 
<application
        android:name="com.myPackage.AppController">
cs


A. 데이터를 받아오는 방법


Volley로 데이터를 받아오는 방법은 데이터 형식에 따라 두가지로 나뉘게 됩니다.


: JsonObjectRequest


: JsonArrayRequest



(1) JsonObjectRequest


다음과 같은 JSON 데이터 형식은 objectRequest를 사용합니다


1
2
3
4
5
6
7
8
9
10
11
{
    "name" : "Ravi Tamada"
    "email" : "ravi8x@gmail.com",
    "phone" : {
        "home" : "08947 000000",
        "mobile" : "9999999999"
    }
     
}
 
/*FROM www.androidhive.info*/
cs



안드로이드에서는 다음과 같은 방식으로 데이터를 가져옵니다.

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
private void makeJsonObjectRequest() {
 
    JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.GET,
            URL, nullnew Response.Listener<JSONObject>() {
 
                @Override
                public void onResponse(JSONObject response) {
                    Log.d(TAG, response.toString());
 
                    try {
                        // Parsing json object response
                        // response will be a json object
                        String name = response.getString("name");
                        String email = response.getString("email");

                        JSONObject phone = response.getJSONObject("phone");
                        String home = phone.getString("home");
                        String mobile = phone.getString("mobile");
 
                        jsonResponse = "";
                        jsonResponse += "Name: " + name + "\n\n";
                        jsonResponse += "Email: " + email + "\n\n";
                        jsonResponse += "Home: " + home + "\n\n";
                        jsonResponse += "Mobile: " + mobile + "\n\n";
 
                        txtResponse.setText(jsonResponse);
 
                    } catch (JSONException e) {
                        e.printStackTrace();
                        Toast.makeText(getApplicationContext(),
                                "Error: " + e.getMessage(),
                                Toast.LENGTH_LONG).show();
                    }
                    hidepDialog();
                }
            }, new Response.ErrorListener() {
 
                @Override
                public void onErrorResponse(VolleyError error) {
                    VolleyLog.d(TAG, "Error: " + error.getMessage());
                    Toast.makeText(getApplicationContext(),
                            error.getMessage(), Toast.LENGTH_SHORT).show();
                    // hide the progress dialog
                    hidepDialog();
                }
            });
 
    // Adding request to request queue
    AppController.getInstance().addToRequestQueue(jsonObjReq);
}
 
/*FROM www.androidhive.info*/
cs



(2) JsonArrayRequest


다음과 같은 JSON 데이터 형식은 ArrayRequest를 사용합니다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[
    {
    "name" : "Ravi Tamada"
    "email" : "ravi8x@gmail.com",
    "phone" : {
        "home" : "08947 000000",
        "mobile" : "9999999999"
    }
    },
    {
    "name" : "Tommy"
    "email" : "tommy@gmail.com",
    "phone" : {
        "home" : "08946 000000",
        "mobile" : "0000000000"
    }
    }
]
 
/*FROM www.androidhive.info*/
cs



안드로이드에서는 다음과 같은 방식으로 데이터를 가져옵니다.


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
private void makeJsonArrayRequest() {
 
    JsonArrayRequest req = new JsonArrayRequest(URL,
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    Log.d(TAG, response.toString());
 
                    try {
                        // Parsing json array response
                        // loop through each json object
                        jsonResponse = "";
                        for (int i = 0; i < response.length(); i++) {
 
                            JSONObject person = (JSONObject) response
                                    .get(i);
 
                            String name = person.getString("name");
                            String email = person.getString("email");
                            
                            JSONObject phone = person.getJSONObject("phone");
                            String home = phone.getString("home");
                            String mobile = phone.getString("mobile");
 
                            jsonResponse += "Name: " + name + "\n\n";
                            jsonResponse += "Email: " + email + "\n\n";
                            jsonResponse += "Home: " + home + "\n\n";
                            jsonResponse += "Mobile: " + mobile + "\n\n\n";
 
                        }
 
                        txtResponse.setText(jsonResponse);
 
                    } catch (JSONException e) {
                        e.printStackTrace();
                        Toast.makeText(getApplicationContext(),
                                "Error: " + e.getMessage(),
                                Toast.LENGTH_LONG).show();
                    }
 
                    hidepDialog();
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    VolleyLog.d(TAG, "Error: " + error.getMessage());
                    Toast.makeText(getApplicationContext(),
                            error.getMessage(), Toast.LENGTH_SHORT).show();
                    hidepDialog();
                }
            });
 
    // Adding request to request queue
    AppController.getInstance().addToRequestQueue(req);
}
 
/*FROM www.androidhive.info*/
cs


공통적으로 AppController.getInstance().addToRequestQueue() 메소드로 작업을 요청합니다. ArrayRequest는 반복문으로 Array의 데이터를 하나 하나 모두 가져오게 됩니다. ( 1회에 Ravi Tamada 의 정보를, 2회에 Tommy의 정보를 가져옵니다 )


B. 데이터를 보내는 방법

데이터를 보내는 방법에는 GET, POST 두 가지가 있습니다.

GET 방식은 URL에 데이터를 포함시켜 보내기 때문에 간단하지만 보안에 취약하고, POST 방식은 URL과 함께 데이터를 BODY로 구성한 후 보내게 됩니다.

(1) GET 방식

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
String url = URL_JSON_OBJECT_REQUEST + "?data1=" + data1 + "&data2=" + data2 + "&data3=" + data3;
 
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
                        url, nullnew Response.Listener<JSONObject>() {
 
       @Override
       public void onResponse(JSONObject response) {
                        
       //SUCCESS
       Log.d(TAG, response.toString());
 
       }
}, new Response.ErrorListener() {
 
       @Override
       public void onErrorResponse(VolleyError error) {
       VolleyLog.d(TAG, "Error: " + error.getMessage());
       Toast.makeText(getApplicationContext(),
       error.getMessage(), Toast.LENGTH_SHORT).show();
       }
 
});
 
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq);
cs

GET 방식에서 URL은 기본적으로 이런 형태를 가지고 있습니다.

"http://00.000.000.000/request.php?data1=" + data1 + "&data2=" + data2 + ...


(2) POST 방식


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
    public void makeStringRequest(final String data1, final String data2, final String data3){
 
        String tag_string_req = "request_register_result";
 
        StringRequest strReq = new StringRequest(Request.Method.POST,
                URL_MY_REQUEST, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
 
                try {
                    JSONObject jObj = new JSONObject(response);
                    boolean error = jObj.getBoolean("error");
 
                    if (!error) {
 
                        goMainFunc();
 
                    } else {
 
                        Toast.makeText(ResultActivity.this"요청에 실패했습니다 : 서버 오류", Toast.LENGTH_SHORT).show();
 
                    }
 
                } catch (JSONException e) {
 
                    e.printStackTrace();
 
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
 
                Log.e(TAG, "Error: " + error.getMessage());
 
            }
        }) {
            @Override
            protected Map<StringString> getParams() throws AuthFailureError {
                Map<StringString> params = new HashMap<StringString>();
                params.put("data1", data1);
                params.put("data2", data2);
                params.put("data3", data3);
                return params;
            }
        };
 
        AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
 
    }
cs


여기서 URL_MY_REQUEST는 "http://00.00.000.000/request.php" 입니다.

이는 개인 웹서버에 저장된 PHP 문서를 사용하는 방법이고, 때에 따라서 도메인이 지정된 경우 00.00.000.000 부분은 도메인으로 대체될 수 있습니다.



TIP. DB를 통해 JSON 데이터를 포함한 URL을 생성하거나, 보낸 데이터를 DB에 저장하는 방법


이런 이슈들을 해결하는 방법은 무수히 많겠지만, PHP + MYSQL 세트를 이용하는 것이 가장 편리한 방법 중 하나가 될 수 있습니다. 

이에 대해서는 해당 포스트를 참고하세요.


JSON 데이터를 포함한 URL 생성 [#G2 : PHP를 이용해 DB[MySQL]의 데이터를 내보내는 방법]


보낸 데이터를 DB에 저장하는 방법 [#G1 : PHP를 이용해 DB[MySQL]에 데이터를 저장하는 방법]