跛足而不迷路能胜过虽健步如飞但误入歧途的人。---培根
如果你想要使用实现一个web应用(或者仅仅一个web page)作为客户端应用程序的一部分,又可以通过使用WebView来实现这种功能。WebView类继承自Android的View类,它使得在activity里面展示web页面成为可能。它没有拥有任何完全开发的web浏览器的特征,比如说导航部件 或者 地址栏。所有WebView能做的默认情况下就只是展示一个web 页面。
下面有两个场景适用于使用WebView:
1、当你想要在你的应用程序里面里面提供一些你需要更新的信息的时候,WebView可能会有所帮助,比如说:在你的Android应用里面的终端用户协议或者用户指南,你可以创建一个包含WebView的Activity,然后使用它来演示那些在线的文档。
2、如果你的应用程序想要提供给用户一些经常需要通过Intent连接来获得的数据,比如说email,WebView可能会有所帮助。在这种情况下,你或许会发现在你的应用程序里面构建一个WebView,通过网页展示用户的数据,要远好于执行一个网络请求,然后解析数据并在Android的布局里面展示。取而代之,你可以设计一个适合于你的android设备的网页,然后在你的应用程序里面实现一个WebView去加载这个web页面。
下面将会讲解如何使用WebView,和利用它做一些其他的事情:比如说处理页面导航,将网页中的JavaScript和你的应用程序的客户端代码绑定在一起。
一、添加一个WebView到你的应用
为了添加一个WebView到你的应用程序,在你的Activity的布局文件里面添加<WebView>标签 。例如:下面有一个布局文件,它包含了一个全屏的WebView:
<?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" />
为了在WebView里面加载一个web页面,使用loadUrl(),例如:
WebView myWebView = (WebView) findViewById(R.id.webview); myWebView.loadUrl("http://www.example.com");
你的应用程序需要有访问Internet的权限你才可以使用它,为了获得Internet的访问权限,你需要在你的manifest文件里面请求Internet的权限,例如:
<manifest ... > <uses-permission android:name="android.permission.INTERNET" /> ... </manifest>
上面的这些满足了你使用WebView组件展示一个web页面。
二、在WebView里面使用JavaScript
如果你想要在一个WebView中加载一个使用了JavaScript的web页面,你必须设置你的WebView使JavaScript能够运行。一旦JavaScript能够运行,你就可以在你的应用程序和你的JavaScript之间创建一些接口。
1、使JavaScript能执行
默认情况下,在WebView里面JavaScript是不能运行的。但是你可以激活它通过WeBView的WebSettings。你可以通过getSettings()来获得WebSettings,然后使用setJavaScriptEnabled()激活JavaScript。
例如:
WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true);
WebSettings提供可很多设置,在将来你使用的过程中会发现。
2、绑定JavaScript代码和你的Android代码
当在你的android应用程序里面开发一个使用WebView的web应用,你可以在你的JavaScript代码和你的客户端的android代码之间创建一个接口。例如:你的JavaScript代码能够调用你的Android代码去展示一个对话框,而不是通过使用JavaScript的alert()函数。
为了在你的JavaScript代码和android代码之间绑定一个新的接口,可以调用addJavascriptInterface(),通过它将一个类实例绑定到你的JavaScript,并且提供一个接口名,能够被JavaScript调用去访问该类。
例如:你可以在你的android应用里面包含下面这个类:
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或者更高,你必须添加@JavascriptInterface
注释:对于任何一个方法你想要在JavaScript中调用(这个方法必须声明是public)。如果你不提供任何的注释,当运行在Android4.2这或者更高版本上的话个方法将不会被web页面访问。
在这个例子里,WebAppInterface类允许web页面调用showToast()方法创建一个Toast信息。
你可以通过addJavascriptInterface()将类和运行在WebView上的JavaScript绑定在一起,并且命名这个借口为Android.例如:
WebView webView = (WebView) findViewById(R.id.webview); webView.addJavascriptInterface(new WebAppInterface(this), "Android");
这将会为运行在WebView上的JavaScript创建一个叫做“Android”的接口。在这个点,你的web程序可以访问WebAppInterface这个类。例如:下面有一些html和JavaScript通过使用新接口,当用户点击按钮的时候创建一个toast消息:
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" /> <script type="text/javascript"> function showAndroidToast(toast) { Android.showToast(toast); } </script>
注解:被绑定到JavaScript上的object对象运行在其他的线程里而不是在他被创建的线程里。
注意:使用addJavaScriptInterface()允许JavaScript去控制你的android应用程序。这可能是一个非常有用的特征或者是非常严重的安全问题。当在WebView里面的Html不可靠的时候(例如:部分或者所有的Htnl被陌生的人或者程序提供),然后攻击者可以通过html执行你的客户端代码或者根据自己的选择去执行相应的代码。因此,你不应该使用addJavascriptInterface(),除非出现在WebView里面的Html和JavaScript是你自己自己编写的。在你的WebView里面,你应该不允许用户导航到其他不是你自己编写的网页(取而代之,允许用户默认的浏览器程序去打开这些外部的链接,用户的默认浏览器能打开所有的URL链接,所以你在处理下面章节即将讲到的页面导航,一定要小心)。
三、处理页面导航
当用户点击一个在你的WebView里面显示的web页面中的一个链接时,对于Android默认的行为就是启动一个能够处理URLs的应用程序。通常,默认的web浏览器能够打开并且加载目的URL。然而,你可以重写WebView的这种默认行为,使得能够在你自己的WebView里面打开链接。
通过由WebView维持的web页面的历史记录,
你可以允许用户向前或向后导航。
打开用户点击的链接,通过使用setWebViewClient简单地为你的WebView提供了一个WebViewClient(),例如:
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient
(new WebViewClient());
现在用户点击的链接都可以在你自己的WebView里面加载。
如果你想对对点击链接之后页面在哪里加载做更多的控制,那么就自定义一个WebViewClient,它重写了shouldOverrideUrlLoading()方法。例如:
private class MyWebViewClient extends WebViewClient {
@Override
public boolean 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;
}
}
为WebView创建这个自定义的WebViewClient实例:
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient
(new MyWebViewClient());
现在当用户点击一个链接的时候,系统会调用shouldOverUrlLoding(),它能够检查URL的host是否匹配一个特定的域(正如上面自己定义的
"www.example.com"
)。如果匹配,该方法就返回false,这样的话就不会重写原来的Url 加载(和平常一样它允许WebView去加载Url)。如果不匹配,一个Intent就会被创建去启动默认的Activity去处理Urls(一般是用户默认的web浏览器)。
1、浏览网页的历史
当你的WebView重写URL的加载方式时,它能够自动积累曾经访问过的web页面的历史。你可以通过goBack()和goForward()方法实现向后或向前导航。
例如,下面将展示如何使用设备的回退按钮实现向后导航:
@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); }
如果有用户曾经访问过的web页面的历史记录,canGoBack()方法就返回true.同样的,你可以使用canGoForwar()方法去检查是否有向前的历史记录。如果你不执行这个检查,一旦用户到达历史记录的末尾,goBack()和goForward()方法将什么都不做。