DefaultHttpClient なサンプル

書いてみた。んですが、org.apache.http ってライブラリ追加しなくても良いのかorz
サンプル作って何も考えずに実機接続して実行したら普通に動作した。以前ご丁寧にライブラリを落っことしてローカルに置いたりなんかしてたんですが、意味が無かった模様。
サンプルの実装以下なんですが、ログなバッファが溢れてるみたいで出力が確認できてません。

package jp.shuri.android.dhchowto;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class DhcHowtoActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String url = "http://api.doko.jp/v1/searchPOI.do?key=******&format=xml&pagenum=1&pagesize=3&keyword=%83R%83%93%83r%83j&lat_jgd=35.6686&lon_jgd=139.7593&order=2";
				HttpAccess(url);
			}
        	
        });
    }
    
    private void HttpAccess(String url) {
    	DefaultHttpClient client = new DefaultHttpClient();
    	HttpGet get = new HttpGet(url);
    	client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(3, false));	
    	HttpEntity entity = null;
    	HttpResponse response;
    	try {
    		response = client.execute(get);
    		entity = response.getEntity();

    		Header[] hs = response.getAllHeaders();
    		Log.d("DhcHowtoActivity", "----------------------------------------");
    		Log.d("DhcHowtoActivity", response.getStatusLine().toString());
    		if (entity != null) {
    			Log.d("DhcHowtoActivity", "Response content length: " + entity.getContentLength());
    			Log.d("DhcHowtoActivity", "Chunked?: " + entity.isChunked());
    		}
    		Log.d("DhcHowtoActivity", "----------------------------------------");
    		for (Header h : hs) {
    			Log.d("DhcHowtoActivity", "name: " + h.getName() + ", value: " + h.getValue());
    		}
    		Log.d("DhcHowtoActivity", "----------------------------------------");

    		BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()), 8*1024);
    		String line;
    		while ((line = br.readLine()) != null) {
    			Log.d("DhcHowtoActivity", line);
    		}

    	} catch (ClientProtocolException ex) {
    		Log.e("DhcHowtoActivity", "error" + ex);
    	} catch (IOException ex) {
    		Log.e("DhcHowtoActivity", "I/O error" + ex);
    	} finally {
    		try {
    			entity.consumeContent();
    		} catch (IOException ex) {
    			Log.e("DhcHowtoActivity", "I/O error" + ex);
    		}
    	}
    	client.getConnectionManager().shutdown();
	}
}

ログが出力されていない件についてはスルーとして、レスポンスな XML をパースしてみる事に。

XMLPullParser

によると

  1. XmlPullParserインスタンスを取得
  2. XmlPullParserにXMLファイルが読み込まれているInputStreamを設定
  3. パース

という順で処理する模様。setInput で設定する InputStream は HttpEntity#getContent メソドで取得できるソレを指定して差し上げれば良いはず。
という事で以下な実装をでっち上げてみたんですが、てっぺんのタグしか読めてない模様。

/*
    		BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()), 8*1024);
    		String line;
    		while ((line = br.readLine()) != null) {
    			Log.d("DhcHowtoActivity", line);
    		}
*/
    		try {
    			xmlPullParser.setInput(entity.getContent(), "UTF-8");
    			for(int e = xmlPullParser.getEventType(); e != XmlPullParser.END_DOCUMENT; e = xmlPullParser.next()){
    				if(e == XmlPullParser.START_TAG) { 
    					Log.d("DhcHowtoActivity", "tag = " + xmlPullParser.getName());
    				}
    				if(e == XmlPullParser.START_TAG && xmlPullParser.getName().equals("name")) {
    					Log.d("DhcHowtoActivity", "name = " + xmlPullParser.getText());
    				}
    			}
    		} catch (Exception e) {
    			Log.e("DhcHowtoActivity", "XMLPullParser error " + e);
    		}

そもそも HttpEntity#getContent() の動作が微妙なのかそれ以前の処理がダメなのか。。
ログに出力されていない、のはログのバッファあふれではなくて、単純に読めてなかったって事らしい。これは困りました。
setInput メソドの呼び出しを以下にしても当たり前ですが動作は変わらず。

    			xmlPullParser.setInput(new InputStreamReader(entity.getContent()));

で、リビジョン戻して試験してみたらバッファ云々じゃなくてそもそも検索結果が 0 件である事が判明orz

原因

URL エンコードされた文字列でアクセスしたら駄目な模様。最初、デフォな文字コードが MacRoman になってて日本語入力できなかった (これは理由にならん) のと URL エンコードはしないと駄目なんかな、って思っていたんですが、そのまんまで良かった模様です。
マトモなレスポンスが戻ってきているようなので XMLPullParser 使ってみる。

パースの結果

実装が微妙な事が判明。START_TAG の時に getName なタグが目的のタグだった場合は次を読まないと駄目だな。無理矢理気味ですが以下かな。

    		try {
    			xmlPullParser.setInput(new InputStreamReader(entity.getContent()));
    			for(int e = xmlPullParser.getEventType(); e != XmlPullParser.END_DOCUMENT; e = xmlPullParser.next()){
    				if(e == XmlPullParser.START_TAG && xmlPullParser.getName().equals("name")) {
    					e = xmlPullParser.next();
    					if(e == XmlPullParser.TEXT) { 
    						Log.d("DhcHowtoActivity", "name = " + xmlPullParser.getText());
    					}
    				}
    			}
    		} catch (Exception e) {
    			Log.e("DhcHowtoActivity", "XMLPullParser error " + e);
    		}

ログ出力は文字化けしてるんですが、問題ありかなぁ。Activity に出力できないものか。

とりあえず

一旦ログ出力。
ちなみにサンプルコードはヤッツケなナニですので、ちゃんとリファクタリングしないと駄目です。

とりあえず

一旦ログ出力。
ちなみにサンプルコードはヤッツケなナニですので、ちゃんとリファクタリングしないと駄目です。

TextView に

出してみました。

    	TextView tv = (TextView)findViewById(R.id.textview);
    	StringBuffer sb = new StringBuffer();
// 中略
    				if(e == XmlPullParser.START_TAG && xmlPullParser.getName().equals("name")) {
    					e = xmlPullParser.next();
    					if(e == XmlPullParser.TEXT) { 
    						String tmp = xmlPullParser.getText();
    						sb.append(tmp);
    						sb.append("\n");
    						tv.setText(sb);
    						Log.d("DhcHowtoActivity", "name = " + tmp);
    					}
    				}

改行されませんでしたが、文字化けはしない形で出力はされておりますな。本当は住所なソレを geocode なナニで変換されたソレを確認できれば良いのでしょうが、それは別途で良いかな。
今日は早めに寝ます。