SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Android Studio 2で始めるアプリ開発入門

Androidアプリでの非同期処理とWeb API連携

Android Studio 2で始めるアプリ開発入門 第11回


Androidの非同期処理

 では、WeatherInfoActivityに非同期でお天気情報を取得する処理を追加していきましょう。

非同期処理3ステップ

 Androidで非同期処理を行うには、先述の通りAsyncTaskを使用します。使い方は以下の3ステップです。

  1. AsyncTaskを継承したクラスを作成。
  2. 上記クラス内のdoInBackground()メソッドに非同期で行いたい処理を記述。
  3. Activityクラス内でこのクラスをnewし、execute()メソッドを実行する。

 このステップに従って、WeatherInfoActivityにソースコードを追記していきましょう。

1)AsyncTaskを継承したクラスを作成

 まず、ステップ1)です。WeatherInfoActivityに以下のメンバクラスを追加してください。

リスト1 WeatherInfoActivityにメンバクラスを追加
public class WeatherInfoActivity extends AppCompatActivity {
        ~省略~
    private class WeatherInfoReceiver extends AsyncTask<String, String, String> {  // (1)
        @Override
        public String doInBackground(String... params) {  // (2)
        }
        
        @Override
        public void onPostExecute(String result) {  // (3)
        }
    }
}

 AsyncTaskを継承したクラスですが、トップレベルクラスとして作成してもいいですが、WeatherInfoActivityでしか使用しないクラスなので、メンバクラスとしてWeatherInfoReceiverを作成しています(リスト1の(1))。

 その際、AsyncTaskにジェネリクスを3個指定する必要があります。これは、AsyncTaskを継承したクラス内のメソッドの引数や戻り値の型を指定するためです。それぞれの役割は以下の通りです。なお、()内はそれぞれのジェネリクス名です。

  • 1個目(Params):execute()、doInBackground()の引数の型
    • これらのメソッドは、可変長引数となっており、上記ステップ3)でexecute()メソッドを実行時に渡された引数が、そのままdoInBackground()の引数として横流しされるような仕組みになっています。
  • 2個目(Progress):publishProgress()、onProgressUpdate()の引数の型
    • これらのメソッドの使い方は後述しますが、publishProgress()実行時に渡された引数が、そのままonProgressUpdate()の引数として横流しされるような仕組みになっています。
  • 3個目(Result):doInBackground()の戻り値の型、および、onPostExecute()、onCancelled()メソッドの引数の型
    • こちらも後述しますが、doInBackground()の戻り値がそのままonPostExecute()、およびonCancelled()の引数としてわたります。

 WeatherInfoReceiverでは

AsyncTask<String, String, String>

とすべてStringを指定していますので、doInBackground()の引数も戻り値もStringであり(リスト1の(2))、onPostExecute()の引数もStringです(リスト1の(3))。

2)doInBackground()に処理を記述

 次に、ステップ2)です。doInBackground()メソッドに非同期で行いたい処理を記述します。なお、doInBackground()メソッドはAsyncTaskクラスでは抽象メソッドとして定義されていますので、必ず実装する必要があります。

 このメソッド内で、インターネットにアクセスしてデータを取得する処理を記述します。

リスト2 doInBackground()に処理を記述
public String doInBackground(String... params) {
    String id = params[0];  // (1)
    String urlStr = "http://weather.livedoor.com/forecast/webservice/json/v1?city=" + id;  // (2)
    HttpURLConnection con = null;  // (3)
    InputStream is = null;  // (3)
    String result = "";  // (3)
    try {
        URL url = new URL(urlStr);  // (4)
        con = (HttpURLConnection) url.openConnection();  // (5)
        con.setRequestMethod("GET");  // (6)
        con.connect();  // (7)
        is = con.getInputStream();  // (8)
        result = is2String(is);  // (9)
    }
    catch(MalformedURLException ex) {
    }
    catch(IOException ex) {
    }
    finally {
        if(con != null) {
            con.disconnect();  // (10)
        }
        if(is != null) {
            try {
                is.close();  // (11)
            }
            catch(IOException ex) {
            }
        }
    }
    return result;  // (12)
}

 インターネットにアクセスするには例外がつきものなので、例外処理を行って少しソースコードが見にくくなっていますが、上記ソースコードが定型の処理となっています。次にその解説を行います。

