1. 自由研究に戻る
  2. Menu表示

森林公園、やまぶき
2012.04.21 東高根森林公園

Android http データ通信、XmlPullParserを使う

httpに関するトレーニングです(ICS4.0.3使用)。

HttpURLConnectionでWebデータ読み込みの確認

手順
下記参考サイトを参照して確認を進めます。
(1)androidでマルチスレッド(バックグランド処理)
 webサイトからダウンロードする場合など所要時間が長くなる場合は、マルチスレッドにしてダウンロードします。マルチスレッドに関しては2通り紹介されてます(Androidで提供されているAsyncTaskを使う方法と、Java標準Threadクラスを使う方法)。
(2)HTTP通信でダウンロードする
 HTTP通信でバイト列(テキスト, 画像データ等)をダウンロードする, HttpURLConnectionクラスの使用例が紹介されています。
 紹介されているandroidのバージョンが違うのでしょう、android4.0.3でこのままではエラーになります。android.os.NetworkOnMainThreadExceptionというエラーです。http通信はmain threadではエラーになるということですので、(1)のサイトが必要になります。
(3)世界を目指せ androidアプリ開発入門 第9回 AndroidでHTTP通信を行う
  AndroidManifestへ下記の記入もお忘れなく。
 <uses-permission android:name="android.permission.INTERNET"> </uses-permission>
 org.apache.httpを使って,HTTPプロトコルのGET, POSTメソッドの実装方法が紹介されています。
(4)Androidメモ HTTP通信
 このサイトは上の(1)(2)(3)を満足してそうです。
(5)Androidメモ XML解析
(6)android XmlPullPerser XML解析
(7)XMLをパース(解析)する
(8)softbank スマートフォンサービス開発支援サイト
(9)【Android】 ライブドア Weather Hacksを使ってみる
 天気予報を読み込んでいますの、確認してみます。

webサイトから読み込み、表示してみます。
webから読み込み
Fig.1 webから読み込み

//////////////////////////////////////////////////////////
///////////プログラム@ src javaファイル///////////////////////////////////
package httpGet01.app;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;

public class HttpGet01Activity extends Activity implements OnClickListener{
    Handler  mHandler   = new Handler();        //Handlerのインスタンス生成    
    TextView mTextView;  
    String src = new String();
    byte[] line = new byte[1024];
    int size;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //TextView取得  
        mTextView = (TextView)findViewById(R.id.ThreadSample1);  
        //TextViewタップ時にonClick実行  
        findViewById(R.id.ThreadSample1).setOnClickListener(this);
    }    
 //   @Override 
    public void onClick(View arg0) {  
        // スレッド起動  
        (new Thread(new Runnable() {  
         //   @Override 
            public void run() {  
                // 通常バックグランドをここに記述します
               HttpURLConnection http = null;
               InputStream in = null;
               TextView web = (TextView)findViewById(R.id.textview);
               try {
                   // URLにHTTP接続
                   URL url = new URL("http://weather.livedoor.com/forecast/rss/8/54.xml");
                   http = (HttpURLConnection)url.openConnection();
                   http.setRequestMethod("GET");
                   http.connect();
                   // データを取得
                   in = http.getInputStream();
                   // HTMLソースを読み出す
                while(true) {
                       size = in.read(line);
                       if(size <= 0)
                           break;
                       src += new String(line);
                   }
               } catch(Exception e) {
                   src=e.toString();
               } finally {
                   try {
                       if(http != null)
                           http.disconnect();
                       if(in != null
                           in.close();
                   } catch (Exception e) {src=e.toString();}
               }                  
                /** Handlerのpostメソッドを使ってUIスレッドに処理をdispatchします  */ 
                mHandler.post(new Runnable() {  
                   // @Override 
                    public void run() {  
                        //取得したイメージをImageViewに設定  
                        mTextView.setText(src);                     
                    }
                });    
            }            
        })).start();  
    }    
 }
//////////////////////////////////////////////////////////
/////////// res xmlファイル///////////////////////////////////
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <Button
        android:id="@+id/ThreadSample1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />    
    <TextView
        android:id="@+id/textview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="hit button key to start http" />    
</LinearLayout>

XmlPullParserでデータ抽出の確認

webからxmlファイルを読み込むのはHttpURLConnectionの仕事で、任意のタグからデータを抽出する作業がXmlPullParserの仕事です。 XMLパーサ
Fig.2 XmlPullParserでデータ抽出したデータ
(Fig.1の内容とは関係ありません、下記xmlファイルをパースしたデータです)
抽出は<title>,<telop>,<description>タグ毎に抽出しています。

/////////抽出元のxmlファイル//////////
 <?xml version="1.0" encoding="UTF-8" ?> 
