[Android] HttpURLConnection:GETリクエストでファイルをダウンロードする

HttpURLConnectionを利用すると、HTTP通信を使った処理を実装することができます。ここでは、HttpURLConnectionでHTTPのGETリクエストを実行し、ファイルをダウンロードする方法について説明します。
広 告
目次
前提条件
- 「AyncTask:非同期処理を実装する」を理解していること
動作確認端末
- Google Nexus 7 – 5.1.1 – API22(実機)
1. インターネット接続の許可を与える
アプリがインターネット接続するためには、アプリに対して「ネットワークへのフルアクセス」の許可を与える必要があります。
「ネットワークへのフルアクセス」の許可を与えるためには、マニフェストファイルの
<manifest>
タグ配下に以下のパーミッションを1行を追加します。
src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
java.net.SocketException: socket failed: EACCES (Permission denied)
の例外が発生します。
2. HttpURLConnectionを使ったGETリクエストの実装例
まずはHttpURLConnectionを使ってHTTPのGETリクエストを実行し、テキストを取得する処理の実装例を示します。
HTTP通信のようなインターネット通信処理は、ThreadやAsyncTaskなどを使用して別スレッド(ワーカースレッド)で実装する必要があります。今回の例では、AsyncTaskを使います。
HttpURLConnectionを使ったGETリクエストの実装例
import android.os.AsyncTask; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public final class HttpGetTask extends AsyncTask<URL, Void, Boolean> { @Override protected Boolean doInBackground(URL[] urls) { HttpURLConnection con = null; try { // アクセス先URL final URL url = new URL(values[0]); // 出力ファイルフルパス final String filePath = "/xxxx/xxxx/xxxx/filename.xxx"; // ローカル処理 // コネクション取得 con = (HttpURLConnection) url.openConnection(); con.connect(); // HTTPレスポンスコード final int status = con.getResponseCode(); if (status == HttpURLConnection.HTTP_OK) { // 通信に成功した // ファイルのダウンロード処理を実行 // 読み込み用ストリーム final InputStream input = con.getInputStream(); final DataInputStream dataInput = new DataInputStream(input); // 書き込み用ストリーム final FileOutputStream fileOutput = new FileOutputStream(filePath); final DataOutputStream dataOut = new DataOutputStream(fileOutput); // 読み込みデータ単位 final byte[] buffer = new byte[4096]; // 読み込んだデータを一時的に格納しておく変数 int readByte = 0; // ファイルを読み込む while((readByte = dataInput.read(buffer)) != -1) { dataOut.write(buffer, 0, readByte); } // 各ストリームを閉じる dataInput.close(); fileOutput.close(); dataInput.close(); input.close(); // 処理成功 return true; } } catch (IOException e1) { e1.printStackTrace(); } finally { if (con != null) { // コネクションを切断 con.disconnect(); } } return false; } }
上記のHttpGetTask
を呼び出し例は以下のとおりです。Activity
やFragment
のライフサイクルイフサイクルメソッドなどメインスレッドにて実装します。
HttpGetTaskの呼び出し例
try { new HttpGetTask().execute(new URL("http://xxxxxxxxxx/xxxxxx/")); } catch (MalformedURLException e) { e.printStackTrace(); }
AsyncTask#execute()メソッドの引数には、リクエス先のURLオブジェクトを渡します。
3. GETリクエストする
以下がGETリクエストを実行するためのコードです。
GETリクエスト処理部分
HttpURLConnection con = null; con = (HttpURLConnection) url.openConnection(); con.connect();
アクセス先URL情報を持ったURLオブジェクトに対してURL#openConnection()メソッドを実行すると、HttpURLConnectionオブジェクト(コネクション)を取得することができます。
URLConnection#connect()メソッドで実際にインターネット接続をします。
処理終了後は、不要なコネクションを残さないために、明示的にコネクションを切断してあげる必要があります。
コネクションを切断
con.disconnect();
4. ファイルをダウンロードする
GETリクエストを実行し、サーバアクセスに成功した場合にのみ、ファイルのダウンロード処理を実行します。
HTTP通信でサーバアクセスが成功すると、サーバからHTTPステータスコードの200
がレスポンスコードとして返ってきます。データ取得に成功したかは、このコードで判定することができます。
以下がレスポンスコードを判定するためのコードです。
レスポンスコードが成功(200)であった場合
// HTTPレスポンスコード final int status = con.getResponseCode(); if (status == HttpURLConnection.HTTP_OK) { // 通信に成功した }
HttpURLConnection#getResponseCode()メソッドを使うとサーバからのレスポンスコードを取得することができます。取得できたレスポンスコードが200
かどうかを判定するためには、HttpURLConnectionに用意された定数を用います。
Nexus7 端末で上記コードを実行した場合、以下のようなリクエスト情報が送信されます。
Nexus7で実行した場合のTCPダンプ
GET /xxxxxxx/ HTTP/1.1 User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; Nexus 7 Build/LMY47V) Host: xxxxxxxxxx Connection: Keep-Alive Accept-Encoding: gzip
アクセスに成功した後はファイルをダウンロードする処理を実行します。テキストデータの読み込み処理は以下のコードのとおりです。
ファイルのダウンロード処理
// ファイルのダウンロード処理を実行 // 読み込み用ストリーム final InputStream input = con.getInputStream(); final DataInputStream dataInput = new DataInputStream(input); // 書き込み用ストリーム final FileOutputStream fileOutput = new FileOutputStream(filePath); final DataOutputStream dataOut = new DataOutputStream(fileOutput); // 読み込みデータ単位 final byte[] buffer = new byte[4096]; // 読み込んだデータを一時的に格納しておく変数 int readByte = 0; // ファイルを読み込む while((readByte = dataInput.read(buffer)) != -1) { dataOut.write(buffer, 0, readByte); } // 各ストリームを閉じる dataInput.close(); fileOutput.close(); dataInput.close(); input.close();
ファイルを読み込み、書き込みをするためにはストリームを使います。読み込み用のストリームとしてはDataInputStreamを、書き込み用のストリームとしてはDataOutputStreamを用います。これらストリームを大容量のサイズのデータを扱う場合に使用されます。ストリームは以下の手順で使用します。
- 1. ストリームを開く
- 2. データが存在する限り、読み込みを継続する
- 3. ストリームを閉じる
読み込み用ストリームを開いた後は、DataInputStream#read(byte[])を使用してバイトデータを読み込みます。
書き込みストリームを開いた後は、DataOutputStream#write(byte[] buffer, int offset, int count)を使ってバイトデータを書き込みます。
DataInputStream#read(byte[])が-1
を返却するとデータの読み込みが終了したことを意味するため処理を終了します。
最後にストリームは閉じるようにします。
5. 参考URL
HttpURLConnection | Android Developers
http://developer.android.com/intl/ja/reference/java/net/HttpURLConnection.html