AndroidのWebViewのエラーページをカスタマイズする

やり方

app/src/main/Assets/化に表示したいエラーページのHTMLを配置して
override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
    view?.loadUrl("file:///android_asset/error.html")
}
するか
Layoutのxmlにエラーページを記載しsetVisiblityView.VISIBLEを渡してあげるかですが、私は前者を採用しています。
本当は他の方法もある気がしますが、よくわからなかったので……。

実装

多言語対応とメッセージを組み込みたいのでクエリーを埋め込みます
webView.webViewClient = object : WebViewClient() {
    override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
        // メインフレームのエラーのみ
        // 画像のリンク切れなどのエラーもハンドリングされてしまうため
        if (request?.isForMainFrame == true) {
            super.onReceivedError(view, request, error)

            // エラーメッセージを取得
            failed = "${error?.description ?: "unknown"}"

            // 端末の言語設定を取得
            val lang = Locale.getDefault().language

            // assetからエラー表示するHTMLを取得
            // クエリでエラーメッセージと言語を埋め込む
            view?.loadUrl("file:///android_asset/error.html?error=$failed&lang=$lang")
        }
    }

    ...
}

// js有効化
webView.settings.javaScriptEnabled = true

app/src/main/Assets/error.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <style>
        body {
            background: #3c4452;
            color: #d8dadc;
            text-align: center;
            padding-top: 100px;
        }
    </style>
    <script>
        var queries = {};
        (function(){
            // クエリを取得
            var str = window.location.search.slice(1);

            if (!str)  return;

            // ハッシュに詰める
            str.split('&').forEach(e => {
                var ary = e.split('=');
                queries[ary[0]] = ary[1];
            });
        })();

        window.addEventListener('DOMContentLoaded', () => {
            // 日本語以外なら日本語を非表示
            if (queries['lang'] != 'ja') {
                document.querySelectorAll('[data-lang="ja"]').forEach(e => {
                    e.style.display = 'none';
                });
            } else {
                document.querySelectorAll('[data-lang="en"]').forEach(e => {
                    e.style.display = 'none';
                });
            }
        });
    </script>
</head>
<body>

<h1 data-lang="en">Error</h1>
<h1 data-lang="ja">エラー</h1>

<p data-lang="en">The page could not be loaded for the following reasons.</p>
<p data-lang="ja">ページは次の理由で読み込めませんでした。</p>

<script>document.write(queries['error'])</script>

</body>
</html>
カスタマイズ前 カスタマイズ後
カスタマイズ前カスタマイズ後

おわりに

Responseとかでできたのかわかりませんが、ひとまずこれでエラーページをカスタマイズできました。

参考

  1. Android webview custom error page - Stack Overflow
    https://stackoverflow.com/a/36286295

0 件のコメント :

コメントを投稿