今回はAndroidのWebViewについてです
iOSと違う部分もあるので見ていきましょう!
Webページを表示させる
Webページを表示させるだけであれば簡単にできます
前提としてAndroidManifest.xmlでインターネットの権限の設定を行ってください
<manifest ... > <uses-permission android:name="android.permission.INTERNET" /> </manifest>
レイアウトファイルでwebviewを作成して、表示させるURLを読み込む処理を行うのみです
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/webView" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
webView.loadUrl("http://www.example.com")
表示させるのはこれだけでできます。ここからは細かい設定について説明します
WebViewの設定を追加する
WebViewの設定はWebSettings
を利用します。設定は次のように行います(一部抜粋します)
// JavaScriptを有効にする(ここでのwebViewはレイアウトのID) webView.settings.javaScriptEnabled = true // ピンチ操作によるズームイン・ズームアウトの有効化 webView.settings.builtInZoomControls = true // ダブルタップによるズームイン・ズームアウトの有効化 webView.settings.useWideViewPort = true // ズームボタン(右下に表示される±のルーペ)の表示・非表示切り替え webView.settings.displayZoomControls = true // // Storageの使用許可の設定 webView.settings.domStorageEnabled = true // trueの場合にはHTMLのwidthがWebViewより大きい時に全体を表示するようによしなに調整される webView.settings.loadWithOverviewMode = true // ズーム機能をサポートするか否か webView.settings.setSupportZoom(true)
webViewClientの設定
webViewClient
はWebView内のセキュリティやルーティングなどのほとんどのアクションを担当するオブジェクトです
webViewClientの主な処理は次です
webView.webViewClient = object :WebViewClient() { // WebView内の別のリンクを表示させる際に override fun shouldOverrideUrlLoading( view: WebView?, request: WebResourceRequest? ): Boolean { // shouldOverrideUrlLoadingから別のActivityやアプリを起動する場合はtrueを返す。falseを返すとWebView内にロードした結果を表示 return false } // ページ読み込み開始時 override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { super.onPageStarted(view, url, favicon) } // ページ読み込み完了時 override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) } // アクセスエラーなどのWebリソースの読み込みエラー発生時の処理 override fun onReceivedError( view: WebView?, request: WebResourceRequest?, error: WebResourceError? ) { super.onReceivedError(view, request, error) // ここを追加しないと画像などが表示できない場合もエラー扱いになる if (request.isForMainFrame) { } } // SSLエラー時 override fun onReceivedSslError( view: WebView?, handler: SslErrorHandler?, error: SslError? ) { super.onReceivedSslError(view, handler, error) handler?.cancel() } }
注意点としてはonReceivedErrorを受け取ってもonPageFinishedは実行されるので、画面の制御などに気をつけましょう
HTMLを表示させる
次にHTMLを表示させる方法です
HTMLはassetsフォルダを作成しておきます
HTMLファイルを置いたら、呼び出してロードするだけで表示できます
// 今回の場合にはtest.htmlというファイルを格納している想定です webView.loadUrl("file:///android_asset/test.html")
CSSを適用させるにはページ読み込み完了したらCSSファイルを読み込む処理を行います
CSSはHTMLと同様にassetsフォルダに置いているという条件付きです。またonPageFinished
で行います
private fun injectCSS() { try { val inputStream = assets.open("style.css") // CSSファイル名を指定 val buffer = ByteArray(inputStream.available()) inputStream.read(buffer) inputStream.close() val encoded = Base64.encodeToString(buffer , Base64.NO_WRAP) webframe.loadUrl( "javascript:(function() {" + "var parent = document.getElementsByTagName('head').item(0);" + "var style = document.createElement('style');" + "style.type = 'text/css';" + // Tell the browser to BASE64-decode the string into your script !!! "style.innerHTML = window.atob('" + encoded + "');" + "parent.appendChild(style)" + "})()" ) } catch (e: Exception) { e.printStackTrace() } }
Javascriptとの連携
Javascriptからアプリの処理を実行したり、アプリからJavaScriptのメソッドを実行したい場合があると思います
Javascriptとの連携はWebChromeClient
を使います
WebChromeClientはブラウザー周辺のchromeの要素を変更するイベントに反応するためのイベントインターフェイスです。 JavaScript、favicons、進行状況と現在のページのタイトルの更新などが含まれます
Javascriptからアプリの処理を実行する
例えば、Javascriptでボタンのタップアクションをアプリ側で受け取りアプリで処理を行う場合です
HTMLは次の例を使用します
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> </head> <body> <script type="text/javascript"> function showMessage() { alert("showMwssage"); } function setMessage(message) { document.getElementById("text").innerHTML = message; } </script> <input type="button" value="Button" onClick="showMessage();" /> <p id="text"></p> </body> </html>
HTMLで設定されるfunction showMessage()
でalertを設定して次のようにonJsAlert
でメッセージを取得できます
webView.webChromeClient = object :WebChromeClient() { override fun onJsAlert( view: WebView?, url: String?, message: String?, result: JsResult? ): Boolean { if (!message.isNullOrEmpty()) { Log.d("jsAlertMessage", message) // showMwssageが取得される } return true } }
アラートメッセージを取得したら処理が行われるようにしたらJavascriptからアプリの処理を実行したことになります
アプリからJavaScriptのメソッドを実行する
今度は先程と逆でアプリからJavascriptを実行する方法です
次のようにevaluateJavascript
でJavascriptの関数を呼び出します
val message = "TEST" webView.evaluateJavascript("setMessage(`${message}`);")
注意点
オフラインなどでWebViewが表示できない時はデフォルトのエラー画面ではなく、エラーメッセージを表示させる・エラーイラストを表示させるなどの対応を行うのが望ましいです
そうしないとリリース時にNGを受けることがあります
iOSではNGを受けないかもしれないですが、同じ対応を行うのが望ましいです
参照
https://android.camposha.info/ja/android-webview/#gsc.tab=0android.camposha.info