ウェブ アプリケーション(またはウェブページ)をクライアント アプリケーションの一部として提供する場合は、WebView
を使用できます。WebView
クラスは、Android の View
クラスの拡張であり、アクティビティ レイアウトの一部としてウェブページを表示できます。ナビゲーション機能やアドレスバーなど、完全なウェブブラウザとしての機能は含まれません。WebView
は、デフォルトではウェブページを表示するだけです。
WebView
を使用すると便利な一般的なシナリオは、エンドユーザー契約やユーザーガイドなど、更新が必要になる可能性のある情報をアプリで提供する場合です。Android アプリ内で、WebView
を含む Activity
を作成し、これを使用してオンラインでホストされているドキュメントを表示できます。
WebView
が役に立つもう 1 つのシナリオは、取得にインターネット接続が常に必要なデータ(メールなど)をユーザーにアプリで提供する場合です。この場合、ネットワーク リクエストを行ってからデータを解析し、Android レイアウトでレンダリングするよりも、Android アプリで WebView
をビルドし、すべてのユーザーデータを含むウェブページを表示するほうが簡単な可能性があります。代わりに、Android デバイス用に調整したウェブページを設計し、ウェブページを読み込む Android アプリに WebView
を実装できます。
このドキュメントでは、WebView
の使用ガイドと、ページ ナビゲーションの処理や、ウェブページから Android アプリのクライアント側コードへの JavaScript のバインドなど、他の処理方法を示します。
アプリへの WebView の追加
WebView
をアプリに追加するには、アクティビティ レイアウトに <WebView>
要素を設定するか、onCreate()
内で WebView
として Activity ウィンドウ全体を設定します。
アクティビティ レイアウトで 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");
注: この HTML の機能には制限があります。エンコード オプションの詳細については、loadData()
と loadDataWithBaseURL()
をご覧ください。
ただし、この機能を使用するにはインターネットへのアクセスが必要です。インターネット アクセスを取得するには、マニフェスト ファイルで INTERNET
権限をリクエストしてください。次に例を示します。
<manifest ... > <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
基本的な WebView
でウェブページを表示するにあたって必要な作業は以上です。また、以下のように変更して WebView
をカスタマイズできます。
WebChromeClient
でフルスクリーン サポートを有効にする。このクラスは、WebView
でホストアプリの UI を変更する(ウィンドウの作成や終了、JavaScript ダイアログのユーザーへの送信など)権限を必要とするときにも呼び出されます。このコンテキストでのデバッグの詳細については、ウェブアプリのデバッグをご覧ください。- フォーム送信のエラーや
WebViewClient
でのナビゲーションなど、コンテンツのレンダリングに影響を与えるイベントを処理する。このサブクラスを使用して URL の読み込みを傍受することもできます。 WebSettings
を変更して JavaScript を有効にする。- JavaScript を使用して
WebView
に組み込んだ Android フレームワーク オブジェクトにアクセスする。
WebView での JavaScript の使用
WebView
で読み込む予定のウェブページで JavaScript が使用されている場合、 で 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 コードで、Android コードのメソッドを呼び出して、JavaScript の alert()
関数を使用する代わりに、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(); } }
注意: targetSdkVersion
を 17 以上に設定している場合、JavaScript で利用できるようにしたい任意のメソッドに @JavascriptInterface
アノテーションを追加する必要があります(メソッドは public にする必要もあります)。アノテーションを設定しない場合、Android 4.2 以降ではウェブページからメソッドにアクセスできません。
この例では、WebAppInterface
クラスにより、showToast()
メソッドを使用してウェブページで Toast
メッセージを作成できます。
addJavascriptInterface()
を使用して WebView
で実行する JavaScript にこのクラスをバインドし、インターフェースに Android
という名前を付けることができます。次に例を示します。
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()
メソッドを呼び出します。
注: JavaScript にバインドされたオブジェクトは、作成されたスレッドではなく、別のスレッドで実行されます。
注意: addJavascriptInterface()
を使用すると、JavaScript で Android アプリを制御できるようになります。これは非常に便利な機能ですが、危険なセキュリティ問題となる可能性があります。WebView
の HTML が信頼できない場合(HTML の一部またはすべてが不明なユーザーまたはプロセスによって提供されるなど)、攻撃者は、クライアント側のコードを実行する HTML、および攻撃者が選択した任意のコードを含めることができます。そのため、WebView
に表示されるすべての HTML および JavaScript を記述しない限り、addJavascriptInterface()
を使用しないでください。また、WebView
内では意図されている以外のウェブページにユーザーが移動できないようにする必要があります(代わりに、外部リンクはユーザーのデフォルトのブラウザ アプリケーションで開くようにします。URL リンクはすべてユーザーのウェブブラウザで開くのがデフォルトです。したがって注意が必要になるのは、次のセクションで説明するような、ページ ナビゲーションに対応する場合に限ります)。
ページ ナビゲーションの処理
ユーザーが WebView
のウェブページからリンクをクリックすると、デフォルトの動作では、Android は URL を処理するアプリを起動します。通常は、デフォルトのウェブブラウザが開いてリンク先 URL を読み込みます。ただし、この WebView
の動作をオーバーライドして、WebView
内でリンクが開くようにできます。さらに、WebView
によって維持されるウェブページ履歴にそってユーザーが前後に移動できるようにも設定できます。
注: セキュリティ上の理由から、システムのブラウザアプリはアプリとアプリケーション データを共有しません。
ユーザーがクリックしたリンクを開くには、setWebViewClient()
を使用して WebView
に WebViewClient
を提供します。次に例を示します。
Kotlin
val myWebView: WebView = findViewById(R.id.webview)
myWebView.webViewClient
= WebViewClient()
Java
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient
(MyWebViewClient);
これで完了です。これで、ユーザーがクリックしたすべてのリンクが WebView
に読み込まれます。
クリックしたリンクの読み込み先をさらに制御したい場合は、shouldOverrideUrlLoading()
メソッドをオーバーライドする独自の WebViewClient
を作成します。次に例を示します。
Kotlin
private class MyWebViewClient : WebViewClient() {
override fun shouldOverrideUrlLoading
(view: WebView?, url: String?): Boolean {
if (Uri.parse(url).host == "www.example.com") {
// This is my web site, so do not override; let my WebView load the page
return false
}
// Otherwise, the link is not for a page on my 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, String url) {
if ("www.example.com".equals(Uri.parse(url).getHost())) {
// This is my website, so do not override; let my WebView load the page
return false;
}
// Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
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 ホストが特定のドメイン(上記で定義)に一致するかどうかを確認します。一致した場合、メソッドは URL の読み込みをオーバーライドしないように false を返します(WebView
が通常どおり URL を読み込むことができるようにします)。URL ホストが一致しない場合、Intent
が作成され、URL 処理用のデフォルトのアクティビティが起動されます(このアクティビティは、ユーザーのデフォルトのウェブブラウザに解決されます)。
ウェブページ履歴を操作する
WebView
が URL の読み込みをオーバーライドすると、アクセスしたウェブページの履歴が自動的に蓄積されます。履歴を前後に移動するには、goBack()
および goForward()
を使用します。
Activity
でデバイスの [戻る] ボタンを使用して後方に移動する方法は次のとおりです。
Kotlin
override funonKeyDown
(keyCode: Int, event: KeyEvent?): Boolean { // Check if the key event was the Back button and if there's history if (keyCode == KeyEvent.KEYCODE_BACK && myWebView.canGoBack
()) { myWebView.goBack() return true } // If it wasn't the Back key or there's no web page history, bubble up to the default // system behavior (probably exit the activity) return super.onKeyDown(keyCode, event) }
Java
@Override public booleanonKeyDown
(int keyCode, KeyEvent event) { // Check if the key event was the Back button and if there's history if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack
()) { myWebView.goBack
(); return true; } // If it wasn't the Back key or there's no web page history, bubble up to the default // system behavior (probably exit the activity) return super.onKeyDown(keyCode, event); } }
canGoBack()
メソッドは、ユーザーがアクセスできるウェブページ履歴がある場合に true を返します。同様に、canGoForward()
を使用して、進むことが可能な履歴があるかどうかを確認できます。このチェックを行わない場合、ユーザーが履歴の最後に到達すると、goBack()
や goForward()
は何も行いません。
デバイス設定の変更を処理する
実行時に、ユーザーがデバイスを回転させたり、インプット メソッド エディタ(IME)を閉じたりするなど、デバイス設定が変更されると、アクティビティ状態が変更されます。これらの変更により、WebView
オブジェクトのアクティビティが破棄され、新しいアクティビティが作成されます。これにより、破棄されたオブジェクトの URL を読み込む新しい WebView
オブジェクトも作成されます。アクティビティのデフォルトの動作を変更するには、マニフェストで orientation
の変更処理方法を変更できます。実行時の設定変更の処理について詳しくは、設定変更の処理をご覧ください。
ウィンドウの管理
デフォルトでは、新しいウィンドウを開くリクエストは無視されます。これは、開かれるのが JavaScript によるものでも、リンクのターゲット属性によるものでも同じです。WebChromeClient
をカスタマイズして、複数のウィンドウを開く動作をご自身で提供できます。
注意: アプリをより安全に保つには、ポップアップや新しいウィンドウが開かないようにすることをおすすめします。この動作を最も安全に実装する方法は、setSupportMultipleWindows()
に "true"
を渡しつつ、onCreateWindow()
メソッド(setSupportMultipleWindows()
が依存します)をオーバーライドしないことです。ただし、このロジックでは、target="_blank"
を使用するページをリンクで読み込むこともできなくなります。