[Kotlin] HttpURLConnectionの使い方 | GETとPOSTリクエスト

Android

Androidアプリで通信処理を作る方法はいくつかあります。
今回はそのうちの一つであるHttpUrlConnectionを使った方法を簡単にではありますがまとめていきます。
特に、頻繁に使われるHTTPメソッドのGETPOSTのサンプルコードを載せていきます。

スポンサーリンク

環境

  • Android Studio : 4.1.1
  • Kotlin : 1.3.72-release-Studio4.1-5

GETリクエスト

GETリクエストのサンプルコードは以下です。

fun startGetRequest() {
    // HttpURLConnectionの作成
    val url = URL("ここにURL")
    val connection = url.openConnection() as HttpURLConnection
    try {
        // ミリ秒単位でタイムアウトを設定
        connection.connectTimeout = CONNECTION_TIMEOUT_MILLISECONDS
        connection.readTimeout = READ_TIMEOUT_MILLISECONDS

//        connection.requestMethod = "GET"
//        connection.connect()

        // Responseの読み出し
        val statusCode = connection.responseCode
        if (statusCode == HttpURLConnection.HTTP_OK) {
            readStream(connection.inputStream)
        }
    } catch (exception: Exception) {
        Log.e("Error", exception.toString())
    } finally {
        connection.disconnect()
    }
}

POSTリクエスト

POSTリクエストのサンプルコードは以下です。

fun startPostRequest() {
  // Bodyのデータ(サンプル)
    val sendDataJson = "{\"id\":\"1234567890\",\"name\":\"hogehoge\"}"
    val bodyData = sendDataJson.toByteArray()
    
    // HttpURLConnectionの作成
    val url = URL("ここにURL")
    val connection = url.openConnection() as HttpURLConnection
    try {
        // ミリ秒単位でタイムアウトを設定
        connection.connectTimeout = CONNECTION_TIMEOUT_MILLISECONDS
        connection.readTimeout = READ_TIMEOUT_MILLISECONDS

//        connection.requestMethod = "POST"
        // Bodyへ書き込むを行う
        connection.doOutput = true

        // リクエストBodyのストリーミング有効化(どちらか片方を有効化)
//        connection.setFixedLengthStreamingMode(bodyData.size)
        connection.setChunkedStreamingMode(0)

        // プロパティの設定
        connection.setRequestProperty("Content-type", "application/json; charset=utf-8")

//        connection.connect()

        // Bodyの書き込み
        val outputStream = connection.outputStream
        outputStream.write(bodyData)
        outputStream.flush()
        outputStream.close()

        // Responseの読み出し
        val statusCode = connection.responseCode
        if (statusCode == HttpURLConnection.HTTP_OK) {
            readStream(connection.inputStream)
        }
    } catch (exception: Exception) {
        Log.e("Error", exception.toString())
    } finally {
        connection.disconnect()
    }
}

サンプルコードの補足

GETリクエストのサンプルコードの補足

GETリクエストのサンプルコードの補足をします。
以下の処理はコメントアウトしていますが、それぞれ有効にしても問題はありません。

//        connection.requestMethod = "GET"
//        connection.connect()

requestMethodはHTTPリクエストメソッドの設定、connect()は接続確立処理です。

requestMethod

requestMethodはデフォルト値がGETになっているため指定は不要です。
コードが理解しやすいようにGETをあえて明記しておくのはありです。

connect()

connect()は通信リンクの確立処理ですが記載は不要です。
connect()を記述すると明示的に接続確立処理を実行することになりますが、connect()を記述しない場合はレスポンスデータを読み出しする際に処理が行われます

つまり、今回のサンプルコードでは以下の処理のタイニングで接続処理が自動的に行われるため不要となります。

val statusCode = connection.responseCode

POSTリクエストのサンプルコードの補足

POSTリクエストのサンプルコードの補足をします。

requestMethod

requestMethod処理はコメントアウトしていますが、それぞれ有効にしても問題ありません。

//        connection.requestMethod = "POST"
        // Bodyへ書き込むを行う
        connection.doOutput = true

「GETリクエストのサンプルコードの補足」の中で「requestMethodはデフォルト値がGETになっているため指定は不要です。」と言いました。

しかし、POSTリクエストであるのにrequestMethodにPOSTを設定していません。
これは、doOutputtrueを設定すると内部的にPOSTのリクエストとして判別される動きとなるためです。
GET/POST以外のHTTTメソッドの場合には指定が必要になるので注意してください。

setFixedLengthStreamingModeとsetChunkedStreamingMode

無駄なメモリ使用と処理時間をかけないように、Bodyの長さが事前に判明している場合にはsetFixedLengthStreamingMode()で長さを指定し、不明な場合はsetChunkedStreamingMode(0)を呼ぶようにします。

        // リクエストBodyのストリーミング有効化(どちらか片方有効)
//        connection.setFixedLengthStreamingMode(bodyData.size)
        connection.setChunkedStreamingMode(0)

Bodyの書き込み

今回、BodyでJSONデータを送信するため、Content-typeを設定してBodyにデータを書き込んでいます。

        // プロパティの設定
        connection.setRequestProperty("Content-type", "application/json; charset=utf-8")

        // Bodyの書き込み
        val outputStream = connection.outputStream
        outputStream.write(bodyData)
        outputStream.flush()
        outputStream.close()

その他補足情報

今回、通信処理を行うため、まずAndroidManifest.xmlにインターネットへの接続許可を追加する必要があります。

<uses-permission android:name="android.permission.INTERNET" />

また、GET/POSTのサンプルコードではreadStream(connection.inputStream)と記述していましたが、readStream()メソッドは定義していませんでした。
どのようにレスポンスデータ読み出したいか、によって方法が異なるためです。
ですが、備忘録としてStringデータとして読み出す一例としてを載せておきます。

fun readStream(inputStream: InputStream) {
    val bufferedReader = BufferedReader(InputStreamReader(inputStream))
    val responseBody = bufferedReader.use { it.readText() }
    bufferedReader.close()

    Log.d("レスポンスデータ : ", responseBody)
}

最後に、今回のサンプルコードはワーカースレッドで実行する必要があります
通信処理をメインスレッドで実行するとandroid.os.NetworkOnMainThreadExceptionエラーが発生しますのでご注意ください。

関連記事

同じ通信処理をOkHttp3を使って実装する方法について記事を書いています。
HttpURLConnectionより簡単に実装ができますので、こちらについて読んでおくのも良いと思います。

参考ページ

今回のHttpURLConnectionの記事を書くにあたり、主に以下のdeveloperページを読み込みましたので、一読しておくと良いと思います。

HttpURLConnection  |  Android Developers