關鍵類
- WebView
- WebSettings
- WebViewClient
- WebChromeClient
WebView基本用法:
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("http://www.example.com");
如果加載的是網絡頁面需要申請網絡權限:
<uses-permission android:name="android.permission.INTERNET" />
補充
- WebView還有兩個方法,
loadData(String data, String miniType,String edcoding)
和loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl)
.有時候loadData()
只能加載‘data’,會導致其他協議的URL無法加載,當加載的URL不一定是‘data’時推薦用后一個方法。- mimeType: 數據類型,如:text/html.
- encoding: 數據編碼方式 base64 或者 url encoding.
- baseUrl: 指定頁面的根路徑.
-
URL
統一資源定位符(uniform resource locator),URI
統一資源標識符(uniform resource identifier )。URI包括URL。URL
的一般語法scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]
。
配置WebView
配置WebView,需要先獲得一個WebSettings對象。WebSettings對象并不是通過new
來獲得,而是在我們創建WebView的時候,就會獲得一個默認的WebSettings對象。這個WebSetting對象可以通過myWebView.getSettings()
來獲得。
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
當我們通過WebView來加載了一個頁面時,點擊頁面上的鏈接時,會彈出一個對話框,讓我們選擇通過哪個瀏覽器來打開,如果我們希望直接在自己的WebView中打開,就可以通過如下方法實現:
myWebView.setWebViewClient(new WebViewClient());
WebView攔截資源請求
有時候我們不希望自己的WebView處理相關的請求,例如頁面中具有發郵件,打電話,發消息這類鏈接的時候,我們希望用戶點擊之后會啟動第三方應用,而不是我們自己的WebView處理,就可以通過如下方式實現。
首先我將一個html文檔放在了main/assets
目錄下,注意不是res/
目錄下。模擬一個網頁。html文檔如下:
<!DOCTYPE html>
<html>
<head>
<title>WebView Test</title>
<!--下面前兩個方法通過javascript調用WebView中的java代碼-->
<!--第三個方法,就是簡單的javascript代碼,在網頁打開,會有一個警告對話框-->
<script type="text/javascript">
var new_activity = function(){
android.newActivity();
}
var send_notification = function(){
android.sendNotification();
}
window.onload = function(){
alert("alert from javascript");
}
</script>
</head>
<body>
<p><a href="mailto: study@163.com">send email</a></p>
<p><a href="tel: 12312312312">call</a></p>
<p><a href="sms: 10086">send message</a></p>
<!--兩個綁定點擊事件的按鈕-->
<button onclick="new_activity()">new activity</button>
<button onclick="send_notification()">send notification</button>
</body>
</html>
在java代碼中重寫WebViewClient的shouldOverrideUrlLoading(WebView view, String url)
方法,該方法返回true
,表示重寫了該方法,這次請求不由自己的WebView
處理,會調用第三方應用。
// 注意url的寫法。
String url = "file:///android_asset/index_test.html";
myWebView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Uri uri = Uri.parse(url);
if ("mailto".equalsIgnoreCase(uri.getScheme())
||"tel".equalsIgnoreCase(uri.getScheme())
||"sms".equalsIgnoreCase(uri.getScheme())){
//注意這里Intent Action的寫法。
Intent intent=new Intent(Intent.ACTION_VIEW, uri);
startActivity( intent);
return true;
}
return false;
}
});
myWebView.loadUrl(url);
補充
- 當我們想要屏蔽掉網頁的某些資源的時候,需要重寫WebViewClient的
shouldIntercepterRequest()
方法,而重寫shouldOverrideUrlLoading
是沒有效果的。因為網頁的資源是在"IO"線程里加載的,而shouldOverrideUrlLoading
運行在主線程,只能攔截新的URL
對象,也就是頁面需要重寫加載的時候,才會回調。而shouldIntercepterRequest
方法運行在IO
線程里,可以對資源請求進行攔截,并且可以返回其他的資源。 - 禁止加載圖片
webSettings.setLoadsImagesAutomatically(false)
- 當頁面載入錯誤時,可以重寫
WebViewClient
的onReceivedError()
方法。
JavaScript和WebView的交互
Jave調用Javascript
直接調用
myWebView.loadUrl("javascript:alert(java to javascript)");
補充
也可以通過evaluateJavascript
方法來處理帶有返回值的js方法。
通過重載WebChromeClient調用
注意上面的Html代碼,當頁面加載時會有一個彈出對話框。雖然已給WebView設置里setJavaScriptEnabled(true)
,但是WebView依然無法顯示對話框。通過如下方法就可使對話框顯示。
myWebView.setWebChromeClient(new WebChromeClient());
那么WebChromeClient
和WebViewClient
有什么不同呢?前者主要負責輔助處理JS,與頁面內容交互。后者主要負責頁面加載過程中的事件通知。
如果你覺得這個彈窗實在太難看了,我們可以通過如下方法,重新自定義:
myWebView.setWebChromeClient(new WebChromeClient(){
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Toast.makeText(MainActivity.this,message,Toast.LENGTH_SHORT).show();
result.confirm();
return true;
}
});
Javascript調用java
主要是通過addJavascriptInterface(Object object,String name)
,向Javascript中注入對象和對象的名字。在api17以下會注入所有public
方法,api17以上只會注入添加了@JavascriptInterface
注釋的方法。
首先我們創建一個類,如下:
public class WebAppInterface {
private Context mContext;
private final static int NOTIFICATION_ID = 1;
public WebAppInterface(Context c) {
mContext = c;
}
// 對應html第一個方法
@JavascriptInterface
public void newActivity(){
Intent intent = new Intent(mContext,JSActivity.class);
mContext.startActivity(intent);
}
// 對應html中第二個方法
@JavascriptInterface
public void sendNotification(){
Notification notification = new NotificationCompat.Builder(mContext)
.setContentTitle("hello")
.setContentText("this notification is sent by js")
.setSmallIcon(R.drawable.notification_icon)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.build();
NotificationManager manager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(NOTIFICATION_ID,notification);
}
}
然后為WebView添加這個js接口
myWebView.addJavascriptInterface(new WebAppInterface(mContext),"android");
之后就可以通過js調用上面設置的兩個方法了。詳細信息請參考上面的html文件。
WebView小拓展
如果我們不希望用戶點擊了WebView中的鏈接跳轉之后,按下返回鍵直接退出應用,可以在Activity中重寫onBackPress
方法
@Override
public void onBackPressed() {
if (myWebView.canGoBack()){
myWebView.goBack();
}else {
super.onBackPressed();
}
}
WebView調試技巧
添加如下代碼
if (Build.VERSION.SDK_INT >=Build.VERSION_CODES.KITKAT && BuildConfig.DEBUG){
myWebView.setWebContentsDebuggingEnabled(true);
}
在chrome瀏覽器中輸入chrome//inspect/#devices
.