| page.title=Building Web Apps in WebView | |
| @jd:body | |
| <div id="qv-wrapper"> | |
| <div id="qv"> | |
| <h2>Quickview</h2> | |
| <ul> | |
| <li>Use {@link android.webkit.WebView} to display web pages in your Android application | |
| layout</li> | |
| <li>You can create interfaces from your JavaScript to your client-side Android code</li> | |
| </ul> | |
| <h2>In this document</h2> | |
| <ol> | |
| <li><a href="#AddingWebView">Adding a WebView to Your Application</a></li> | |
| <li><a href="#UsingJavaScript">Using JavaScript in WebView</a> | |
| <ol> | |
| <li><a href="#EnablingJavaScript">Enabling JavaScript</a></li> | |
| <li><a href="#BindingJavaScript">Binding JavaScript code to Android code</a></li> | |
| </ol> | |
| </li> | |
| <li><a href="#HandlingNavigation">Handling Page Navigation</a> | |
| <ol> | |
| <li><a href="#NavigatingHistory">Navigating web page history</a></li> | |
| </ol> | |
| </li> | |
| </ol> | |
| <h2>Key classes</h2> | |
| <ol> | |
| <li>{@link android.webkit.WebView}</li> | |
| <li>{@link android.webkit.WebSettings}</li> | |
| <li>{@link android.webkit.WebViewClient}</li> | |
| </ol> | |
| </div> | |
| </div> | |
| <p>If you want to deliver a web application (or just a web page) as a part of a client application, | |
| you can do it using {@link android.webkit.WebView}. The {@link android.webkit.WebView} class is an | |
| extension of Android's {@link android.view.View} class that allows you to display web pages as a | |
| part of your activity layout. It does <em>not</em> include any features of a fully developed web | |
| browser, such as navigation controls or an address bar. All that {@link android.webkit.WebView} | |
| does, by default, is show a web page.</p> | |
| <p>A common scenario in which using {@link android.webkit.WebView} is helpful is when you want to | |
| provide information in your application that you might need to update, such as an end-user agreement | |
| or a user guide. Within your Android application, you can create an {@link android.app.Activity} | |
| that contains a {@link android.webkit.WebView}, then use that to display your document that's | |
| hosted online.</p> | |
| <p>Another scenario in which {@link android.webkit.WebView} can help is if your application provides | |
| data to the user that | |
| always requires an Internet connection to retrieve data, such as email. In this case, you might | |
| find that it's easier to build a {@link android.webkit.WebView} in your Android application that | |
| shows a web page with all | |
| the user data, rather than performing a network request, then parsing the data and rendering it in | |
| an Android layout. Instead, you can design a web page that's tailored for Android devices | |
| and then implement a {@link android.webkit.WebView} in your Android application that loads the web | |
| page.</p> | |
| <p>This document shows you how to get started with {@link android.webkit.WebView} and how to do some | |
| additional things, such as handle page navigation and bind JavaScript from your web page to | |
| client-side code in your Android application.</p> | |
| <h2 id="AddingWebView">Adding a WebView to Your Application</h2> | |
| <p>To add a {@link android.webkit.WebView} to your Application, simply include the {@code | |
| <WebView>} element in your activity layout. For example, here's a layout file in which the | |
| {@link android.webkit.WebView} fills the screen:</p> | |
| <pre> | |
| <?xml version="1.0" encoding="utf-8"?> | |
| <WebView xmlns:android="http://schemas.android.com/apk/res/android" | |
| android:id="@+id/webview" | |
| android:layout_width="fill_parent" | |
| android:layout_height="fill_parent" | |
| /> | |
| </pre> | |
| <p>To load a web page in the {@link android.webkit.WebView}, use {@link | |
| android.webkit.WebView#loadUrl(String) loadUrl()}. For example:</p> | |
| <pre> | |
| WebView myWebView = (WebView) findViewById(R.id.webview); | |
| myWebView.loadUrl("http://www.example.com"); | |
| </pre> | |
| <p>Before this will work, however, your application must have access to the Internet. To get | |
| Internet access, request the {@link android.Manifest.permission#INTERNET} permission in your | |
| manifest file. For example:</p> | |
| <pre> | |
| <manifest ... > | |
| <uses-permission android:name="android.permission.INTERNET" /> | |
| ... | |
| </manifest> | |
| </pre> | |
| <p>That's all you need for a basic {@link android.webkit.WebView} that displays a web page.</p> | |
| <h2 id="UsingJavaScript">Using JavaScript in WebView</h2> | |
| <p>If the web page you plan to load in your {@link android.webkit.WebView} use JavaScript, you | |
| must enable JavaScript for your {@link android.webkit.WebView}. Once JavaScript is enabled, you can | |
| also create interfaces between your application code and your JavaScript code.</p> | |
| <h3 id="EnablingJavaScript">Enabling JavaScript</h3> | |
| <p>JavaScript is disabled in a {@link android.webkit.WebView} by default. You can enable it | |
| through the {@link | |
| android.webkit.WebSettings} attached to your {@link android.webkit.WebView}. You can retrieve {@link | |
| android.webkit.WebSettings} with {@link android.webkit.WebView#getSettings()}, then enable | |
| JavaScript with {@link android.webkit.WebSettings#setJavaScriptEnabled(boolean) | |
| setJavaScriptEnabled()}.</p> | |
| <p>For example:</p> | |
| <pre> | |
| WebView myWebView = (WebView) findViewById(R.id.webview); | |
| WebSettings webSettings = myWebView.getSettings(); | |
| webSettings.setJavaScriptEnabled(true); | |
| </pre> | |
| <p>{@link android.webkit.WebSettings} provides access to a variety of other settings that you might | |
| find useful. For example, if you're developing a web application | |
| that's designed specifically for the {@link android.webkit.WebView} in your Android application, | |
| then you can define a | |
| custom user agent string with {@link android.webkit.WebSettings#setUserAgentString(String) | |
| setUserAgentString()}, then query the custom user agent in your web page to verify that the | |
| client requesting your web page is actually your Android application.</p> | |
| from your Android SDK {@code tools/} directory | |
| <h3 id="BindingJavaScript">Binding JavaScript code to Android code</h3> | |
| <p>When developing a web application that's designed specifically for the {@link | |
| android.webkit.WebView} in your Android | |
| application, you can create interfaces between your JavaScript code and client-side Android code. | |
| For example, your JavaScript code can call a method in your Android code to display a {@link | |
| android.app.Dialog}, instead of using JavaScript's {@code alert()} function.</p> | |
| <p>To bind a new interface between your JavaScript and Android code, call {@link | |
| android.webkit.WebView#addJavascriptInterface(Object,String) addJavascriptInterface()}, passing it | |
| a class instance to bind to your JavaScript and an interface name that your JavaScript can call to | |
| access the class.</p> | |
| <p>For example, you can include the following class in your Android application:</p> | |
| <pre> | |
| 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(); | |
| } | |
| } | |
| </pre> | |
| <p class="caution"><strong>Caution:</strong> If you've set your <a | |
| href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a> | |
| to 17 or higher, <strong>you | |
| must add the {@code @JavascriptInterface} annotation</strong> to any method that you want | |
| available to your JavaScript (the method must also be public). If you do not provide the | |
| annotation, the method is not accessible by your web page when running on Android 4.2 or | |
| higher.</p> | |
| <p>In this example, the {@code WebAppInterface} class allows the web page to create a {@link | |
| android.widget.Toast} message, using the {@code showToast()} method.</p> | |
| <p>You can bind this class to the JavaScript that runs in your {@link android.webkit.WebView} with | |
| {@link android.webkit.WebView#addJavascriptInterface(Object,String) addJavascriptInterface()} and | |
| name the interface {@code Android}. For example:</p> | |
| <pre> | |
| WebView webView = (WebView) findViewById(R.id.webview); | |
| webView.addJavascriptInterface(new WebAppInterface(this), "Android"); | |
| </pre> | |
| <p>This creates an interface called {@code Android} for JavaScript running in the {@link | |
| android.webkit.WebView}. At this point, your web application has access to the {@code | |
| WebAppInterface} class. For example, here's some HTML and JavaScript that creates a toast | |
| message using the new interface when the user clicks a button:</p> | |
| <pre> | |
| <input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> | |
| <script type="text/javascript"> | |
| function showAndroidToast(toast) { | |
| Android.showToast(toast); | |
| } | |
| </script> | |
| </pre> | |
| <p>There's no need to initialize the {@code Android} interface from JavaScript. The {@link | |
| android.webkit.WebView} automatically makes it | |
| available to your web page. So, at the click of the button, the {@code showAndroidToast()} | |
| function uses the {@code Android} interface to call the {@code WebAppInterface.showToast()} | |
| method.</p> | |
| <p class="note"><strong>Note:</strong> The object that is bound to your JavaScript runs in | |
| another thread and not in the thread in which it was constructed.</p> | |
| <p class="caution"><strong>Caution:</strong> Using {@link | |
| android.webkit.WebView#addJavascriptInterface(Object,String) addJavascriptInterface()} allows | |
| JavaScript to control your Android application. This can be a very useful feature or a dangerous | |
| security issue. When the HTML in the {@link android.webkit.WebView} is untrustworthy (for example, | |
| part or all of the HTML | |
| is provided by an unknown person or process), then an attacker can include HTML that executes | |
| your client-side code and possibly any code of the attacker's choosing. As such, you should not use | |
| {@link android.webkit.WebView#addJavascriptInterface(Object,String) addJavascriptInterface()} unless | |
| you wrote all of the HTML and JavaScript that appears in your {@link android.webkit.WebView}. You | |
| should also not allow the user to | |
| navigate to other web pages that are not your own, within your {@link android.webkit.WebView} | |
| (instead, allow the user's | |
| default browser application to open foreign links—by default, the user's web browser | |
| opens all URL links, so be careful only if you handle page navigation as described in the | |
| following section).</p> | |
| <h2 id="HandlingNavigation">Handling Page Navigation</h2> | |
| <p>When the user clicks a link from a web page in your {@link android.webkit.WebView}, the default | |
| behavior is | |
| for Android to launch an application that handles URLs. Usually, the default web browser opens and | |
| loads the destination URL. However, you can override this behavior for your {@link | |
| android.webkit.WebView}, | |
| so links open within your {@link android.webkit.WebView}. You can then allow the user to navigate | |
| backward and forward through their web page history that's maintained by your {@link | |
| android.webkit.WebView}.</p> | |
| <p>To open links clicked by the user, simply provide a {@link | |
| android.webkit.WebViewClient} for your {@link android.webkit.WebView}, using {@link | |
| android.webkit.WebView#setWebViewClient(WebViewClient) setWebViewClient()}. For example:</p> | |
| <pre> | |
| WebView myWebView = (WebView) findViewById(R.id.webview); | |
| myWebView.{@link android.webkit.WebView#setWebViewClient(WebViewClient) setWebViewClient}(new WebViewClient()); | |
| </pre> | |
| <p>That's it. Now all links the user clicks load in your {@link android.webkit.WebView}.</p> | |
| <p>If you want more control over where a clicked link load, create your own {@link | |
| android.webkit.WebViewClient} that overrides the {@link | |
| android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String) | |
| shouldOverrideUrlLoading()} method. For example:</p> | |
| <pre> | |
| private class MyWebViewClient extends WebViewClient { | |
| @Override | |
| public boolean {@link android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String) shouldOverrideUrlLoading}(WebView view, String url) { | |
| if (Uri.parse(url).getHost().equals("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 = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); | |
| startActivity(intent); | |
| return true; | |
| } | |
| } | |
| </pre> | |
| <p>Then create an instance of this new {@link android.webkit.WebViewClient} for the {@link | |
| android.webkit.WebView}:</p> | |
| <pre> | |
| WebView myWebView = (WebView) findViewById(R.id.webview); | |
| myWebView.{@link android.webkit.WebView#setWebViewClient(WebViewClient) setWebViewClient}(new MyWebViewClient()); | |
| </pre> | |
| <p>Now when the user clicks a link, the system calls | |
| {@link android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String) | |
| shouldOverrideUrlLoading()}, which checks whether the URL host matches a specific domain (as defined | |
| above). If it does match, then the method returns false in order to <em>not</em> override the URL | |
| loading (it allows the {@link android.webkit.WebView} to load the URL as usual). If the URL host | |
| does not match, then an {@link android.content.Intent} is created to | |
| launch the default Activity for handling URLs (which resolves to the user's default web | |
| browser).</p> | |
| <h3 id="NavigatingHistory">Navigating web page history</h3> | |
| <p>When your {@link android.webkit.WebView} overrides URL loading, it automatically accumulates a | |
| history of visited web | |
| pages. You can navigate backward and forward through the history with {@link | |
| android.webkit.WebView#goBack()} and {@link android.webkit.WebView#goForward()}.</p> | |
| <p>For example, here's how your {@link android.app.Activity} can use the device <em>Back</em> button | |
| to navigate backward:</p> | |
| <pre> | |
| @Override | |
| public boolean {@link android.app.Activity#onKeyDown(int,KeyEvent) onKeyDown}(int keyCode, KeyEvent event) { | |
| // Check if the key event was the Back button and if there's history | |
| if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.{@link android.webkit.WebView#canGoBack() canGoBack}()) { | |
| myWebView.{@link android.webkit.WebView#goBack() 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); | |
| } | |
| </pre> | |
| <p>The {@link android.webkit.WebView#canGoBack()} method returns | |
| true if there is actually web page history for the user to visit. Likewise, you can use {@link | |
| android.webkit.WebView#canGoForward()} to check whether there is a forward history. If you don't | |
| perform this check, then once the user reaches the end of the history, {@link | |
| android.webkit.WebView#goBack()} or {@link android.webkit.WebView#goForward()} does nothing.</p> | |