サンプルアプリの基本部分
Open Weatherの仕様が理解できたところで、サンプルアプリの作成に入っていきましょう。
サンプルアプリの概要
今回作成するサンプルアプリは、起動すると、図3の左側の画面が表示されます。
上部に都市名のリストが表示されており、その都市名をタップすると、図3の右側のように天気情報が表示されるようになります。この時、非同期でOpen WeatherのWeb APIサービスにアクセスし、レスポンスデータとしての天気情報JSONを取得します。ここまでがワーカースレッドでの動作になります。その後、UIスレッドでJSONデータを解析し、表示させるようにします。
なお、都市リストとしては、筆者在住の近畿圏の都市としていますが、適宜変更していただいてもかまいません。
基本部分はスケルトンアプリを活用
そのようなアプリを作成するにあたり、まずは、非同期でWeb APIサービスにアクセスする処理コードとJSONデータの解析コードを記述する前段階までの部分を作成する必要があります。それらのソースコードをここに掲載するには、紙面が足りません。そこで、あらかじめスケルトンプロジェクトを用意しています。ダウンロードサンプル中の「AsyncJavaSample-Skeleton.zip」が該当します。解凍の上、Android Studioで読み込んで、一度エミュレータなどでアプリを実行してみてください。図3の左の画面が表示されます。ただし、リストをタップしても、何も動作しないように見えます。
このプロジェクトにコードを記述する形で、以降解説を行なっていきます。
その前に、まず既存のソースコードでポイントとなるところを説明しておきます。
Web APIアクセス用URL生成ロジック
MainActivityのフィールドにリスト1の定数があります。
private static final String WEATHERINFO_URL = "https://api.openweathermap.org/data/2.5/weather?lang=ja"; private static final String APP_ID = "";
このWEATHERINFO_URLがOpen WeatherのWeb APIサービスを利用するためのURLの基本部分です。また、APP_IDがAPIキーです。スケルトンコードでは、「""」と空文字となっていますが、ここに各自が取得したAPIキー文字列をコピー&ペーストしてください。
次に、リストがタップされた時の処理が記述されたListItemClickListenerクラスのonItemClick()メソッド内の処理に注目しましょう。これは、リスト2のようになっています。
public void onItemClick(…) { Map<String, String> item = _list.get(position); String q = item.get("q"); String url = WEATHERINFO_URL + "&q=" + q + "&appid=" + APP_ID; // (1) asyncExecute(); // (2) }
リスト1で説明した定数WEATHERINFO_URLとAPP_IDと、さらにタップされたリストデータをもとに都市名を表す文字列qを使って、実際にWeb APIサービスにアクセスするためのURLの完全形を生成しているのが、(1)です。
非同期処理用のコードもあらかじめ記述されている
さらに、リストをタップした際に非同期でWeb APIにアクセスするため、(2)の位置に非同期処理を開始するためのメソッドasyncExecute()を実行しています。このメソッドは、前回記述したasyncExecute()メソッドそのものです。さらに、このメソッド内の処理で実行するBackgroundTaskクラス、さらに、ワーカースレッドでの処理終了後にUIスレッドで処理を行うためのPostExecutorクラスも、そのままスケルトンプロジェクトに記述しています。確認してください。
なお、スケルトンプロジェクト内のそのBackgroundTaskクラスには、is2String()メソッドが追記されています。こちらはInputStreamオブジェクトを文字列に変換する定型処理が記述されたメソッドであり、のちに利用しますのであらかじめ記述してあります。
HTTPアクセスの許可
AndroidアプリがWebアクセスを行う場合、HTTPアクセスの許可として、リスト3の2行をAndroidManifest.xmlに記述しておく必要があります。こちらも、スケルトンプロジェクトにはあらかじめ記述しています。
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />