先ほどと同じプログラムでwww.yahoo.comとwww.google.comを読み込んでみました。同じプログラムで読み込んでいるにもかかわらず、見た目が若干異なります。分かりやすいように並べてみます。
Yahoo!と比べると、Googleは<title>タグのところにページタイトルが表示され、faviconも表示されています。実は、Googleの方は自分で作成したWebViewとは別のWebブラウザが勝手に起動しているのです。
Googleのページを閉じると、本来ここに読み込むはずだった真っ白のWebViewが出てきます。
この現象はYahoo!のページでも、任意のリンクをクリックすると発生します。これは、どうしてでしょうか?答えは、連載第3回の「ブラウザや地図、ストリートビューの基、Intentとは?」で紹介したIntentにありました。
Googleの場合は、接続元IPアドレスから各国のGoogleに適切にリダイレクトされるようになっています。新しいURLにアクセスする必要が出たWebViewは、そのURLを自分で表示せず、ActivityManagerによってIntentを発行し、発行されるIntentはWebページを表示させたいものであるため、結果として「Webブラウザが起動する」ということになります。リンクをクリックした場合も同様です。
下記は、Googleにアクセスした際のログです。Intentが2回発行されているのが分かりますね。
08-10 22:26:32.269: INFO/ActivityManager(570): Starting activity: Intent { comp={com.example.android.web/com.example.android.web.Example01} (has extras) } 08-10 22:26:33.593: DEBUG/InetAddress(720): www.google.com: 66.249.89.99 (family 2, proto 6) 08-10 22:26:33.601: DEBUG/InetAddress(720): www.google.com: 66.249.89.147 (family 2, proto 6) 08-10 22:26:33.611: DEBUG/InetAddress(720): www.google.com: 66.249.89.104 (family 2, proto 6) 08-10 22:26:34.110: INFO/ActivityManager(570): Displayed activity com.example.android.web/.Example01: 1814 ms 08-10 22:26:35.160: INFO/ActivityManager(570): Starting activity: Intent { action=android.intent.action.VIEW categories={android.intent.category.BROWSABLE} data=http://www.google.cn/m comp={com.android.browser/com.android.browser.BrowserActivity} (has extras) } 08-10 22:26:35.239: DEBUG/PhoneWindow(720): couldn't save which view has focus because the focused view android.webkit.WebView@435cc958 has no id. 08-10 22:26:37.000: WARN/ActivityManager(570): Unable to start service Intent { comp={com.google.android.googleapps/com.google.android.googleapps.GoogleLoginService} }: not found 08-10 22:26:38.019: INFO/ActivityManager(570): Displayed activity com.android.browser/.BrowserActivity: 2853 ms 08-10 22:26:44.711: DEBUG/dalvikvm(720): GC freed 1404 objects / 128504 bytes in 306ms 08-10 22:26:44.839: DEBUG/webviewglue(720): nativeDestroy view: 0x207d70 08-10 22:26:45.159: DEBUG/InetAddress(742): www.google.cn: 203.208.37.104 (family 2, proto 6) 08-10 22:26:45.179: DEBUG/InetAddress(742): www.google.cn: 203.208.37.99 (family 2, proto 6) 08-10 22:26:45.220: DEBUG/InetAddress(742): www.google.cn: 203.208.37.160 (family 2, proto 6) 08-10 22:26:45.520: DEBUG/InetAddress(742): www.google.com: 66.249.89.104 (family 2, proto 6) 08-10 22:26:45.554: DEBUG/InetAddress(742): www.google.com: 66.249.89.99 (family 2, proto 6) 08-10 22:26:45.554: DEBUG/InetAddress(742): www.google.com: 66.249.89.147 (family 2, proto 6)
Webブラウザを起動するのではなく、アプリ内のWebViewでリンク先も表示させたい場合は、「WebViewClient」というクラスを使用します。
WebView webView = new WebView(this); webView.setWebViewClient(new WebViewClient()); webView.loadUrl(“http://www.yahoo.com”); setContentView(webView, new LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.FILL_PARENT));
このように、WebView#setWebViewClient(WebViewClient)を呼び出せばWebブラウザは起動されなくなり、WebView自身がWebを表示するためのクライアントになります。WebViewClientについては、後ほどもう少し詳しく解説します。
アプリ内でWebブラウザを使用できるのなら、任意のURLを自由に入力できるようにしたいですね。
やっていることは、EditTextでENTERが押されたら、入力されている文字列を取り出しWebViewに渡しているだけです。この画面のレイアウトはXMLで行っています。WebViewはAndroid Layout Editorでは編集できません。
左側の「Views」に、WebViewが含まれていません。右側のレイアウト画面にWebViewがあるのは、XMLを直接編集したためです。ビューのサイズは、レイアウト画面に反映されるので、割り切って使うのなら問題ありません。
アドレス入力に加え、進むボタンと戻るボタンを付ければ、立派なWebブラウザです。
WebViewには、以下の履歴管理用のメソッドが用意されています。
メソッド | 説明 |
---|---|
boolean canGoBack( ) | 戻れるかどうか判定する |
void goBack( ) | 戻る |
boolean canGoForward( ) | 進めるかどうか判定する |
void goForward( ) | 進む |
boolean canGoBackOrForward(int steps) | 指定したステップ移動できるか判定する |
void goBackOrForward(int steps) | 指定したステップ移動する |
表1 WebViewの履歴管理用メソッド |
canGoBack()とcanGoForward()を使用して、ボタンの活性/非活性をコントロールしています。この活性/非活性をどのタイミングで行うかというと、前述したWebViewClientのコールバックメソッド内で行います。
ここは大事なので、ソースコードを見てみましょう。
class MyWebViewClient extends WebViewClient { @Override public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { back.setEnabled(webView.canGoBack()); forward.setEnabled(webView.canGoForward()); } @Override public void onPageFinished(WebView view, String url) { if (webView.getTitle() != null) { Example03.this.setTitle(webView.getTitle()); } } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { Example03.this.setTitle("Loading..."); back.setEnabled(webView.canGoBack()); forward.setEnabled(webView.canGoForward()); } }
WebViewClientを継承したクラスを作成し、ハンドリングしたいコールバックメソッドをオーバーライドします。今回は、以下の3つを使用しています。
メソッド | 説明 |
---|---|
void onPageStarted(…) | ページ読み込み直後に呼び出される |
void onPageFinished(…) | ページ読み込み完了後に呼び出される |
void doUpdateVisitedHistory(…) | 履歴が更新されたタイミングで呼び出される |
表2 WebViewClientのコールバックメソッド |
ページ読み込み開始時と履歴更新時に、ボタンの活性/非活性を制御しています。また、ついでにページ読み込み開始時にタイトルを「Loading……」にし、読み込み終了時にWebページのタイトルに変更しています。
このようにして、作ったクラスのインスタンスを以下のようにWebViewに設定すればOKです。
webView = (WebView)findViewById(R.id.WebView01); webView.setWebViewClient(new MyWebViewClient());
進む/戻るボタンの制御も含め、わずか80行しかありません。本当にWebViewを使うととても簡単にWebブラウザアプリができてしまいます。
次ページでは、タッチスクリーンによるモーションジェスチャーの付け方やWebViewの真骨頂であるJavaScriptとの連動の仕方を解説します。
Copyright © ITmedia, Inc. All Rights Reserved.