API との json なやりとり

リハビリと材料精査を兼ねて Web な API とのやりとりなサンプルを書いて動作確認をしてみました。サンプルを書いて、というか以下なナニをパクッて作成。

ありがとうございます。

とりあえず

以下な要件を満たすべく手を入れてます。

  • 面倒なので onCreate でデータ取得
    • これは元ネタも同様な動作
  • HTTP 通信は UIThread とは別なソレでやりとり
  • 通信している間は ProgressDialog 出す
  • データはリクルートさん (hotpepper) より取得
  • HashMap に表示しない値も持ってみて一部のみ ListView にて表示

コードが以下となります。ちなみに JSONfunctions.java ですが、hotpepper が REST な API だとゆーことで HTTP メソドを GET した程度の修正しかしていません。おそらく汎用的に使えるものと思ってます。
Main.java が以下。

package com.pxr.tutorial.json;

import java.util.ArrayList;
import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.pxr.tutorial.xmltest.R;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

public class Main extends ListActivity {
    private JSONObject mJson;
    private ArrayList<HashMap<String, String>> mylist;
    private Handler mHandler = new Handler();
    private ProgressDialog mProgressDialog;
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.listplaceholder);
        
        mylist = new ArrayList<HashMap<String, String>>();
        mProgressDialog = new ProgressDialog(this);
        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        mProgressDialog.setMessage("Please wait ...");
        mProgressDialog.setCancelable(true);
        mProgressDialog.show();

        new Thread(new Runnable() {
            @Override
            public void run() {
                //mJson = JSONfunctions.getJSONfromURL("http://api.geonames.org/earthquakesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&username=demo");
                mJson = JSONfunctions.getJSONfromURL("http://webservice.recruit.co.jp/hotpepper/gourmet/v1/?key=40[API-KEY]&lat=34.67&lng=135.52&range=5&order=4&format=json");
                mHandler.post(new ListSetting());
            }          
        }).start();          
    }

    private class ListSetting implements Runnable {
        @Override
        public void run() {
            try{
                
                JSONObject result = mJson.getJSONObject("results");
                JSONArray  earthquakes = result.getJSONArray("shop");
                
                for(int i=0;i<earthquakes.length();i++){                        
                    HashMap<String, String> map = new HashMap<String, String>();    
                    JSONObject e = earthquakes.getJSONObject(i);
                    
                    map.put("id",  String.valueOf(i));
                    map.put("iid", e.getString("id"));
                    map.put("name", e.getString("name"));
                    map.put("lat", e.getString("lat"));
                    map.put("lng", e.getString("lng"));
                    mylist.add(map);            
                }        
            }catch(JSONException e)        {
                Log.e("log_tag", "Error parsing data "+e.toString());
            }
            
            ListAdapter adapter = new SimpleAdapter(Main.this, mylist , R.layout.main, 
                    new String[] { "name", "iid" }, 
                    new int[] { R.id.item_title, R.id.item_subtitle });
            
            setListAdapter(adapter);
            
            final ListView lv = getListView();
            lv.setTextFilterEnabled(true);    
            lv.setOnItemClickListener(new OnItemClickListener() {
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                
                    @SuppressWarnings("unchecked")
                    HashMap<String, String> o = (HashMap<String, String>) lv.getItemAtPosition(position);                    
                    Toast.makeText(Main.this, "ID '" + o.get("name") + "' was clicked.", Toast.LENGTH_SHORT).show(); 

                }
            });        
            mProgressDialog.dismiss();
        }
    }
}

最初、run の中で ProgressDialog#show とか呼び出してたりして駄目さ加減満点。JSONObject をバラすあたりも慣用的なヤり方を完全に忘れてて困りました。しかし JSON は取り回しが楽で良いですねぇ。早く Rails3 で json 戻す方法を調べたいものです。
そして以下が JSONfunction.java です。

package com.pxr.tutorial.json;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class JSONfunctions {

    public static JSONObject getJSONfromURL(String url){
        InputStream is = null;
        String result = "";
        JSONObject jArray = null;
        
        //http post
        try{
                HttpClient httpclient = new DefaultHttpClient();
                HttpGet httpget = new HttpGet(url);
                HttpResponse response = httpclient.execute(httpget);
                HttpEntity entity = response.getEntity();
                is = entity.getContent();

        }catch(Exception e){
                Log.e("log_tag", "Error in http connection "+e.toString());
        }

        //convert response to string
        try{
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
                }
                is.close();
                result=sb.toString();
        }catch(Exception e){
                Log.e("log_tag", "Error converting result "+e.toString());
        }
        
        try{
            
            jArray = new JSONObject(result);            
        }catch(JSONException e){
                Log.e("log_tag", "Error parsing data "+e.toString());
        }
    
        return jArray;
    }
}

余計な import があったりしますが、ご容赦下さい。タイミング的にアレですが、勉強会の材料にもなるな、と。