반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

오늘은 Android Tablet Developer's Cook Book에 나오는 JSON 관련 예제를 공부할 겁니다.


Chapter 15에 나오는 예제인데요. ConsumeJSONWebserviceApp 이라는 프로젝트 입니다.


일단 SampleJSON.php 라는 파일이 아래 경로에 있습니다.


http://www.gosolkit.com/SampleJSON.php


이 php가 만들어낸 json 데이터는 아래와 같습니다.


[{"state":"Alabama","capital":"Montgomery","latitude":"32.361538","longitude":"-86.279118"},{"state":"Alaska","capital":"Juneau","latitude":"58.301935","longitude":"-134.419740"},{"state":"Arizona","capital":"Phoenix","latitude":"33.448457","longitude":"112.073844"},{"state":"California","capital":"Secramento","latitude":"36.448457","longitude":"112.073844"},{"state":"Gangwon","capital":"Chunchon","latitude":"33.448457","longitude":"112.073844"},{"state":"Rhode Island","capital":"Providence","latitude":"33.448457","longitude":"112.073844"},{"state":"New Jersey","capital":"Trenton","latitude":"33.448457","longitude":"112.073844"}]

위 URL은 책에 있는 URL이랑은 다릅니다.

제 개인 URL 을 사용했구요. json 데이터도 안에 그 내용을 조금 더 추가했습니다.


원격에 있는 php로 생성한 JSON 파일을 받아와서 안드로이드 앱에서 사용하는 예제 입니다.


우선 첫번째로 layout xml 파일을 보죠.


activity_consume_jsonwebservice_app.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"> 
    <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/state_name"
            android:hint="Enter State Name" 
                android:textSize="@dimen/text_size"   />
    <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/submit_btn"
            android:text="Submit"
                android:textSize="@dimen/text_size" />
    <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/response"
                android:textSize="@dimen/text_size" />
</LinearLayout>


LinearLayout으로 감쌌고 orientation은 vertical 입니다.

그 안에 EditText와 Button 그리고 TextView 이렇게 세개의 view 가 있습니다.



EditText에 주 이름을 넣고 Submit 버튼을 누르면 그 아래 TextView에 원격에서 받은 JSON 데이터를 파싱해서 뿌려 줄 건가 봅니다.


그러면 이제 자바 파일을 보죠.


ConsumeJSONWebserviceAppActivity.java


public class ConsumeJSONWebserviceAppActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_consume_jsonwebservice_app);
        Button submitButton = (Button)this.findViewById(R.id.submit_btn);
        submitButton.setOnClickListener(new Button.OnClickListener(){
             public void onClick(View v)  { 
                    new ReadJSONFeed().execute("http://www.gosolkit.com/SampleJSON.php");               
             }
        });
    }
     
    private class ReadJSONFeed extends AsyncTask<String, String, String> {
        protected void onPreExecute() {}

        @Override
        protected String doInBackground(String... urls) {
       HttpClient httpclient = new DefaultHttpClient();
       StringBuilder builder = new StringBuilder();
            HttpPost httppost = new HttpPost(urls[0]);
           try {
           HttpResponse response = httpclient.execute(httppost);
        StatusLine statusLine = response.getStatusLine();
       int statusCode = statusLine.getStatusCode();
       if (statusCode == 200) {
            HttpEntity entity = response.getEntity();
            InputStream content = entity.getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(content));
            String line;
            while ((line = reader.readLine()) != null) {
                builder.append(line);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }     
    return builder.toString();
        }

        protected void onPostExecute(String result) {
            String state="";
            String stateInfo="";
            EditText stateName = (EditText) findViewById(R.id.state_name);
            String searchState=stateName.getText().toString();
            try{
             JSONArray countriesArray = new JSONArray(result);       
                   for (int i =0 ; i<countriesArray.length();i++) {
                       JSONObject jObject = countriesArray.getJSONObject(i);
                      state = jObject.getString("state");
                      if(searchState.equalsIgnoreCase(state))
                      {
                          stateInfo+="Capital: "+jObject.getString("capital")+"\n";
                          stateInfo+="Latitude: "+jObject.getString("latitude")+"\n";
                          stateInfo+="Longitude: "+jObject.getString("longitude")+"\n";
                      }
                   }
            }
             catch (JSONException e) {
                 e.printStackTrace();
                 }
            TextView resp = (TextView) findViewById(R.id.response);
            if(stateInfo.trim().length() >0 )
             resp.setText(stateInfo);   
            else
                resp.setText("Sorry no match found");
        }
    }
}



그렇게 복잡한거 같지는 않죠?


먼저 onCreate()를 보죠.

activity_consume_jsonwebservice_app.xml 을 Layout 으로 사용한다고 세팅했습니다.

바로 위에서 본 xml 입니다.


그리고 버튼에 대한 객체를 만들고 이 버튼에 onClickListener를 달았습니다.

이 버튼을 클릭하면 ReadJSONFeed() 라는 클래스를 호출하네요. 그리고 excute() 라는 메소드에 아까 소개했던 원격 URL 을 pass 합니다.


그러면 ReadJSONFeed() 클래스를 보겠습니다.

