🙌

[Android] Javascript Interface

2024/09/21に公開

Javascript Interfaceとは?

スマホアプリ内にウェブページを埋め込むwebViewを使う際、
フロントエンドのコードがスマホアプリのネイティブコードを叩く手段が提供されている。

それがJavascriptInterface

使い方導入

kotlin実装

class MyJavascriptInterfaces {
    @JavascriptInterface
    fun hello(){
        Log.i("webViewApp", "Hello, World")
    }
}

というJavascript Interfaceを搭載したクラスを作り

binding.webView.apply {
    settings.javaScriptEnabled = true
    addJavascriptInterface(MyJavascriptInterfaces(), "MyJavascriptInterface")
    loadUrl("https://www.google.co.jp/")
}

webViewのaddJavascriptInterface関数を使用して登録するだけ。簡単。

フロントエンドから叩く方法

MyJavascriptInterface.hello()

で叩ける。

もしもリリース済みのアプリで

  1. JavascriptInterfaceを導入しようとしている場合
  2. JavascriptInterfaceの関数を追加しようとしている場合

は、過去のアプリ上でエラーが発生しないよう

MyJavascriptInterface?.hello?.()

とすると安全である。

実際に動かしてみる

webViewアプリを起動して
Chrome上で chrome://inspect/#devices を開いてください

image.png

このように現在起動しているwebView画面の一覧が出て来ます。
スマホでGoogle Chrome等のブラウザを開いているとそれも一覧に出て来ます。

inspectを押すと見慣れた物が出て来ます。
先ほどのJavascriptInterface呼び出し関数をconsole上で実行すると

image.png
エラーが発生せず
LogCatを確認すると Hello, World が正常に出力されています。

取り扱える値

誰かドキュメント探して教えてください(土下座)!!!探しても見つからなかったので実際に動かして試しました。

結論から言うと、引数と戻り値ともに

  • Boolean
  • Int
  • Double
  • String
  • String?
    が取り扱える。

引数限定として

  • StringArray
    も渡せる。
@JavascriptInterface
fun getInt(v: Int): Int {
    return v+2
}

@JavascriptInterface
fun getBoolean(v: Boolean): Boolean {
    return !v
}

@JavascriptInterface
fun getDouble(v: Double): Double {
    return v+1
}

@JavascriptInterface
fun getString(v: String): String {
    return "hello~ $v"
}

@JavascriptInterface
fun getOptionalString(v: String?): String? {
    return v?.let{"hello~ $it"}
}

@JavascriptInterface
fun getStringArray(v: Array<String>) {
    v.forEach {
        element -> Log.i("WebViewApp", element)
    }
}

応用例

Stringが扱えるので、jsonを一回stringに変換すれば相互にjsonの受け渡しが可能です。

@JavascriptInterface
fun getJsonString(v: String): String {
    val json: JSONObject = JSONObject(v)
    val name: String = json.get("name") as String
    val age: Int = json.get("age") as Int
    json.put("status", "alive")
    return json.toString()
}
let character = {"name": "taro", "age":25}
// jsonをstringに変換すると共にJavascriptInterfaceで値の受け渡し
let returnString = MyJavascriptInterface.getJsonString(JSON.stringify(character))
// stringをjsonに変換
let json = JSON.parse(returnString)

サンプルレポジトリ

https://github.com/holndal/javascriptInterfaceScratch

Discussion