Yahoo気象情報APIでJSONデータを取得する
ネットワーク通信 - mixi-inc/AndroidTraining
の実習と課題3でYoutubeのAPIが使えないので他のAPIを使用することにした。
APIはこちら
気象情報API - Yahoo!デベロッパーネットワーク
- 取得したJSONデータ
{ "ResultInfo":{ "Count":1, "Total":1, "Start":1, "Status":200, "Latency":0.003336, "Description":"", "Copyright":"(C) Yahoo Japan Corporation." }, "Feature":[ { "Id":"201701130415_xxx.21671_yy.692798", "Name":"地点(xxx.21671,yy.692798)の2017年01月13日 04時15分から60分間の天気情報", "Geometry":{ "Type":"point", "Coordinates":"xxx.21671,yy.692798" }, "Property":{ "WeatherAreaCode":5510, "WeatherList":{ "Weather":[ { "Type":"observation", "Date":"201701130415", "Rainfall":0.00 },{ "Type":"forecast", "Date":"201701130425", "Rainfall":4.13 },{ "Type":"forecast", "Date":"201701130435", "Rainfall":0.00 },{ "Type":"forecast", "Date":"201701130445", "Rainfall":3.38 },{ "Type":"forecast", "Date":"201701130455", "Rainfall":0.00 },{ "Type":"forecast", "Date":"201701130505", "Rainfall":0.85 },{ "Type":"forecast", "Date":"201701130515", "Rainfall":0.00 } ] } } } ] }
- AsyncTaskLoaderをextendしたローダ
アプリケーションIDの箇所はXXXでマスクしてある
package jp.mixi.assignment.network.networkAssignment; import android.content.Context; import android.support.v4.content.AsyncTaskLoader; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class MyAsyncTaskLoader extends AsyncTaskLoader<JSONObject> { private JSONObject cache; public MyAsyncTaskLoader (Context context) { super(context); } //非同期処理の中身 @Override public JSONObject loadInBackground() { JSONObject json = null; try{ URL url = new URL("http://weather.olp.yahooapis.jp/v1/place?coordinates=xxx.2167111,yy.69279806&output=json&appid=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); HttpURLConnection con = null; try { con = (HttpURLConnection)url.openConnection(); con.connect(); InputStream is = con.getInputStream(); StringBuilder src = new StringBuilder(); while(true) { byte[] line = new byte[1024]; int size = is.read(line); if (size <= 0) break; src.append(new String(line, "utf-8")); } json = new JSONObject(src.toString()); } catch (IOException | JSONException e) { e.printStackTrace(); } finally { con.disconnect(); } } catch (MalformedURLException e) { e.printStackTrace(); } return json; } @Override public void deliverResult(JSONObject data) { if(isReset()) { if(cache != null) { cache = null; //キャッシュデータがある場合は削除してメモリから破棄可能にする } return; } //得られたデータをキャッシュする cache = data; //ローダが開始されている場合、親にデータが得られたことを通知する if(isStarted()) { super.deliverResult(data); } } @Override protected void onStartLoading() { //キャッシュがある場合はそちらを返す if(cache != null) { deliverResult(cache); return; } //データソースに変更があったり、キャッシュデータが無い場合はloadInBackground()に行くようにする if(takeContentChanged() || cache == null) { forceLoad(); } } //ローダの非同期処理がストップするときのコールバック @Override protected void onStopLoading() { cancelLoad(); super.onStopLoading(); } //ローダがリセットされるときのコールバック @Override protected void onReset() { onStopLoading(); super.onReset(); } }
- Activity
ローダを呼び出し、結果(JSONObject)をパースする。
ListViewに貼り付けても良いのだが、取り敢えずTextViewにそのままべたっと貼った。
package jp.mixi.assignment.network.networkAssignment; import android.os.Build; import android.os.Bundle; import android.os.StrictMode; import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.view.Menu; import android.widget.TextView; import android.widget.Toast; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; public class MainActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<JSONObject> { @Override protected void onCreate(Bundle savedInstanceState) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { StrictMode.setThreadPolicy( new StrictMode.ThreadPolicy.Builder() .detectNetwork() .penaltyDeath() .build()); } super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LoaderManager manager = getSupportLoaderManager(); Bundle argsForLoader = new Bundle(); manager.initLoader(0, argsForLoader, MainActivity.this); } @Override public Loader<JSONObject> onCreateLoader(int id, Bundle args) { switch (id) { case 0: return new MyAsyncTaskLoader(this); default: return null; } } @Override public void onLoadFinished(Loader<JSONObject> loader, JSONObject result) { String name = ""; String weather = ""; String[] type = new String[7]; String[] date = new String[7]; String[] rain = new String[7]; try { JSONArray feature = result.getJSONArray("Feature"); name = feature.getJSONObject(0).getString("Name"); JSONArray jWeather = feature.getJSONObject(0).getJSONObject("Property").getJSONObject("WeatherList").getJSONArray("Weather"); for (int i=0; i<7; i++) { type[i] = jWeather.getJSONObject(i).getString("Type"); date[i] = jWeather.getJSONObject(i).getString("Date"); rain[i] = jWeather.getJSONObject(i).getString("Rainfall"); } } catch (JSONException e) { e.printStackTrace(); } for (int i=0; i<7; i++) { date[i] = date[i].substring(0, 4) + "年" + date[i].substring(4, 6) + "月" + date[i].substring(6, 8) + "日" + date[i].substring(8, 10) + "時" + date[i].substring(10, 12) + "分"; rain[i] += "mm/h"; weather += ((0 == i) ? "観測" : "予報") + "\n" + date[i] + rain[i] + "\n"; } Toast.makeText(this, name, Toast.LENGTH_LONG).show(); TextView tv = (TextView)findViewById(R.id.title); tv.setText(weather); } @Override public void onLoaderReset(Loader<JSONObject> loader) {} @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }