#はじめに
こんにちは。某学校でプログラミング等の勉強中のサーバーサイドのプログラマーのワタタクです。
今回もAndroid開発していきましょう。
今回はAndroidで外部のネットワークと接続してデータを取得してみたいと思います。
#対象者
- Javaがそこそこ書ける人。
- Android開発においてもそこそこできる人。
#Webアクセス概要
-
アプリ内で http アクセスのソースコードを記述する。 → レスポンスの内容は JSON か XML が多い。
-
画面内で画面部品 WebView を使う。 → レスポンスの内容は原則 HTML。
#非同期処理
Webアクセスのように、処理に時間がかかるもの、予期せぬエラーが起こりそうなもおは、 メイン処理とは別のスレッドで処理(非同期処理)を行う。
#AsyncTask
Androidの非同期処理のうち、UIスレッドとやりとりがある場合は、AsyucTaskクラスを使うと便利。
##1.AsyncTaskの使い方 -
Asynuc Task を継承したクラスを作成する。
→ アクティビティクラスの private メンバクラスとして作ると便利。 -
メソッド doInBackground() 内に非同期で行いたい処理を記述する。
→ このメソッドは Asyuc Task の抽象メソッドなので、必ずオーバーライドする必要がある。 -
アクティビティでこのクラスを newして、execute() メソッドを実行する
private class クラス名 extends AsyucTask< ... > {
...
@Override
public String doInBackground( String ... params ) {
// ここに非同期処理を記述
}
}
その後
クラス名 変数名 = new クラス名();
変数名.execute( ... );
*メソッドの引数にある「...」( ドット 3 コ ) は可変長引数を表す。
→ メソッド内での引数の扱いは配列となる。
##2.その他のメソッド
AsyucTask には doInBackground() 以外にも以下のメソッドがある。
これらのメソッドは UI スレッド上で実行されるので、画面部品の操作が可能。
- onPostExecute() : doInBackground() の終了後に実行される。
- onPreExecute() : doInBackground() の開始前に実行される。
- onProgressUpdate() : doInBackground() の中で publishProgress() を呼び出した時に実行される。
さらに、アクティビティから cancel() が呼び出されると、doInBackground() 終了後、 onCancelled() が実行される。
##3.ジェネリクス
AsyucTask の子クラスを作るとき、ジェネリクスに 3 個の型を書く必要がある。
→型指定が不要なものは Void と記述。
...クラス名 extends AsyucTask<①String, ②Void, ③String> {
①Params
execute() . doInBackground() の引数の型。
→ execute() の引数がそのまま doInBackground() の引数として渡される
②Progress
publishProgress() . onProgressUpdate() の引数の型。
→ publishProgress() の引数が、そのまま onProgressUpdate() の引数として渡される。
③Result
doInBackground() の戻り値、および、onPostExecute() . onCanceled() の引数の型。 → doInBackground() の戻り値は、そのまま、onPostExecute() や onCanceled() の引数 として渡される。
#httpアクセス
##インターネット接続許可を与える
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
もし許可を与えずにインターネット通信を行うとjava.net.SocketException: socket failed: EACCES (Permission denied)の例外が発生します。
##インターネットに接続する
HttpURLConnectionオブジェクトを使います。
##URL文字列をセットする。
URL url = new URL("URL文字列");
##コネクションの取得
con = (HttpURLConnection) url.openConnection();
アクセス先URL情報を持ったURLオブジェクトに対して**URL#openConnection()**メソッドを実行すると、HttpURLConnectionオブジェクト(コネクション)を取得することができます。
##アクセス方法の設定
**setRequestMethod()を使います。
*今回はデータ取得のため"GET"
con.setRequestMethod("GET")
##実際にインターネット接続
**URLConnection#connect()**を使います。
con.connect();
##コネクションの切断
**disconnect()**を使います。
処理終了後は、不要なコネクションを残さないために、明示的にコネクションを切断してあげる必要があります。
con.disconnect()
##httpリクエストの際のサンプルコード
private class クラス名 extends AsyncTask<String, Void, String> {
private static final String DEBUG_TAG = "タグ";
@Override
public String doInBackground(String... params) {
String urlStr = params[0];
String id = params[1];
HttpURLConnection con = null;
InputStream is = null;
String result = "";
try {
URL url = new URL(urlStr);
con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.connect();
is = con.getInputStream();
result = is2String(is);
}
catch(MalformedURLException ex) {
Log.e(DEBUG_TAG, "URL変換失敗", ex);
}
catch(IOException ex) {
Log.e(DEBUG_TAG, "通信失敗", ex);
}
finally {
if (con != null) {
con.disconnect();
}
if (is != null) {
try {
is.close();
}
catch (IOException ex) {
Log.e(DEBUG_TAG, "InputStream解除失敗", ex);
}
}
}
return result;
}
private String is2String(InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sb = new StringBuffer();
char[] b = new char[1024];
int line;
while(0 <= (line = reader.read(b))) {
sb.append(b, 0, line);
}
return sb.toString();
}
}
*InputStreamはバイトを読み込むためのクラス。
*is2Strクラスはおまじないみたいなものとして書いておいてください。理由はわかりません。わかる人は教えてください。
#JSONの扱い
JSONObjectクラスを使います。
引数として「JSON文字列」を指定します。
その後、以下の操作を行いながら、目的の JSONObject を取得し、getString( ... ) で値を取得する。
- 直下の JSONObject の取得は、getJSONObject( ... )
- 直下の JSONArray( JSON 配列 ) の取得は、getJSONArray( ... )
- JSONArray の指定の JSONObject の取得は、getJSONObject( ... )
##JSON処理の際のサンプルコード
private class クラス名 extends AsyncTask<String, Void, String> {
@Override
public void onPostExecute(String result) {
String title = "";
String text = "";
String dateLabel = "";
String telop = "";
try {
JSONObject rootJSON = new JSONObject(result);
title = rootJSON.getString("title");
JSONObject descriptionJSON = rootJSON.getJSONObject("description");
text = descriptionJSON.getString("text");
JSONArray forecasts = rootJSON.getJSONArray("forecasts");
JSONObject forecastNow = forecasts.getJSONObject(0);
dateLabel = forecastNow.getString("dateLabel");
telop = forecastNow.getString("telop");
}
catch(JSONException ex) {
Log.e(DEBUG_TAG, "JSON解析失敗", ex);
}
}
}
以上。
もし何か間違っている等のご指摘があればご連絡ください。
最後まで読んで頂きありがとうございました。