StradaのWebViewとネイティブコード連携を理解する
みんな大好き(のはず)Turbo関連のネイティブコンポーネント連携ライブラリのStradaがついにリリースされたので実装を調べてみる。
前提
- Turbo NativeでWebアプリが動いている。これはリモートのURLでよい。
- Stimulusでコントローラーを記述している
テスト環境
https://turbo-native-demo.glitch.me/ を https://github.com/hotwired/turbo-ios のDemo Appで読み込むとStradaの機能を試せるようになってる。
git clone https://github.com/hotwired/turbo-ios
xed Demo/
サーバーサイドのコードは https://github.com/hotwired/turbo-native-demo にあり、これの実行にRailsはいらない(Express+EJSで書いてある)。
とりあえず https://turbo-native-demo.glitch.me/strada-menu のサンプルで説明。
このページをiOSアプリで開き、ボタンをタップするとWebViewのコンテキストの外でネイティブコードのUIAlertActionのAPIが呼び出される。
使い方
ViewとなるHTML
data-action="click@window->menu#hideOnClickOutside"
と宣言されている部分はネイティブではなくWebのみにフォールバックされるViewになる。
data-action="click->bridge--menu#show click->menu#show"
になっているelementがネイティブブリッジ用。
Stimulus.register("bridge--menu", BridgeMenuController)
でアタッチされている
this.send("display",...
のブロックが肝でこれを呼び出すことでネイティブコンポーネントへメッセージを送信している。
コールバックにネイティブ→Webの逆方向の呼び出しが発生した時の関数がある。このサンプルの場合、クリックしたメニュー項目をViewに反映させるためのコード。
以下がネイティブコンポーネントの実装。send->onReceive()
がペアになっている。この場合message.event='display'
になっている。
ネイティブからWebViewに返す時はreply()
。
WebView内で動作するControllerも同時に実行されていて was selected
と表示しているのはWebになる。
WebViewの外部のViewをネイティブに実装することもできる。以下はAnddroidのViewを記述している個所。
開発フロー
Strada自体の使い方は以上で、ポイントとしては今までのHotwireシリーズ同様に
- Turobのみを使ってWebアプリを構成する
- Stimulusを追加してクライアントサイドを書く
- Turbo Nativeでハイブリッドアプリにする
- Stradaでブリッジコードを書いて拡張する
を段階的にデリバリーできるようになっている。
以降はStradaの内部実装を深掘りしたい。
strada-ios実装
- WKWebViewをWKUserContentControllerで拡張してstrada.jsのインターフェイスをネイティブ側に付ける
- ブラウザ側(Webアプリ)にはwindow.Stradaが注入されていてこれを使った双方向のメッセージングプロトコルが実装されている
なのでWebアプリからこういうコードを直接実行するとメッセージングを直接使うことが可能。
Strada.web.send({
id: "1",
component: "menu",
event: "display",
data: {
metadata: { url: window.location.href },
title: "こんにちは",
items: [{ index: 0, title: "さようなら" }],
},
callback: console.log('Strada callback'),
});
strada-android実装
-
webview.addJavascriptInterface()
でStradaNative(strada.js)をwindow.nativeBridge
にットする -
webview.evaluateJavascript()
で生成したJavaScriptのコードを実行することでメッセージングをする
Discussion