WebView
を使用して、ウェブ アプリケーションまたはウェブページをクライアント アプリケーションの一部として配信します。WebView
クラスは Android の View
クラスの拡張機能で、ウェブページをアクティビティ レイアウトの一部として表示できます。ナビゲーション コントロールやアドレスバーなど、完全に開発されたウェブブラウザの機能は含まれません。デフォルトでは、すべての WebView
でウェブページが表示されます。
WebView
を使用すると、エンドユーザー契約やユーザーガイドなど、更新が必要なものをアプリ内で提供できます。Android アプリ内で、WebView
を含む Activity
を作成し、それを使用してオンラインでホストされているドキュメントを表示できます。
WebView
は、メールなどのデータを取得するためにインターネット接続が必要なデータをアプリからユーザーに提供する場合にも役立ちます。この場合は、ネットワーク リクエストを実行してデータを解析し、Android レイアウトでレンダリングするよりも、すべてのユーザーデータを含むウェブページを表示する WebView
を Android アプリでビルドするほうが簡単な場合があります。代わりに、Android 搭載デバイス用にカスタマイズされたウェブページを設計し、そのウェブページを読み込む Android アプリに WebView
を実装できます。
このドキュメントでは、WebView
の使用方法、ウェブページから Android アプリのクライアント側コードに JavaScript をバインドする方法、ページ ナビゲーションを処理する方法、WebView
使用時のウィンドウを管理する方法について説明します。
以前のバージョンの Android で WebView を使用する
アプリが実行されているデバイスで最新の WebView
機能を安全に使用するには、AndroidX Webkit ライブラリを追加します。これは、以前のバージョンのプラットフォームでは使用できない android.webkit
API を使用するためにアプリに追加できる静的ライブラリです。
次のように build.gradle
ファイルに追加します。
Kotlin
dependencies { implementation("androidx.webkit:webkit:1.8.0") }
Groovy
dependencies { implementation ("androidx.webkit:webkit:1.8.0") }
詳細については、GitHub の WebView
の例をご覧ください。
アプリに WebView を追加する
アプリに WebView
を追加するには、アクティビティ レイアウトに <WebView>
要素を含めるか、onCreate()
で Activity
ウィンドウ全体を WebView
として設定します。
アクティビティ レイアウトに WebView を追加する
レイアウト内のアプリに WebView
を追加するには、アクティビティのレイアウト XML ファイルに次のコードを追加します。
<WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" />
WebView
でウェブページを読み込むには、次の例に示すように loadUrl()
を使用します。
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.loadUrl("http://www.example.com")
Java
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.loadUrl("http://www.example.com");
onCreate() に WebView を追加する
代わりに、アクティビティの onCreate()
メソッドでアプリに WebView
を追加するには、次のようなロジックを使用します。
Kotlin
val myWebView = WebView(activityContext) setContentView(myWebView)
Java
WebView myWebView = new WebView(activityContext); setContentView(myWebView);
次に、ページを読み込みます。
Kotlin
myWebView.loadUrl("http://www.example.com")
Java
myWebView.loadUrl("https://www.example.com");
または、HTML 文字列から URL を読み込みます。
Kotlin
// Create an unencoded HTML string, then convert the unencoded HTML string into // bytes. Encode it with base64 and load the data. val unencodedHtml = "<html><body>'%23' is the percent code for ‘#‘ </body></html>"; val encodedHtml = Base64.encodeToString(unencodedHtml.toByteArray(), Base64.NO_PADDING) myWebView.loadData(encodedHtml, "text/html", "base64")
Java
// Create an unencoded HTML string, then convert the unencoded HTML string into // bytes. Encode it with base64 and load the data. String unencodedHtml = "<html><body>'%23' is the percent code for ‘#‘ </body></html>"; String encodedHtml = Base64.encodeToString(unencodedHtml.getBytes(), Base64.NO_PADDING); myWebView.loadData(encodedHtml, "text/html", "base64");
アプリがインターネットにアクセスできる必要があります。インターネット アクセスを取得するには、次の例に示すように、マニフェスト ファイルで INTERNET
権限をリクエストします。
<manifest ... > <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
次のいずれかの方法で WebView
をカスタマイズできます。
WebChromeClient
を使用して全画面サポートを有効にする。このクラスは、ウィンドウの作成やクローズ、ユーザーへの JavaScript ダイアログの送信など、ホストアプリの UI を変更する権限をWebView
が要求する場合にも呼び出されます。このコンテキストでのデバッグについて詳しくは、ウェブアプリをデバッグするをご覧ください。WebViewClient
を使用して、フォームの送信やナビゲーションのエラーなど、コンテンツ レンダリングに影響するイベントを処理する。このサブクラスを使用して、URL の読み込みをインターセプトすることもできます。WebSettings
を変更して JavaScript を有効にする。- JavaScript を使用して、
WebView
に挿入した Android フレームワーク オブジェクトにアクセスする。
WebView で JavaScript を使用する
WebView
で読み込むウェブページで JavaScript が使用されている場合は、WebView
で JavaScript を有効にする必要があります。JavaScript を有効にすると、アプリコードと JavaScript コードの間にインターフェースを作成できます。
JavaScript を有効にする
デフォルトでは、JavaScript は WebView
で無効になっています。有効にするには、WebView
に接続された WebSettings
を使用します。getSettings()
で WebSettings
を取得し、setJavaScriptEnabled()
で JavaScript を有効にします。
次の例をご覧ください。
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.settings.javaScriptEnabled = true
Java
WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true);
WebSettings
を使用すると、他にも役立つさまざまな設定にアクセスできます。たとえば、Android アプリの WebView
専用に設計されたウェブ アプリケーションを開発する場合、setUserAgentString()
を使用してカスタム ユーザー エージェント文字列を定義し、ウェブページでカスタム ユーザー エージェントをクエリして、ウェブページをリクエストしているクライアントが Android アプリであることを確認できます。
JavaScript コードを Android コードにバインドする
Android アプリの WebView
専用に設計されたウェブ アプリケーションを開発する場合、JavaScript コードとクライアント側 Android コードの間にインターフェースを作成できます。たとえば、JavaScript の alert()
関数を使用する代わりに、Android コード内でメソッドを呼び出して Dialog
を表示できます。
JavaScript と Android コードの間に新しいインターフェースをバインドするには、addJavascriptInterface()
を呼び出して、JavaScript にバインドするクラス インスタンスと、JavaScript がクラスにアクセスするために呼び出すことができるインターフェース名を渡します。
例として、Android アプリに次のクラスを含めることができます。
Kotlin
/** Instantiate the interface and set the context. */ class WebAppInterface(private val mContext: Context) { /** Show a toast from the web page. */ @JavascriptInterface fun showToast(toast: String) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show() } }
Java
public class WebAppInterface { Context mContext; /** Instantiate the interface and set the context. */ WebAppInterface(Context c) { mContext = c; } /** Show a toast from the web page. */ @JavascriptInterface public void showToast(String toast) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); } }
この例では、WebAppInterface
クラスにより、ウェブページは showToast()
メソッドを使用して Toast
メッセージを作成できます。
次の例に示すように、addJavascriptInterface()
を使用して、WebView
で実行される JavaScript にこのクラスをバインドできます。
Kotlin
val webView: WebView = findViewById(R.id.webview) webView.addJavascriptInterface(WebAppInterface(this), "Android")
Java
WebView webView = (WebView) findViewById(R.id.webview); webView.addJavascriptInterface(new WebAppInterface(this), "Android");
これにより、WebView
で実行される JavaScript 用に Android
というインターフェースが作成されます。この時点で、ウェブ アプリケーションは WebAppInterface
クラスにアクセスできます。たとえば、次の HTML と JavaScript は、ユーザーがボタンをタップしたときに新しいインターフェースを使用してトースト メッセージを作成するものです。
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> <script type="text/javascript"> function showAndroidToast(toast) { Android.showToast(toast); } </script>
JavaScript から Android
インターフェースを初期化する必要はありません。WebView
により、自動的にウェブページで使用できるようになります。ユーザーがボタンをタップすると、showAndroidToast()
関数は Android
インターフェースを使用して WebAppInterface.showToast()
メソッドを呼び出します。
ページ ナビゲーションを処理する
デフォルトでは、ユーザーが WebView
内のウェブページからリンクをタップすると、URL を処理するアプリが起動します。通常は、デフォルトのウェブブラウザが開いてリンク先 URL が読み込まれます。ただし、WebView
のこの動作をオーバーライドして、WebView
内でリンクが開くようにすることもできます。これにより、WebView
で管理されるウェブページ履歴をユーザーが前後に移動できるようになります。
ユーザーがタップしたリンクを開くには、setWebViewClient()
を使用して WebView
の WebViewClient
を指定します。ユーザーがタップしたすべてのリンクが WebView
に読み込まれます。クリックされたリンクの読み込み場所をより細かく制御するには、shouldOverrideUrlLoading()
メソッドをオーバーライドする独自の WebViewClient
を作成します。次の例では、MyWebViewClient
が Activity
の内部クラスであることを前提としています。
Kotlin
private class MyWebViewClient : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { if (Uri.parse(url).host == "www.example.com") { // This is your website, so don't override. Let your WebView load // the page. return false } // Otherwise, the link isn't for a page on your site, so launch another // Activity that handles URLs. Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply { startActivity(this) } return true } }
Java
private class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { if ("www.example.com".equals(request.getUrl().getHost())) { // This is your website, so don't override. Let your WebView load the // page. return false; } // Otherwise, the link isn't for a page on your site, so launch another // Activity that handles URLs. Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl()); startActivity(intent); return true; } }
次に、以下のとおり、WebView
用に新しい WebViewClient
のインスタンスを作成します。
Kotlin
val myWebView: WebView = findViewById(R.id.webview) myWebView.webViewClient = MyWebViewClient()
Java
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.setWebViewClient(new MyWebViewClient());
ユーザーがリンクをタップすると、shouldOverrideUrlLoading()
メソッドが呼び出されます。このメソッドは、上記の例で定義されているように、URL ホストが特定のドメインと一致するかどうかを確認します。一致する場合、メソッドは false を返し、URL の読み込みをオーバーライドしません。これにより、WebView
が通常どおり URL を読み込むことができます。URL ホストが一致しない場合は、Intent
が作成され、URL を処理するためのデフォルトの Activity
が起動し、ユーザーのデフォルトのウェブブラウザに解決されます。
カスタム URL を処理する
WebView
は、リソースをリクエストし、カスタム URL スキームを使用するリンクを解決する際に制限を適用します。たとえば、shouldOverrideUrlLoading()
や shouldInterceptRequest()
などのコールバックを実装すると、WebView
は有効な URL に対してのみコールバックを呼び出します。
たとえば、次のようなリンクの場合、WebView
は shouldOverrideUrlLoading()
メソッドを呼び出さない場合があります。
<a href="showProfile">Show Profile</a>
上記の例のような無効な URL は、WebView
で一貫性のない方法で処理されるため、代わりに正しい形式の URL を使用することをおすすめします。組織が管理しているドメインのカスタム スキームまたは HTTPS URL を使用できます。
上記の例のように、リンクで単純な文字列を使用する代わりに、次のようなカスタム スキームを使用できます。
<a href="example-app:showProfile">Show Profile</a>
この URL は、次のように shouldOverrideUrlLoading()
メソッドで処理できます。
Kotlin
// The URL scheme must be non-hierarchical, meaning no trailing slashes. const val APP_SCHEME = "example-app:" override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { return if (url?.startsWith(APP_SCHEME) == true) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length), "UTF-8") respondToData(urlData) true } else { false } }
Java
// The URL scheme must be non-hierarchical, meaning no trailing slashes. private static final String APP_SCHEME = "example-app:"; @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith(APP_SCHEME)) { urlData = URLDecoder.decode(url.substring(APP_SCHEME.length()), "UTF-8"); respondToData(urlData); return true; } return false; }
shouldOverrideUrlLoading()
API は、特定の URL に対するインテントを起動することを主な目的としています。実装する際は、WebView
が処理する URL に対して false
を返すようにしてください。ただし、インテントが起動することに限定されるわけではありません。起動インテントは、上記のコードサンプルのカスタム動作に置き換えることができます。
ウェブページの履歴に移動する
WebView
が URL の読み込みをオーバーライドすると、アクセスしたウェブページの履歴が自動的に蓄積されます。履歴を前後に移動するには、goBack()
と goForward()
を使用します。
たとえば、Activity
でデバイスの [戻る] ボタンを使用して戻る方法を以下に示します。
Kotlin
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { // Check whether the key event is the Back button and if there's history. if (keyCode == KeyEvent.KEYCODE_BACK && myWebView.canGoBack()) { myWebView.goBack() return true } // If it isn't the Back button or there isn't web page history, bubble up to // the default system behavior. Probably exit the activity. return super.onKeyDown(keyCode, event) }
Java
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Check whether the key event is the Back button and if there's history. if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) { myWebView.goBack(); return true; } // If it isn't the Back button or there's no web page history, bubble up to // the default system behavior. Probably exit the activity. return super.onKeyDown(keyCode, event); }
アプリで AndroidX AppCompat
1.6.0 以降を使用している場合は、前のスニペットをさらに簡素化できます。
Kotlin
onBackPressedDispatcher.addCallback { // Check whether there's history. if (myWebView.canGoBack()) { myWebView.goBack() } }
Java
onBackPressedDispatcher.addCallback { // Check whether there's history. if (myWebView.canGoBack()) { myWebView.goBack(); } }
canGoBack()
メソッドは、ユーザーがアクセスするウェブページ履歴がある場合に true を返します。同様に、canGoForward()
を使用して、転送履歴が存在するかどうかを確認できます。このチェックを行わなかった場合、ユーザーが履歴の最後に達すると、goBack()
と goForward()
は何も実行しません。
デバイス設定の変更を処理する
実行時に、ユーザーがデバイスを回転させたり、インプット メソッド エディタ(IME)を閉じたりしたときなど、デバイスの構成が変更されると、アクティビティの状態が変化します。この変更により、WebView
オブジェクトのアクティビティが破棄されて新しいアクティビティが作成されます。これにより、破棄されたオブジェクトの URL を読み込む新しい WebView
オブジェクトも作成されます。アクティビティのデフォルトの動作を変更するには、マニフェストで orientation
の変更を処理する方法を変更します。実行時に構成変更を処理する方法については、構成の変更を処理するをご覧ください。
ウィンドウの管理
デフォルトでは、新しいウィンドウを開くリクエストは無視されます。これは、オブジェクトを開くのが JavaScript で行われる場合でも、リンクのターゲット属性によって行われる場合でも同じです。WebChromeClient
をカスタマイズして、複数のウィンドウを開く独自の動作を指定できます。
アプリの安全性を保つため、ポップアップや新しいウィンドウが開かないようにすることをおすすめします。この動作を実装する最も安全な方法は、"true"
を setSupportMultipleWindows()
に渡しますが、setSupportMultipleWindows()
が依存する onCreateWindow()
メソッドをオーバーライドしないことです。このロジックにより、リンクで target="_blank"
を使用するページは読み込まれなくなります。