コンパイラかく語りき

import { Fun } from 'programming'

flutter アプリで表示するウェブビューを React.js/Next.js で作る(ウェブビュー判定、イベントハンドラ呼び出し)

概要

ネイティブアプリを開発する際に一部のページをウェブで表示する、という要件はあると思います。(いわゆるウェブビュー) その際に、ウェブビューを React.js と Next.js で作成する方法です。

※ちなみに筆者はネイティブアプリ開発の経験はありません。あくまでウェブフロントエンド開発の観点での記事です。

環境

対象の flutter ライブラリはこちら→ https://inappwebview.dev/

この記事を執筆している時点での環境は、React.js のバージョンが 18.2.0、Next.js のバージョンが 13.1.4、InAppWebView が6系です。

ウェブビュー開発

ウェブビュー自体は、React.js で普通にビューを作れば OK です。

ページ表示するコンポーネントを作成し、Next.js でルーティング登録します。

ネイティブアプリからは、このルーティング(URL)を呼び出すカタチになります。

ウェブビュー判定

ウェブビューの判定です。

筆者はウェブビューに関する処理は、1つのカスタムフックスにまとめました。

import { useEffect, useState } from 'react'

/**
 * WebView Custom Hook
 */
const useWebview = () => {
  const [isWebview, setIsWebview] = useState(false)

  useEffect(() => {
    // webview判定
    window.addEventListener('flutterInAppWebViewPlatformReady', () => {
      setIsWebview(true)
    })
  }, [])

  return { isWebview }
}

flutter 側が発行する flutterInAppWebViewPlatformReady イベントを監視しています。これがコールされれば webview、という判定です。

window.flutter_inappwebview の存在チェックでも良い気がしますが、後続のイベントハンドラ呼び出しでも利用したいので、 flutterInAppWebViewPlatformReady を判定材料としました。

イベントハンドラ呼び出し

ネイティブアプリとウェブアプリ間でのコミュニケーションです。

flutter 側でイベントハンドラを登録してもらいます。

onWebViewCreated: (controller) {
  // "myHandlerName" という名称で JavaScript イベントハンドラを登録
  controller.addJavaScriptHandler(handlerName: 'myHandlerName', callback: (args) {
    // JavaScript 側から送られたデータを表示
    print(args);

    // データを JavaScript 側に返す
    return {
      'bar': 'bar_value', 'baz': 'baz_value'
    };
  });
}

ウェブアプリ側から呼び出します。先ほどのカスタムフックスを拡張します。

import { useCallback, useEffect, useState } from 'react'

// 型拡張
declare global {
  interface Window {
    flutter_inappwebview: {
      callHandler: (handlerName: string, data?: unknown) => void
    }
  }
}

/**
 * WebView Custom Hook
 */
const useWebview = () => {

  // 省略

  /** webview イベントハンドラ実行 */
  const callWebViewEvent = useCallback<typeof global.window.flutter_inappwebview.callHandler>(
    (handlerName, data) => {
      if (!isWebview) return
      window.flutter_inappwebview.callHandler(handlerName, data)
    },
    [isWebview]
  )

  return { isWebview, callWebViewEvent }
}

export default useWebview

登録されたイベントハンドラは、 window.flutter_inappwebview.callHandler から呼び出し可能です。

せっかく TypeScript なので、もう少し型をつけても良いかもですね。

まとめ

flutter アプリで表示するウェブビューを React.js/Next.js で作る、について書きました。

より詳しいことは、公式ドキュメントに記載されています。

inappwebview.dev