【Android】WebView使用時の設定とTipsまとめ
- WebViewClientを設定してロード時の処理を定義する
- WebView内ページのリダイレクトを判定する
- ユーザーエージェントを設定する
- JavaScriptを有効化し、WebView内JavaScriptとJavaを連携する
- URL別にWebView/標準ブラウザを判別する
- 端末の戻るボタンで1ページ戻る
- おまけ(goBack()で戻れない!?)
準備
WebViewを使用するため、AndroidManifestに以下のパーミッションを追加するのを忘れないように。
AndroidManifest.xml
android.permission.INTERNET
WebViewClientを設定してロード時の処理を定義する
java
//WebViewインスタンスの生成 WebView webview = new WebView(this); // WebViewClientの設定 webview.setWebViewClient(new WebViewClient() { // 新しいURLが指定されたときの処理を定義 @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // 別のActivityやアプリを起動する場合 return true; // WebView内に読み込み結果を表示する場合 return false; } // ページ読み込み開始時の処理 @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { Toast.makeText(OfferActivity.this, "読み込み開始", Toast.LENGTH_LONG).show(); } // ページ読み込み完了時の処理 @Override public void onPageFinished(WebView view, String url) { Toast.makeText(OfferActivity.this, "読み込み完了", Toast.LENGTH_LONG).show(); } // ページ読み込みエラー時の処理 @Override public void onReceivedError(WebView view, int errorCode, String description, String url) { Toast.makeText(OfferActivity.this, "通信エラー", Toast.LENGTH_LONG).show(); } });
WebView内ページのリダイレクトを判定する
java
webview.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (view.getHitTestResult().getType() > 0) { // クリック参照ページの場合 return true; } else { // リダイレクトページの場合 return false; } } });
ユーザーエージェントを設定する
java
// ユーザーエージェントの設定 webview.getSettings().setUserAgentString("YourUserAgent");
JavaScriptを有効化し、WebView内JavaScriptとJavaを連携する
■JavaScriptを有効化
java
// JS有効化 webview.getSettings().setJavaScriptEnabled(true);
■JavaScriptから呼び出されるクラスの定義
java
public class WebAppInterface { Context mContext; // コンストラクタ WebAppInterface(Context c) { mContext = c; } // JavaScriptから呼び出されるメソッド @JavascriptInterface public void showToast(String toast) { Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); } }
■JavaScriptから参照できるよう設定
java
// 第2引数はJavaScriptでセレクタとして使用する名前 webview.addJavascriptInterface(new WebAppInterface(webview), "Android");
※追記
Android4.2 (APIレベル17)以降から@JavascriptInterfaceアノテーションを付加した
publicメソッドのみ呼び出せるように変更がありました。
■表示されるHTMLファイルの設定
html
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> <script type="text/javascript"> function showAndroidToast(toast) { Android.showToast(toast); } </script>
URL別にWebView/標準ブラウザを判別する
java
@Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (Uri.parse(url).getHost().equals("www.example.com")) { // WebView内で表示する return false; } // 標準ブラウザで表示する Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; }
端末の戻るボタンで1ページ戻る
端末の戻るボタンが押されたときにWebView内で1ページ戻り、戻るページがなくなったらActivityを終了する。
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) { myWebView.goBack(); return true; } return super.onKeyDown(keyCode, event); }
おまけ(goBack()で戻れない!?)
JavaScriptと連携してWebViewのgoBack()を呼び出すと、canGoBack()の結果はtrueが返っているにも関わらずページが戻らない事象が発生。
webview.copyBackForwardList().getCurrentIndex()で調べてみるとJSから呼び出した時点でなぜかIndexが+1されている・・・
よって以下のようにすることで1ページ戻ることができた。
runOnUiThreadを使用しているのはWarning対応です。
''Warning: A WebView method was called on thread 'WebViewCoreThread'. All WebView methods must be called on the UI thread. Future versions of WebView may not support use on other threads.''
public class WebAppInterface { @JavascriptInterface public void goback() { runOnUiThread(new Runnable() { @Override public void run() { if (webview.canGoBack()) { //webview.goBack(); ←これだと戻れない webview.goBackOrForward(-2); } } }); } }
まとめ
以上の設定を踏まえたサンプル
public class MainActivity extends Activity { private final int MP = ViewGroup.LayoutParams.MATCH_PARENT; private static WebView webview; // JavaScriptから呼び出されるクラスの定義 public class WebAppInterface { @JavascriptInterface public void goback() { runOnUiThread(new Runnable() { @Override public void run() { if (webview.canGoBack()) { //webview.goBack(); ←これだと戻れない webview.goBackOrForward(-2); } } }); } } @SuppressLint("SetJavaScriptEnabled") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // WebViewのみのページ生成 LinearLayout layout = new LinearLayout(this); setContentView(layout); webview = new WebView(this); layout.addView(webview, new LinearLayout.LayoutParams(MP, MP, 1)); // WebViewClient設定 webview.setWebViewClient(new WebViewClient() { // 新しいURLが指定されたときの処理を定義 @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // ホストによってWebView内で表示するか標準ブラウザで表示するか判定する if (Uri.parse(url).getHost().equals("www.example.com")) { // WebView内で表示する return false; } // 標準ブラウザで表示する Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(intent); return true; } // ページ読み込み開始時の処理 @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { Toast.makeText(MainActivity.this, "読み込み開始", Toast.LENGTH_LONG).show(); } // ページ読み込み完了時 @Override public void onPageFinished(WebView view, String url) { Toast.makeText(MainActivity.this, "読み込み完了", Toast.LENGTH_LONG).show(); } // エラー時 @Override public void onReceivedError(WebView view, int errorCode, String description, String url) { Toast.makeText(MainActivity.this, "通信エラー", Toast.LENGTH_LONG).show(); } }); // ユーザーエージェントの設定 webview.getSettings().setUserAgentString("MyUserAgent"); // JavaScript有効化 webview.getSettings().setJavaScriptEnabled(true); // JavaScriptから参照できるよう設定(第2引数はJavaScriptでセレクタとして使用する名前) webview.addJavascriptInterface(new WebAppInterface(), "Android"); // ページの読み込み webview.loadUrl("http://example.com"); } // 戻るボタンが押されたときの処理 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) { webview.goBack(); return true; } return super.onKeyDown(keyCode, event); } }
html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>Sample</title> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <meta name="author" content="yusukekuni"> <meta name=apple-mobile-web-app-capable content=yes> <meta name=apple-mobile-web-app-status-bar-style content=black> <!-- アプリ側で定義したメソッドへのアクセス --> <script type="text/javascript"> function goback() { Android.goback(); } </script> </head> <body> <a href="#" onclick="goback()" class="btn">Back</a> </body> </html>