LoginSignup
6
7

More than 5 years have passed since last update.

Android開発〜WEBアクセス(GET)外部と通信してデータを取得してみる。〜

Last updated at Posted at 2018-11-06

はじめに

こんにちは。某学校でプログラミング等の勉強中のサーバーサイドのプログラマーのワタタクです。:relaxed:
今回もAndroid開発していきましょう。
今回はAndroidで外部のネットワークと接続してデータを取得してみたいと思います。

対象者

  • Javaがそこそこ書ける人。
  • Android開発においてもそこそこできる人。

Webアクセス概要

1) アプリ内で http アクセスのソースコードを記述する。 → レスポンスの内容は JSON か XML が多い。
2) 画面内で画面部品 WebView を使う。 → レスポンスの内容は原則 HTML。

非同期処理

Webアクセスのように、処理に時間がかかるもの、予期せぬエラーが起こりそうなもおは、 メイン処理とは別のスレッドで処理(非同期処理)を行う。

AsyncTask

Androidの非同期処理のうち、UIスレッドとやりとりがある場合は、AsyucTaskクラスを使うと便利。

1.AsyncTaskの使い方

1) Asynuc Task を継承したクラスを作成する。
→ アクティビティクラスの private メンバクラスとして作ると便利。

2) メソッド doInBackground() 内に非同期で行いたい処理を記述する。
→ このメソッドは Asyuc Task の抽象メソッドなので、必ずオーバーライドする必要がある。

3) アクティビティでこのクラスを 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アクセス

インターネット接続許可を与える

src/main/AndroidManifest.xml
<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);
            }

   }
}

以上。
もし何か間違っている等のご指摘があればご連絡ください。
最後まで読んで頂きありがとうございました。

6
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7