2021年3月7日日曜日

AndroidでkHttpを使ってみる

 Androidのネットワーク通信で有名な外部ライブラリといえば「OkHttp」「Retrofit」だろう。
なのであえて、「kHttp」というライブラリを使った通信を行ってみた。


kHttpとは

公式はここ
Pythonでスクレイピングをするときに使う「requestsモジュール」をKotlinで使うようにしたもの。Android以外でも使えるHTTPリクエストできるシンプルなライブラリだ。

    Android9.0から使えなくなる

    Andorid9.0以上で実行すると、以下の実行時エラーになる
    # Logcatの内容
    java.lang.NoSuchFieldException: No field host in class Ljava/net/URL; (declaration of 'java.net.URL' appears in /system/framework/core-oj.jar)
      at java.lang.Class.getDeclaredField(Native Method)
    
    エラー内容から、このライブラリはURLクラスの「host」というプライベート変数をリフレクションで書き換えてHttp通信していたようだ。
    一応、裏を取るためにライブラリの中身も確認

    ビンゴ!
    どうやら、Android9.0のOSからURLクラスの処理が変わったようだ。
    この問題を解決するため「kHttp Android」というライブラリが出てきた。


ライブラリを使うための準備

以上から
本記事のkHttpはAndroid9.0以上でも使える様に「kHttp Android」として話を進める。
// Projectの build.gradleに追記
// ...
repositories {
    // ...
    maven { url 'https://jitpack.io' }
}
// appの build.gradleに追記
// ...
dependencies {
    // ...
    implementation "io.karn:khttp-android:0.1.2"
}
appの build.gradleのversionは公式を参照して最新を使用

実装

AndroidはHTTPのリクエストをUIスレッド上で実行できないのでコルーチンで実行

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import khttp.get
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch;

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        GlobalScope.launch {
            val test = get("https://httpbin.org/ip").jsonObject.getString("origin")
            Log.d("Tag", test)
        }
     }
}
公式のサンプルコードは「http」プロトコルを使っているが、
Androidで行うなら「https」にすべき。
これもAndroid9.0よりセキュリティ観点から、Httpのリクエストが抑止されているからだ

0 件のコメント:

コメントを投稿