はじめに
AndroidアプリにはWebサイトを表示することができるWebViewというものがあります。
そこで、AndroidとWebView間でデータをやり取りするのにどうしたらいいのかを書いていこうと思います。
やりたいこと
- WebView から Android にデータを渡す
- Android から WebView にデータを渡す
WebView から Android にデータを渡す
webView.webChromeClient
の onJsAlert
を使っていきます。
これはWebView内のJavaScriptの alert
を検知して発火するイベントです。
alert
に表示する文字列を onJsAlert
の引数 message
として受けることができます。
Android
// 省略
webView.webChromeClient = object : WebChromeClient() {
override fun onJsAlert(view: WebView, url: String, message: String, result: JsResult): Boolean {
// 処理
result.cancel()
return true
}
}
// 省略
WebView
<template>
<div class="home">
<button @click="callNativeFunc()">Submit</button>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
@Component({})
export default class Home extends Vue {
public callNativeFunc() {
alert(JSON.stringify({key: "test", msg: "hoge"}))
}
}
</script>
Android から WebView にデータを渡す
webView.evaluateJavascript()
を使って WebViewのWindowオブジェクトに埋め込まれた関数を呼び出します。
下記の例では window.testFunc
をAndroidからコールしています。
WebViewではVueコンポーネントの mounted()
のタイミングで window オブジェクトにAndroidから呼ばれる関数を宣言しています。
Android
// 省略
val text = "{key: \"test\", msg: \"Message from Native\"}"
webView.evaluateJavascript("window.testFunc('$text')", null)
// 省略
WebView
<template>
<div class="home">
<button @click="callNativeFunc()">Submit</button>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
@Component({})
export default class Home extends Vue {
public mounted() {
(window as any).testFunc = (text: string) => {
// 処理
};
}
public callNativeFunc() {
alert(JSON.stringify({key: "test", msg: "hoge"}))
}
}
</script>
結論
個人的には割とイレギュラーな形でデータの受け渡しをしているので、管理が大変になるというか、アプリの仕様が複雑化するなーと感じました。
WebViewは静的なサイトを表示するだけにした方が、アプリとしての治安が守られるのかなーという気がしました。
ほかにもっといい方法あるよ!という知見をお持ちの方がおられましたら、その知見をご教授ください…
ではまた!!!