m_shige1979のときどきITブログ

プログラムの勉強をしながら学習したことや経験したことをぼそぼそと書いていきます

Github(変なおっさんの顔でるので気をつけてね)

https://github.com/mshige1979

androidでRSSを取得して一覧表示

前回はRSSを取得しただけ

パースとか便利なメソッドがあると思っていたけど軽く探しただけではなかった

参考

XMLをパース(解析)する | Tech Booster
これを見て必要な分を加工して取得する

画面

MainActivity用
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/listView"
        android:layout_centerHorizontal="true"
        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true" />

</RelativeLayout>
リストビューの明細用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="50dp"
    android:weightSum="1">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Large Text"
        android:id="@+id/textView" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Medium Text"
        android:id="@+id/textView2"
        android:layout_weight="0.08" />

</LinearLayout>

内部処理

MainActivity
package jp.mshige1979.app.sampleapp01;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

import android.os.Handler;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends Activity {

    private Handler handler;
    private final String RSS_URL = "http://m-shige1979.hatenablog.com/rss";
    private String RssText;
    private ListView listview;
    List<Item> list = new ArrayList<Item>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        handler = new Handler();

        setContentView(R.layout.activity_main);

        // 紐付け
        listview = (ListView)findViewById(R.id.listView);

        // ArrayAdapterへ設定
        RowItemAdapter rowAdapater = new RowItemAdapter(this, 0, list);

        // リストビューへ設定
        listview.setAdapter(rowAdapater);

        // リストをクリック
        listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                // リストビューの項目を取得
                ListView listview = (ListView) parent;
                Item item = (Item) listview.getItemAtPosition(position);

                // インテントのインスタンス生成
                Intent intent = new Intent(MainActivity.this, MainActivity2Activity.class);

                // 値をセットする
                intent.putExtra("title", item.getTitle());
                intent.putExtra("link", item.getLink());

                // 次画面のアクティビティ起動
                startActivity(intent);

            }
        });

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // メニューボタンを追加
        MenuItem item1 = menu.add("UPDATE");
        item1.setIcon(android.R.drawable.ic_menu_upload);

        item1.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {

                Thread thread1 = new Thread() {
                    @Override
                    public void run() {
                        try {
                            // URLよりRSSを取得
                            RssText = RssParse.getRss(MainActivity.this, RSS_URL);
                            list = RssParse.parse(RssText);

                            // handler
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    // 読み込み終了
                                    RowItemAdapter rowAdapater = new RowItemAdapter(MainActivity.this, 0, list);
                                    listview.setAdapter(rowAdapater);
                                    Toast.makeText(MainActivity.this, "読み込み終了", Toast.LENGTH_SHORT).show();
                                }
                            });

                        } catch (Exception e) {
                            Log.d("sample", e.getMessage());
                        }
                    }
                };
                thread1.start();

                return false;
            }
        });

        // 画面にメニューを表示
        item1.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


}

その他

Itemクラス
package jp.mshige1979.app.sampleapp01;


public class Item {
    private String title;
    private String pubDate;
    private String link;

    public String getTitle() {
        return title;
    }

    public String getLink() {
        return link;
    }

    public String getPubDate() {
        return pubDate;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setLink(String link) {
        this.link = link;
    }

    public void setPubDate(String pubDate) {
        this.pubDate = pubDate;
    }


}
パース、取得クラス
package jp.mshige1979.app.sampleapp01;

import android.content.Context;
import android.net.http.AndroidHttpClient;
import android.util.Log;
import android.util.Xml;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

/**
 * RSSを取得するクラス
 */
public class RssParse{
    public static String getRss(Context context, String url)
        throws IOException{

        StringBuilder sb = new StringBuilder();

        AndroidHttpClient client = AndroidHttpClient.newInstance("TEST");
        HttpGet get = new HttpGet(url);

        try{
            // リクエストを取得
            HttpResponse response = client.execute(get);

            BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            String line = null;
            while((line = br.readLine()) != null){
                sb.append(line);
            }

        }finally {
            // 閉じる
            client.close();
        }

        return sb.toString();

    }