httpアクセス

 インターネットにアクセスするにはAndroidでもhttpプロトコルを使うため、httpアクセスと呼ぶことができます。Androidでhttpアクセスを行うには、APIレベル9以前であればApache HttpClientを使用していました。現在ではHttpURLConnectionを使用します。使い方は以下の手順です。

 url文字列からURLオブジェクトを作成します(リスト2の(4))。このurl文字列ですが、ライブドアの仕様に従ったURLをまず文字列として生成しています(リスト2の(2))。その際、都市IDが必要なので、これをdoInBackground()の引数として受け取ります(リスト2の(1))。

 URLオブジェクトからHttpURLConnectionオブジェクトを取得します(リスト2の(5))。これは、URLオブジェクトのopenConnection()メソッドを使用します。ただ、このメソッドの戻り値の型は、URLConnectionなので、HttpURLConnectionにキャストする必要があります。

 POSTかGETを設定します(リスト2の(6))。これは、HttpURLConnectionのsetRequestMethod()メソッドに引数として「POST」か「GET」の文字列を渡します。今回はGETなのでそのようにしています。

 http接続を行います(リスト2の(7)))。これは、HttpURLConnectionのconnect()メソッドを使います。このメソッドを実行したときに、httpアクセスを行い、レスポンスデータの取得まで行います。したがって、メソッド実行後にはHttpURLConnectionオブジェクト内にレスポンスデータが格納されています。

 この格納されたレスポンスデータを取得します(リスト2の(8))。ただ、これはInputStreamオブジェクトとして格納されているので、getInputStream()メソッドを実行して取得します。

 HttpURLConnectionオブジェクトを解放します(リスト2の(10))。これは、disconnect()メソッドを使いますが、こういう接続関係のオブジェクトはリソースを必要としますので、確実に開放しておく必要があります。そのため、finallyブロック内で解放します。その際、未接続の状態でfinallyブロックが実行される可能性もありますので、あらかじめcon(HttpURLConnectionオブジェクト)のnullチェックを行っています。

 あとは、取得したInputStreamオブジェクトを必要な形に変換して、必要データを取り出したり、ファイルとして保存したりします。今回はレスポンスデータがJSON文字列なので、InputStreamオブジェクトを文字列に変換する必要があります。それが、リスト2の(9)です。ここで呼び出しているis2String()はInputStreamオブジェクトを文字列に変換する定型処理を記述したprivateメソッドです。このメソッドのソースコードはダウンロードサンプルを参照してください。

 なお、InputStreamオブジェクトも確実に解放する必要がありますので、finallyブロックでclose()を行っています(リスト2の(11))

 また、このように、tryブロック内で取得したオブジェクトをtry外で解放などの処理を行うため、あらかじめtry外で宣言する必要があります。それが、リスト2の(3)です。

 最後に、httpアクセスの結果、取得したJSON文字列(ここに天気情報が格納されている)をdoInBackground()の戻り値として返します(リスト2の(12))。

インターネット接続許可

 これで、ひととおりhttpアクセスのソースコードが記述できたことになりますが、このままではhttpアクセスができません。Androidではアプリがインターネットにアクセスするには、その許可を与える必要があります。これは、AndroidManifest.xmlに以下の2行を記述することで可能となります。

リスト3 AndroidManifest.xmlへの追加
<manifest …>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <application
        ~省略~

3)非同期処理の実行

 最後に、ステップ3)です。Activityクラス内でこの非同期処理クラスをnewし、execute()メソッドを実行します。WeatherInfoActivityのonCreate()メソッドに以下のソースコードを追加してください。

リスト4 onCreate()メソッドにソースコードを追加
protected void onCreate(Bundle savedInstanceState) {
        ~省略~
    Intent intent = getIntent();  // (1)
    String cityName = intent.getStringExtra("cityName");  // (1)
    String cityId = intent.getStringExtra("cityId");  // (1)

    WeatherInfoReceiver receiver = new WeatherInfoReceiver();  // (2)
    receiver.execute(cityId);  // (3)
}

 非同期処理を実行する前に、まず都市リスト画面からの引継ぎデータを取得します(リスト4の(1))。その上で、非同期処理クラスであるWeatherInfoReceiverをnewし(リスト4の(2))、execute()メソッドを実行しています(リスト4の(3))。

次のページ
JSONデータの表示

この記事は参考になりましたか?

Android Studio 2で始めるアプリ開発入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 齊藤 新三(サイトウ シンゾウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。Web系製作会社のシステム部門、SI会社を経てフリーランスとして独立。屋号はSarva(サルヴァ)。HAL大阪の非常勤講師を兼務。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/9746 2018/05/23 15:37

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー