| Scott Main | 65e62f4 | 2010-09-20 12:46:34 -0700 | [diff] [blame] | 1 | page.title=Building Web Apps in WebView |
| 2 | @jd:body |
| 3 | |
| 4 | <div id="qv-wrapper"> |
| 5 | <div id="qv"> |
| 6 | <h2>Quickview</h2> |
| 7 | <ul> |
| 8 | <li>Use {@link android.webkit.WebView} to display web pages in your Android application |
| 9 | layout</li> |
| 10 | <li>You can create interfaces from your JavaScript to your client-side Android code</li> |
| 11 | </ul> |
| 12 | |
| 13 | <h2>In this document</h2> |
| 14 | <ol> |
| 15 | <li><a href="#AddingWebView">Adding a WebView to Your Application</a></li> |
| 16 | <li><a href="#UsingJavaScript">Using JavaScript in WebView</a> |
| 17 | <ol> |
| 18 | <li><a href="#EnablingJavaScript">Enabling JavaScript</a></li> |
| 19 | <li><a href="#BindingJavaScript">Binding JavaScript code to Android code</a></li> |
| 20 | </ol> |
| 21 | </li> |
| 22 | <li><a href="#HandlingNavigation">Handling Page Navigation</a> |
| 23 | <ol> |
| 24 | <li><a href="#NavigatingHistory">Navigating web page history</a></li> |
| 25 | </ol> |
| 26 | </li> |
| 27 | </ol> |
| 28 | |
| 29 | <h2>Key classes</h2> |
| 30 | <ol> |
| 31 | <li>{@link android.webkit.WebView}</li> |
| 32 | <li>{@link android.webkit.WebSettings}</li> |
| 33 | <li>{@link android.webkit.WebViewClient}</li> |
| 34 | </ol> |
| 35 | |
| 36 | <h2>Related tutorials</h2> |
| 37 | <ol> |
| 38 | <li><a href="{@docRoot}resources/tutorials/views/hello-webview.html">Web View</a></li> |
| 39 | </ol> |
| 40 | |
| 41 | </div> |
| 42 | </div> |
| 43 | |
| 44 | <p>If you want to deliver a web application (or just a web page) as a part of a client application, |
| 45 | you can do it using {@link android.webkit.WebView}. The {@link android.webkit.WebView} class is an |
| 46 | extension of Android's {@link android.view.View} class that allows you to display web pages as a |
| 47 | part of your activity layout. It does <em>not</em> include any features of a fully developed web |
| 48 | browser, such as navigation controls or an address bar. All that {@link android.webkit.WebView} |
| 49 | does, by default, is show a web page.</p> |
| 50 | |
| 51 | <p>A common scenario in which using {@link android.webkit.WebView} is helpful is when you want to |
| 52 | provide information in your application that you might need to update, such as an end-user agreement |
| 53 | or a user guide. Within your Android application, you can create an {@link android.app.Activity} |
| 54 | that contains a {@link android.webkit.WebView}, then use that to display your document that's |
| 55 | hosted online.</p> |
| 56 | |
| 57 | <p>Another scenario in which {@link android.webkit.WebView} can help is if your application provides |
| 58 | data to the user that |
| 59 | always requires an Internet connection to retrieve data, such as email. In this case, you might |
| 60 | find that it's easier to build a {@link android.webkit.WebView} in your Android application that |
| 61 | shows a web page with all |
| 62 | the user data, rather than performing a network request, then parsing the data and rendering it in |
| 63 | an Android layout. Instead, you can design a web page that's tailored for Android devices |
| 64 | and then implement a {@link android.webkit.WebView} in your Android application that loads the web |
| 65 | page.</p> |
| 66 | |
| 67 | <p>This document shows you how to get started with {@link android.webkit.WebView} and how to do some |
| 68 | additional things, such as handle page navigation and bind JavaScript from your web page to |
| 69 | client-side code in your Android application.</p> |
| 70 | |
| 71 | |
| 72 | |
| 73 | <h2 id="AddingWebView">Adding a WebView to Your Application</h2> |
| 74 | |
| 75 | <p>To add a {@link android.webkit.WebView} to your Application, simply include the {@code |
| 76 | <WebView>} element in your activity layout. For example, here's a layout file in which the |
| 77 | {@link android.webkit.WebView} fills the screen:</p> |
| 78 | |
| 79 | <pre> |
| 80 | <?xml version="1.0" encoding="utf-8"?> |
| 81 | <WebView xmlns:android="http://schemas.android.com/apk/res/android" |
| 82 | android:id="@+id/webview" |
| 83 | android:layout_width="fill_parent" |
| 84 | android:layout_height="fill_parent" |
| 85 | /> |
| 86 | </pre> |
| 87 | |
| 88 | <p>To load a web page in the {@link android.webkit.WebView}, use {@link |
| 89 | android.webkit.WebView#loadUrl(String) loadUrl()}. For example:</p> |
| 90 | |
| 91 | <pre> |
| 92 | WebView myWebView = (WebView) findViewById(R.id.webview); |
| 93 | myWebView.loadUrl("http://www.example.com"); |
| 94 | </pre> |
| 95 | |
| 96 | <p>Before this will work, however, your application must have access to the Internet. To get |
| 97 | Internet access, request the {@link android.Manifest.permission#INTERNET} permission in your |
| 98 | manifest file. For example:</p> |
| 99 | |
| 100 | <pre> |
| 101 | <manifest ... > |
| 102 | <uses-permission android:name="android.permission.INTERNET" /> |
| 103 | ... |
| 104 | </manifest> |
| 105 | </pre> |
| 106 | |
| 107 | <p>That's all you need for a basic {@link android.webkit.WebView} that displays a web page.</p> |
| 108 | |
| 109 | |
| 110 | |
| 111 | |
| 112 | <h2 id="UsingJavaScript">Using JavaScript in WebView</h2> |
| 113 | |
| 114 | <p>If the web page you plan to load in your {@link android.webkit.WebView} use JavaScript, you |
| 115 | must enable JavaScript for your {@link android.webkit.WebView}. Once JavaScript is enabled, you can |
| 116 | also create interfaces between your application code and your JavaScript code.</p> |
| 117 | |
| 118 | |
| 119 | <h3 id="EnablingJavaScript">Enabling JavaScript</h3> |
| 120 | |
| 121 | <p>JavaScript is disabled in a {@link android.webkit.WebView} by default. You can enable it |
| 122 | through the {@link |
| 123 | android.webkit.WebSettings} attached to your {@link android.webkit.WebView}. You can retrieve {@link |
| 124 | android.webkit.WebSettings} with {@link android.webkit.WebView#getSettings()}, then enable |
| 125 | JavaScript with {@link android.webkit.WebSettings#setJavaScriptEnabled(boolean) |
| 126 | setJavaScriptEnabled()}.</p> |
| 127 | |
| 128 | <p>For example:</p> |
| 129 | |
| 130 | <pre> |
| 131 | WebView myWebView = (WebView) findViewById(R.id.webview); |
| 132 | WebSettings webSettings = myWebView.getSettings(); |
| 133 | webSettings.setJavaScriptEnabled(true); |
| 134 | </pre> |
| 135 | |
| 136 | <p>{@link android.webkit.WebSettings} provides access to a variety of other settings that you might |
| 137 | find useful. For example, if you're developing a web application |
| 138 | that's designed specifically for the {@link android.webkit.WebView} in your Android application, |
| 139 | then you can define a |
| 140 | custom user agent string with {@link android.webkit.WebSettings#setUserAgentString(String) |
| 141 | setUserAgentString()}, then query the custom user agent in your web page to verify that the |
| 142 | client requesting your web page is actually your Android application.</p> |
| 143 | |
| 144 | from your Android SDK {@code tools/} directory |
| 145 | <h3 id="BindingJavaScript">Binding JavaScript code to Android code</h3> |
| 146 | |
| 147 | <p>When developing a web application that's designed specifically for the {@link |
| 148 | android.webkit.WebView} in your Android |
| 149 | application, you can create interfaces between your JavaScript code and client-side Android code. |
| 150 | For example, your JavaScript code can call a method in your Android code to display a {@link |
| 151 | android.app.Dialog}, instead of using JavaScript's {@code alert()} function.</p> |
| 152 | |
| 153 | <p>To bind a new interface between your JavaScript and Android code, call {@link |
| 154 | android.webkit.WebView#addJavascriptInterface(Object,String) addJavascriptInterface()}, passing it |
| 155 | a class instance to bind to your JavaScript and an interface name that your JavaScript can call to |
| 156 | access the class.</p> |
| 157 | |
| 158 | <p>For example, you can include the following class in your Android application:</p> |
| 159 | |
| 160 | <pre> |
| 161 | public class JavaScriptInterface { |
| 162 | Context mContext; |
| 163 | |
| 164 | /** Instantiate the interface and set the context */ |
| 165 | JavaScriptInterface(Context c) { |
| 166 | mContext = c; |
| 167 | } |
| 168 | |
| 169 | /** Show a toast from the web page */ |
| 170 | public void showToast(String toast) { |
| 171 | Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show(); |
| 172 | } |
| 173 | } |
| 174 | </pre> |
| 175 | |
| 176 | <p>In this example, the {@code JavaScriptInterface} class allows the web page to create a {@link |
| 177 | android.widget.Toast} message, using the {@code showToast()} method.</p> |
| 178 | |
| 179 | <p>You can bind this class to the JavaScript that runs in your {@link android.webkit.WebView} with |
| 180 | {@link android.webkit.WebView#addJavascriptInterface(Object,String) addJavascriptInterface()} and |
| 181 | name the interface {@code Android}. For example:</p> |
| 182 | |
| 183 | <pre> |
| 184 | WebView webView = (WebView) findViewById(R.id.webview); |
| 185 | webView.addJavascriptInterface(new JavaScriptInterface(this), "Android"); |
| 186 | </pre> |
| 187 | |
| 188 | <p>This creates an interface called {@code Android} for JavaScript running in the {@link |
| 189 | android.webkit.WebView}. At this point, your web application has access to the {@code |
| 190 | JavaScriptInterface} class. For example, here's some HTML and JavaScript that creates a toast |
| 191 | message using the new interface when the user clicks a button:</p> |
| 192 | |
| 193 | <pre> |
| 194 | <input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> |
| 195 | |
| 196 | <script type="text/javascript"> |
| 197 | function showAndroidToast(toast) { |
| 198 | Android.showToast(toast); |
| 199 | } |
| 200 | </script> |
| 201 | </pre> |
| 202 | |
| 203 | <p>There's no need to initialize the {@code Android} interface from JavaScript. The {@link |
| 204 | android.webkit.WebView} automatically makes it |
| 205 | available to your web page. So, at the click of the button, the {@code showAndroidToast()} |
| 206 | function uses the {@code Android} interface to call the {@code JavaScriptInterface.showToast()} |
| 207 | method.</p> |
| 208 | |
| 209 | <p class="note"><strong>Note:</strong> The object that is bound to your JavaScript runs in |
| 210 | another thread and not in the thread in which it was constructed.</p> |
| 211 | |
| 212 | <p class="caution"><strong>Caution:</strong> Using {@link |
| 213 | android.webkit.WebView#addJavascriptInterface(Object,String) addJavascriptInterface()} allows |
| 214 | JavaScript to control your Android application. This can be a very useful feature or a dangerous |
| 215 | security issue. When the HTML in the {@link android.webkit.WebView} is untrustworthy (for example, |
| 216 | part or all of the HTML |
| 217 | is provided by an unknown person or process), then an attacker can include HTML that executes |
| 218 | your client-side code and possibly any code of the attacker's choosing. As such, you should not use |
| 219 | {@link android.webkit.WebView#addJavascriptInterface(Object,String) addJavascriptInterface()} unless |
| 220 | you wrote all of the HTML and JavaScript that appears in your {@link android.webkit.WebView}. You |
| 221 | should also not allow the user to |
| 222 | navigate to other web pages that are not your own, within your {@link android.webkit.WebView} |
| 223 | (instead, allow the user's |
| 224 | default browser application to open foreign links—by default, the user's web browser |
| 225 | opens all URL links, so be careful only if you handle page navigation as described in the |
| 226 | following section).</p> |
| 227 | |
| 228 | |
| 229 | |
| 230 | |
| 231 | <h2 id="HandlingNavigation">Handling Page Navigation</h2> |
| 232 | |
| 233 | <p>When the user clicks a link from a web page in your {@link android.webkit.WebView}, the default |
| 234 | behavior is |
| 235 | for Android to launch an application that handles URLs. Usually, the default web browser opens and |
| 236 | loads the destination URL. However, you can override this behavior for your {@link |
| 237 | android.webkit.WebView}, |
| 238 | so links open within your {@link android.webkit.WebView}. You can then allow the user to navigate |
| 239 | backward and forward through their web page history that's maintained by your {@link |
| 240 | android.webkit.WebView}.</p> |
| 241 | |
| 242 | <p>To open links clicked by the user, simply provide a {@link |
| 243 | android.webkit.WebViewClient} for your {@link android.webkit.WebView}, using {@link |
| 244 | android.webkit.WebView#setWebViewClient(WebViewClient) setWebViewClient()}. For example:</p> |
| 245 | |
| 246 | <pre> |
| 247 | WebView myWebView = (WebView) findViewById(R.id.webview); |
| 248 | myWebView.{@link android.webkit.WebView#setWebViewClient(WebViewClient) setWebViewClient}(new WebViewClient()); |
| 249 | </pre> |
| 250 | |
| 251 | <p>That's it. Now all links the user clicks load in your {@link android.webkit.WebView}.</p> |
| 252 | |
| 253 | <p>If you want more control over where a clicked link load, create your own {@link |
| 254 | android.webkit.WebViewClient} that overrides the {@link |
| 255 | android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String) |
| 256 | shouldOverrideUrlLoading()} method. For example:</p> |
| 257 | |
| 258 | <pre> |
| 259 | private class MyWebViewClient extends WebViewClient { |
| 260 | @Override |
| 261 | public boolean {@link android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String) shouldOverrideUrlLoading}(WebView view, String url) { |
| 262 | if (Uri.parse(url).getHost().equals("www.example.com")) { |
| 263 | // This is my web site, so do not override; let my WebView load the page |
| 264 | return false; |
| 265 | } |
| 266 | // Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs |
| 267 | Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); |
| 268 | startActivity(intent); |
| 269 | return true; |
| 270 | } |
| 271 | } |
| 272 | </pre> |
| 273 | |
| 274 | <p>Then create an instance of this new {@link android.webkit.WebViewClient} for the {@link |
| 275 | android.webkit.WebView}:</p> |
| 276 | |
| 277 | <pre> |
| 278 | WebView myWebView = (WebView) findViewById(R.id.webview); |
| 279 | myWebView.{@link android.webkit.WebView#setWebViewClient(WebViewClient) setWebViewClient}(new MyWebViewClient()); |
| 280 | </pre> |
| 281 | |
| 282 | <p>Now when the user clicks a link, the system calls |
| 283 | {@link android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String) |
| 284 | shouldOverrideUrlLoading()}, which checks whether the URL host matches a specific domain (as defined |
| 285 | above). If it does match, then the method returns false in order to <em>not</em> override the URL |
| 286 | loading (it allows the {@link android.webkit.WebView} to load the URL as usual). If the URL host |
| 287 | does not match, then an {@link android.content.Intent} is created to |
| 288 | launch the default Activity for handling URLs (which resolves to the user's default web |
| 289 | browser).</p> |
| 290 | |
| 291 | |
| 292 | |
| 293 | |
| 294 | <h3 id="NavigatingHistory">Navigating web page history</h3> |
| 295 | |
| 296 | <p>When your {@link android.webkit.WebView} overrides URL loading, it automatically accumulates a |
| 297 | history of visited web |
| 298 | pages. You can navigate backward and forward through the history with {@link |
| 299 | android.webkit.WebView#goBack()} and {@link android.webkit.WebView#goForward()}.</p> |
| 300 | |
| 301 | <p>For example, here's how your {@link android.app.Activity} can use the device BACK key to navigate |
| 302 | backward:</p> |
| 303 | |
| 304 | <pre> |
| 305 | @Override |
| 306 | public boolean {@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown}(int keyCode, KeyEvent event) { |
| 307 | // Check if the key event was the BACK key and if there's history |
| 308 | if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.{@link android.webkit.WebView#canGoBack() canGoBack}() { |
| 309 | myWebView.{@link android.webkit.WebView#goBack() goBack}(); |
| 310 | return true; |
| 311 | } |
| 312 | // If it wasn't the BACK key or there's no web page history, bubble up to the default |
| 313 | // system behavior (probably exit the activity) |
| 314 | return super.onKeyDown(keyCode, event); |
| 315 | } |
| 316 | </pre> |
| 317 | |
| 318 | <p>The {@link android.webkit.WebView#canGoBack()} method returns |
| 319 | true if there is actually web page history for the user to visit. Likewise, you can use {@link |
| 320 | android.webkit.WebView#canGoForward()} to check whether there is a forward history. If you don't |
| 321 | perform this check, then once the user reaches the end of the history, {@link |
| 322 | android.webkit.WebView#goBack()} or {@link android.webkit.WebView#goForward()} does nothing.</p> |
| 323 | |
| 324 | |
| 325 | |
| 326 | |
| 327 | |
| 328 | |