- <lwws version="livedoor Weather Web Service 1.0">
  <author>livedoor Weather Team.</author
  <location area="関東" pref="茨城県" city="水戸" /> 
  <title>茨城県 水戸 - 明日の天気</title
  <link>http://weather.livedoor.com/area/8/54.html?v=1</link
  <forecastday>tomorrow</forecastday
  <day>Tuesday</day
  <forecastdate>Tue, 01 May 2012 00:00:00 +0900</forecastdate
  <publictime>Mon, 30 Apr 2012 17:00:00 +0900</publictime
  <telop>曇り</telop
  <description>日本のはるか東に中心を持つ高気圧が東日本に張り出しています。一方、東シナ海には前線が停滞し、九州の南に低気圧が発生して東に進んでいます。現在、関東地...<br />[PR]<a href="http://weather.livedoor.com/indexes/cloth_wash/?r=rest_pr">きょうは洗濯できるかな?</a></description
- <image>
  <title>曇り</title
//////////////////////////////////////////////////////////
/////////// srcファイル、プログラム@にparserを追加///////
先述の参考サイト(9)の確認になってしまいました。
http://weather.livedoor.com/forecast/webservice/rest/v1?city=54&day=tomorrowからxmlファイルをダウンロードし、parserに渡します。
package httpGet01.app;

import java.io.InputStream;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.StringTokenizer;
import org.xmlpull.v1.XmlPullParser;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Xml;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;

public class HttpGet01Activity extends Activity implements OnClickListener{
    Handler  mHandler   = new Handler();        //Handlerのインスタンス生成    
    TextView mTextView;  
    String src = new String();
    byte[] line = new byte[1024];
    int size;    
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //TextView取得  
        mTextView = (TextView)findViewById(R.id.ThreadSample1);  
        //TextViewタップ時にonClick実行  
        findViewById(R.id.ThreadSample1).setOnClickListener(this);
    }    
 //   @Override 
    public void onClick(View arg0) {  
        // スレッド起動  
        (new Thread(new Runnable() {  
         //   @Override 
            public void run() {  
                // 通常バックグランドをここに記述します
                int intEventType = -1;
                   String strParserName = "";               
                   StringTokenizer  objToken = null;
                  String strGettingTitle = "";
                String strGettingTelop = "";
                String strGettingDiscription = "";
                
                HttpURLConnection http = null;
                InputStream in = null;
                TextView web = (TextView)findViewById(R.id.textview);
                try {
                    // URLにHTTP接続
                    URL url = new URL("http://weather.livedoor.com/forecast/rss/8/54.xml");
                    http = (HttpURLConnection)url.openConnection();
                    http.setRequestMethod("GET");
                    http.connect();
                    // データを取得
                    in = http.getInputStream();
                    // HTMLソースを読み出す
                    while(true) {
                        size = in.read(line);
                        if(size <= 0)
                            break;
                        src += new String(line);
                    }
                } catch(Exception e) {
                    src=e.toString();
                } finally {
                    try {
                        if(http != null)
                            http.disconnect();
                        if(in != null
                            in.close();
                    } catch (Exception e) {src=e.toString();}
                }                  
                /** Handlerのpostメソッドを使ってUIスレッドに処理をdispatchします  */ 
                mHandler.post(new Runnable() {  
                   // @Override 
                    public void run() {  
                        //取得したイメージをImageViewに設定  
                        mTextView.setText(src);                     
                    }
                });    
                try{
                //取得XMLのURIを設定--ここからをプログラム@に追加
                //uri += "?city=" + id + "&day=tomorrow";
                    URL uri = new URL("http://weather.livedoor.com/forecast/webservice/rest/v1?city=54&day=tomorrow");
                   //XML取得
                    http = (HttpURLConnection)uri.openConnection();
                    http.setRequestMethod("GET");
                    http.connect();
                    // データを取得
                    in = http.getInputStream();
                    //XMLから情報を抽出
                    XmlPullParser parser = Xml.newPullParser();
                    parser.setInput(in,"UTF-8");                    
                    while(intEventType != XmlPullParser.END_DOCUMENT){
                        switch (intEventType){
                           case XmlPullParser.START_TAG: 
                            strParserName = parser.getName() ;
                            if(strParserName.equals("title") && strGettingTitle.equals("")){
                                   strGettingTitle = parser.nextText();
                               }
                               if(strParserName.equals("telop") && strGettingTelop.equals("")){
                                   strGettingTelop = parser.nextText();
                               }
                               if(strParserName.equals("description") && strGettingDiscription.equals("")){
                                   strGettingDiscription = parser.nextText();
                               }
                        }        
                        if(!strParserName.equals("") && !strGettingTelop.equals("") && !strGettingDiscription.equals("")){ 
                            break;
                        } 
                        intEventType = parser.next();
                    }
                    //取得データを画面に表示 
                    src=strGettingTitle + "\n" + strGettingTelop + "\n" + strGettingDiscription;                    
                }catch(Exception e){                    
                    src=e.toString(); 
                }finally{
                }              
                mHandler.post(new Runnable() {  
                // @Override 
                    public void run() {  
                     //取得したイメージをImageViewに設定  
                        mTextView.setText(src);                     
                    }
                });  
            }
        })).start();  
    }    
}