이 클래스는 AsyncTask 를 상속합니다.

여기를 보시면 해당 API를 보실 수 있습니다.


UI thread를 쉽게 사용할 수 있게 해 준다고 하네요. background 로 실행되게 해서 그 결과를 UI thread에 publish 하는 군요. 따로 thread나 handler들을 작성하지 않아도 된다고 하네요.

이 AsyncTask는 짧은 기간 동안 수행할 작업에 사용됩니다. 만약 긴 기간동안 수행할 작업을 쓰레드로 사용하시려면 Executor, ThreadPoolExecutor and FutureTask 같은 java.util.concurrent pacakge 를 사용 하셔야 합니다.

이 asynchronous task(비동기 작업)은 Params, Progress and Result 이렇게 3가지가 있고 4개의 step들이 있습니다.

onPreExecute, doInBackground, onProgressUpdate and onPostExecute


그러면 계속 ReadJSONFeed 클래스를 보겠습니다.

첫번째 줄에는 위에 봤든 onPreExecute() 메소드가 있네요. 그 안에는 아무것도 없구요.

그냥 넘어가도 되겠습니다.


그 다음에는 또 위에서 봤던 doInBackground() 메소드가 나옵니다.

이 안에 어떤 로직을 넣으면 Background 로 돌아가게 됩니다.


우선 HTTPClient와 HttpPost, StringBuilder 를 초기화 했습니다.

HttpResponse를 초기화 하면서 httpclient의 execute메소드를 통해 httppost를 pass 해 줍니다.

여기 httppost에는 아까 버튼 눌렀을 때 pass 했던 url이 들어 있습니다.

그러면 response 안에 그 결과값 즉 json 데이터들이 담기겠죠.

그 다음에는 StatusLine을 초기화 하면서 이 response의 line을 get 합니다.

즉 json 내용을 get 하는거죠.

그리고 이 statusLine 의 statusCode를 statusCode라는 변수에 담습니다.

이 statusCode에는 성공했는지 실패 했는지에 대한 정보가 담기겠죠.

다음 if 문에서는 만약에 이 작업이 성공했으면 HttpEntity 를 생성해서 여기에 response의 Entity를 가져 옵니다. 그리고 그 내용을 InputStrean에 담고요.

다음에 BufferedReader를 이용해서 그 내용을 읽습니다.


Java에서 파일 내용을 읽어 들일 때 사용하는 InputStream과 BufferedReader가 여기서도 사용되네요.

그 다음에 line이라는 String을 만들어서 모든 줄을 이 line에 넣습니다.


여기까지가 doInBackground() 메소드가 하는 일입니다.

간단하네요. 원격에 있는 정보를 가져와서 이것을 사람이 읽을 수 있는 정보로 line이라는 String에 담은 겁니다.


그 다음에 실행되는 메소드는 onPostExecute() 입니다.

한번 볼까요?


state, stateInfo 라는 String을 만들었습니다. 주 이름과 그 주에 대한 정보를 담을 변수들 인 것 같습니다.

그리고 layout xml에서 만든 EditText에 대한 변수를 만들었습니다.


그리고 searchState라는 String에 이 stateName의 내용을 담을 겁니다.


다음에 나오는 내용들은 JSON을 파싱하는 로직 입니다.

아까 doInBackGround에서는 line이라는 String에 이 JSON 데이터를 그냥 담았죠.

이것을 파싱해서 사람이 알아볼 수 있도록 화면에 뿌려줄 겁니다.


onPostExecute(String result) 라고 위에 돼 있죠. 여기서는 pass 받은 string을 result 라는 변수이름으로 사용할 겁니다.


보시면 이 result 를 countriesArray라는 JSONArray 에 담습니다.


그 다음 for 문을 돌려서 아까 만들었던 변수들에 해당 내용들을 담습니다.

state에는 주 이름이 그리고 searchState에 있는 내용들은 Capital, Latitude, Longitute 별로 따로 사람이 읽기 좋게 편집해서 stateInfo에 담습니다.


그 다음에는 try catch 문 밖을 보시면 되는데요.


TextView 객체를 만들었죠.

이 text 뷰에 위에 만들었던 stateInfo를 setText() 해서 화면에 표시합니다.


그러면 아래와 같은 화면을 보실 수 있습니다.





여기서의 주요 개념은 AsyncTask 를 이용해서 쉽게 Background 작업을 하도록 한다는 것과

원격의 데이터를 받아 오는 방법 여기서는 HttpClient, StringBuilder, HttpPost, HttpResponse 등이 사용됐습니다. 그리고 이 데이터를 바이너리 형태로 돼 있을 텐데 이것을 InputStream과 BufferedReader를 이용해서 사람이 읽을 수 있는 문자로 파싱하는 방법을 배웠습니다.

그리고 그 파싱된 JSON 타입을 다시 key 값을 이용해서 value를 가져와서 필요에 따라 편집하는 방법도 배웠습니다.


아주 중요한 개념들이 많네요.


안드로이드 앱과 웹 서비스와의 네트워킹도 아주 쉽게 사용할 수 있도록 만들었군요.




반응형