しかし、XMLやJSONをパースするような単調な処理は出来るだけ無くしたいので、
Spring AndroidとSimple(xmlシリアルフレームワーク)を使用してXMLデータを取得し、
アプリに表示させてみた。
今回はイベント開催支援ツールのATNDのAPIを使用してAndroid系イベントを取得して
イベントタイトルとイベント日時をアプリにリスト表示してみる。
実際に使用するAPI→http://api.atnd.org/events/?keyword=android&format=xml
サンプルプロジェクトのダウンロードリンクは記事の最後。
まず前エントリーを参考にMavenプロジェクトからAndroidプロジェクトを作成。
pom.xmlを追記
- <dependency>
- <groupId>org.simpleframework</groupId>
- <artifactId>simple-xml</artifactId>
- <version>2.6.1</version>
- <exclusions>
- <exclusion>
- <artifactId>stax</artifactId>
- <groupId>stax</groupId>
- </exclusion>
- <exclusion>
- <artifactId>stax-api</artifactId>
- <groupId>stax</groupId>
- </exclusion>
- <exclusion>
- <artifactId>xpp3</artifactId>
- <groupId>xpp3</groupId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.springframework.android</groupId>
- <artifactId>spring-android-rest-template</artifactId>
- <version>1.0.0.M4</version>
- </dependency>
- <repositories>
- <repository>
- <id>org.springframework.maven.milestone</id>
- <name>Spring Maven Milestone Repository</name>
- <url>http://maven.springframework.org/milestone</url>
- <snapshots><enabled>false</enabled></snapshots>
- </repository>
- </repositories>
次にXMLデータをマッピングさせるオブジェクトを作成する。
要素には@Element、属性には@Attributeをつける。
@Element、@Attributeのnameは要素名(属性名)と変数名が同じであれば省略可能。
XMLのすべての要素をオブジェクトにマッピングしない場合は@Rootアノテーションにstrict = false
をつける必要がある。
Event.java
- package jp.u1aryz.products.atndsearch;
- import org.simpleframework.xml.Element;
- import org.simpleframework.xml.Root;
- @Root(name = "event", strict = false)
- public class Event {
- @Element
- private String title;
- @Element(name = "started_at")
- private String eventDate;
- public void setTitle(String title) {
- this.title = title;
- }
- public String getTitle() {
- return title;
- }
- public void setEventDate(String eventDate) {
- this.eventDate = eventDate;
- }
- public String getEventDate() {
- return eventDate;
- }
- }
リストの場合は@ElementListアノテーションを使う。
EventList.java
- package jp.u1aryz.products.atndsearch;
- import java.util.List;
- import org.simpleframework.xml.ElementList;
- import org.simpleframework.xml.Root;
- @Root(name = "events", strict = false)
- public class EventList {
- @ElementList
- private List<Event> events;
- public void setEvents(List<Event> events) {
- this.events = events;
- }
- public List<Event> getEvents() {
- return events;
- }
- }
そしてXMLデータからオブジェクトにマッピングさせる処理を作成する。
HTTP通信は通常、UIスレッドとは別のスレッドで行うため、今回のポイントとなる処理も
doInBackground内に入れる。
GetAndroidEventActivity.java
- package jp.u1aryz.products.atndsearch;
- import java.util.ArrayList;
- import java.util.List;
- import org.springframework.http.HttpEntity;
- import org.springframework.http.HttpHeaders;
- import org.springframework.http.HttpMethod;
- import org.springframework.http.MediaType;
- import org.springframework.http.ResponseEntity;
- import org.springframework.web.client.RestTemplate;
- import android.app.ListActivity;
- import android.app.ProgressDialog;
- import android.os.AsyncTask;
- import android.os.Bundle;
- import android.util.Log;
- public class GetAndroidEventActivity extends ListActivity {
- private static String TAG = GetAndroidEventActivity.class.getSimpleName();
- private ProgressDialog progressDialog;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
- @Override
- protected void onStart() {
- super.onStart();
- // ATND APIの呼び出しを非同期で行う
- new GetEventTask().execute();
- }
- private void refreshEvents(List<Event> events) {
- if (events != null) {
- EventListAdapter adapter = new EventListAdapter(this, events);
- setListAdapter(adapter);
- }
- }
- public void showProgressDialog() {
- if (progressDialog == null) {
- progressDialog = new ProgressDialog(this);
- progressDialog.setIndeterminate(true);
- }
- progressDialog.setMessage("Loading. Please wait...");
- progressDialog.show();
- }
- public void dismissProgressDialog() {
- if (progressDialog != null) {
- progressDialog.dismiss();
- }
- }
- private class GetEventTask extends AsyncTask<Void, Void, List<Event>> {
- @Override
- protected void onPreExecute() {
- // プログレスバーを表示
- showProgressDialog();
- }
- @Override
- protected List<Event> doInBackground(Void... params) {
- try {
- // Android関連のイベントを検索するURL
- String url =
- "http://api.atnd.org/events/?keyword=android&format=xml";
- // Acceptヘッダに"application/xml"をセット
- HttpHeaders requestHeaders = new HttpHeaders();
- List<MediaType> acceptableMediaTypes =
- new ArrayList<MediaType>();
- acceptableMediaTypes.add(MediaType.APPLICATION_XML);
- requestHeaders.setAccept(acceptableMediaTypes);
- HttpEntity<?> requestEntity =
- new HttpEntity<Object>(requestHeaders);
- RestTemplate restTemplate = new RestTemplate();
- // HTTPのGETリクエストを実行(マッピングさせるクラスを指定する)
- ResponseEntity<EventList> responseEntity =
- restTemplate.exchange(url,
- HttpMethod.GET,
- requestEntity,
- EventList.class);
- // イベントリストを取得
- EventList eventList = responseEntity.getBody();
- return eventList.getEvents();
- } catch (Exception e) {
- Log.e(TAG, e.getMessage(), e);
- }
- return null;
- }
- @Override
- protected void onPostExecute(List<Event> result) {
- // プログレスバーを非表示
- dismissProgressDialog();
- // 結果を返す
- refreshEvents(result);
- }
- }
- }
最後にViewに取得したデータをセットするAdapterの作成。
特別な処理はしていないので、通常のAndroidの知識で理解出来ると思う。
EventListAdapter.java
- package jp.u1aryz.products.atndsearch;
- import java.util.List;
- import android.content.Context;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.ArrayAdapter;
- import android.widget.TextView;
- public class EventListAdapter extends ArrayAdapter<Event> {
- private LayoutInflater mInflater;
- public EventListAdapter(Context context, List<Event> objects) {
- super(context, 0, objects);
- mInflater = LayoutInflater.from(context);
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- ViewHolder holder;
- if (convertView == null) {
- convertView =
- mInflater.inflate(android.R.layout.simple_list_item_2, null);
- holder = new ViewHolder();
- holder.title =
- (TextView) convertView.findViewById(android.R.id.text1);
- holder.eventDate =
- (TextView) convertView.findViewById(android.R.id.text2);
- convertView.setTag(holder);
- } else {
- holder = (ViewHolder) convertView.getTag();
- }
- Event event = getItem(position);
- holder.title.setText(event.getTitle());
- holder.eventDate.setText(event.getEventDate());
- return convertView;
- }
- }
- class ViewHolder {
- TextView title;
- TextView eventDate;
- }
<uses-permission android:name="android.permission.INTERNET" />を忘れなければ
下記のようにイベントを取得出来る。
日時のフォーマットが見づらいけど。。。
これで単調なパース処理とおさらば〜
時間があればJSONバージョンもやるかも!?
ダウンロードはこちらから