    public static List<Item> parse(String xml){

        List<Item> list = new ArrayList<Item>();

        // XMLパーサを生成
        XmlPullParser xmlPullParser = Xml.newPullParser();

        // 入力データを設定
        try {
            xmlPullParser.setInput(new StringReader(xml));
        } catch (XmlPullParserException e) {
            Log.d("sample", "Error");
        }

        // 解析して記事のタイトルやリンク、日時を取得
        try {
            int eventType;
            String data = null;
            int itemFlg = -1;
            String fieldName = null;
            Item item = new Item();

            eventType = xmlPullParser.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {
                if(eventType == XmlPullParser.START_DOCUMENT) {
                    Log.d("sample", "Start document");

                } else if(eventType == XmlPullParser.END_DOCUMENT) {
                    Log.d("sample", "End document");

                } else if(eventType == XmlPullParser.START_TAG) {
                    data = xmlPullParser.getName();
                    Log.d("sample", "Start tag "+ data);
                    if(data.equals("item")){
                        itemFlg = 1;
                        item = new Item();
                    }
                    fieldName = data;

                } else if(eventType == XmlPullParser.END_TAG) {
                    data = xmlPullParser.getName();
                    Log.d("sample", "End tag "+ data);
                    if(data.equals("item")){
                        itemFlg = 0;
                        list.add(item);
                    }

                } else if(eventType == XmlPullParser.TEXT) {
                    data = xmlPullParser.getText();
                    Log.d("sample", "Text "+ data);

                    if(itemFlg == 1){
                        if(fieldName.equals("title")){
                            Log.d("sample", "title = "+ data);
                            item.setTitle(data);
                            fieldName = "";
                        }
                        if(fieldName.equals("pubDate")){
                            Log.d("sample", "pubDate = "+ data);
                            item.setPubDate(data);
                            fieldName = "";
                        }
                        if(fieldName.equals("link")){
                            Log.d("sample", "link = "+ data);
                            item.setLink(data);
                            fieldName = "";
                        }
                    }

                }
                eventType = xmlPullParser.next();
            }

        } catch (Exception e) {
            Log.d("sample", "Error");
        }

        return list;

    }
}
リストビュー用アダプター
package jp.mshige1979.app.sampleapp01;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.util.List;

public class RowItemAdapter extends ArrayAdapter<Item> {

    private LayoutInflater layoutinflater;

    // コンストラクタ
    public RowItemAdapter(Context context, int textViewResourceId, List<Item> objects){
        super(context, textViewResourceId, objects);
        layoutinflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // 指定行のデータを取得
        Item detail = (Item)getItem(position);

        // nullの場合のみ再作成
        if(null == convertView){
            convertView = layoutinflater.inflate(R.layout.row, null);
        }

        // 行のデータを項目へ設定
        TextView text1 = (TextView)convertView.findViewById(R.id.textView);
        text1.setText(detail.getTitle());

        TextView text2 = (TextView)convertView.findViewById(R.id.textView2);
        text2.setText(detail.getLink());

        // 返却
        return convertView;
    }

}

このへんは今までのパクリを流用

結果

f:id:m_shige1979:20150705120733p:plain

詳細画面を用意して、ページを表示するようにする

もう少し

画面

MainActivity2Activity
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="jp.mshige1979.app.sampleapp01.MainActivity2Activity">

    <WebView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/webView"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

内部処理

MainActivity2Activity
package jp.mshige1979.app.sampleapp01;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;
import android.widget.Toast;


public class MainActivity2Activity extends Activity {

    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_activity2);

        // webview
        webView = (WebView)findViewById(R.id.webView);

        // インテントを取得
        Intent intent = getIntent();
        // インテントに保存されたデータを取得
        String data = intent.getStringExtra("title");
        String link = intent.getStringExtra("link");
        setTitle(data);

        // URLを読み込み
        webView.loadUrl(link);

        // data
        Toast.makeText(MainActivity2Activity.this,data, Toast.LENGTH_SHORT).show();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main_activity2, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

結果

f:id:m_shige1979:20150705121224p:plain

所感

なんとなく非同期処理のやり方などが慣れてきたかもしれない…