WebView

WebView

安卓原生顯示網頁控件。

作用

  • 可以直接顯示和渲染web頁面,直接顯示網頁
  • webview可以直接用html文件(網絡上或本地assets中)作佈局
  • 和JavaScript交互調用

基本使用

  1. 添加網絡請求權限
<uses-permission android:name="android.permission.INTERNET"/>```
2. layout佈局

webview = (WebView) findViewById(R.id.webView1);
webview.loadUrl("http://www.baidu.com/");

WebSetting

設置webview屬性

setJavaScriptEnabled(true);  //支持js

setPluginsEnabled(true);  //支持插件

setUseWideViewPort(false);  //將圖片調整到適合webview的大小

setSupportZoom(true);  //支持縮放

setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); //支持內容重新佈局

supportMultipleWindows();  //多窗口

setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);  //關閉webview中緩存

setAllowFileAccess(true);  //設置可以訪問文件

setNeedInitialFocus(true); //當webview調用requestFocus時爲webview設置節點

webview webSettings.setBuiltInZoomControls(true); //設置支持縮放

setJavaScriptCanOpenWindowsAutomatically(true); //支持通過JS打開新窗口

setLoadWithOverviewMode(true); // 縮放至屏幕的大小

setLoadsImagesAutomatically(true);  //支持自動加載圖片```


## WebViewClient
 主要提供網頁加載各個階段的通知,比如網頁開始加載onPageStarted,網頁結束加載onPageFinished等;
爲解決應用啓用後,自動的打開了系統內置的瀏覽器問題,需webview設置WebViewClient,並重寫方法:

webview.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});“`
方法全解:

doUpdateVisitedHistory(WebView view, String url, boolean isReload)  //(更新歷史記錄)

onFormResubmission(WebView view, Message dontResend, Message resend) //(應用程序重新請求網頁數據)

onLoadResource(WebView view, String url) // 在加載頁面資源時會調用,每一個資源(比如圖片)的加載都會調用一次。

onPageStarted(WebView view, String url, Bitmap favicon) //這個事件就是開始載入頁面調用的,通常我們可以在這設定一個loading的頁面,告訴用戶程序在等待網絡響應。

onPageFinished(WebView view, String url) //在頁面加載結束時調用。同樣道理,我們知道一個頁面載入完成,於是我們可以關閉loading 條,切換程序動作。

onReceivedError(WebView view, int errorCode, String description, String failingUrl)// (報告錯誤信息)

onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,String realm)//(獲取返回信息授權請求)

onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) //重寫此方法可以讓webview處理https請求。

onScaleChanged(WebView view, float oldScale, float newScale) // (WebView發生改變時調用)

onUnhandledKeyEvent(WebView view, KeyEvent event) //(Key事件未被加載時調用)

shouldOverrideKeyEvent(WebView view, KeyEvent event)//重寫此方法才能夠處理在瀏覽器中的按鍵事件。

shouldOverrideUrlLoading(WebView view, String url)
//在點擊請求的是鏈接是纔會調用,重寫此方法返回true表明點擊網頁裏面的鏈接還是在當前的webview裏跳轉,不跳到瀏覽器那邊。這個函數我們可以做很多操作,比如我們讀取到某些特殊的URL,於是就可以不打開地址,取消這個操作,進行預先定義的其他操作,這對一個程序是非常必要的。```


## WebChromeClient
主要提供網頁加載過程中提供的數據內容,比如返回網頁的title,favicon等。

若自己定義了一個頁面加載進度的progressbar,需要展示給用戶的時候,可以通過如下方式獲取webview內頁面的加載進度:

webview.setWebChromeClient(new WebChromeClient(){
@Override
public void onProgressChanged(WebView view, int newProgress) {
//get the newProgress and refresh progress bar
}
});“`
每個頁面,都有一個標題,比如www.baidu.com這個頁面的title即“百度一下,你就知道”,那麼如何知道當前webview正在加載的頁面的title:

webview.setWebChromeClient(new WebChromeClient(){
            @Override
            public void onReceivedTitle(WebView view, String title) {
                titleview.setText(title);//a textview
            }
        });```

## 文件下載
最簡單的方式:

class MyDownloadListenter implements DownloadListener{
@Override
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype, long contentLength) {
System.out.println(“url ==== >” + url);
//new HttpThread(url).start();

Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
}“`
使用自建IO流的方式,後面章節待續。

錯誤處理

當瀏覽器發生錯誤時,可加載本地html文件或本地控件,以美觀界面。

webview.setWebViewClient(new WebViewClient(){

      @Override
      public void onReceivedError(WebView view, int errorCode,
        String description, String failingUrl) {
    switch(errorCode)
    {
    case HttpStatus.SC_NOT_FOUND:
        view.loadUrl("file:///android_assets/error_handle.html");
        break;
    }
      }
  });```

 ## <font color="#ff0000">WebView與JavaScript的交互</font>
- webview調用js

mWebView.loadUrl(“javascript:do()”);“`
js所在的html文件大致如下:



/* This function is invoked by the webview*/
function do() {
alert("1");
}


package com.test.webview;
class DemoJavaScriptInterface {
  DemoJavaScriptInterface() {
  }
  /**
   * This is not called on the UI thread. Post a runnable to invoke
   * loadUrl on the UI thread.
   */
  public void clickOnAndroid() {
      mHandler.post(new Runnable() {
    public void run() {
        //TODO
    }
      });
  }
}```
首先給webview設置:

mWebview.setJavaScriptEnabled(true);“`
隨後將本地的類(被js調用的)映射出去:

mWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");```
“demo”這個名字就是公佈出去給JS調用的,那麼js久可以直接用下列代碼調用本地的DemoJavaScriptInterface類中的方法了:


function showAndroidToast(toast)
{
demo.clickOnAndroid();
}
“`

WebView與JavaScript相互調用混淆問題

若webview中的js調用了本地的方法,正常情況下發布的debug包js調用的時候是沒有問題的,但是通常發佈商業版本的apk都是要經過混淆的步驟,這個時候會發現之前調用正常的js卻無法正常調用本地方法了。

這是因爲混淆的時候已經把本地的代碼的引用給打亂了,導致js中的代碼找不到本地的方法的地址。

解決這個問題很簡單,即在proguard.cfg文件中加上一些代碼,聲明本地中被js調用的代碼不被混淆。下面舉例說明:
- 若被js調用的那個類DemoJavaScriptInterface的包名爲com.test.webview,那麼就要在proguard.cfg文件中加入:

-keep public class com.test.webview.DemoJavaScriptInterface{
    public <methods>;
}```
- 若是內部類,則大致寫成如下形式:

-keep public class com.test.webview.DemoJavaScriptInterface$InnerClass{
public ;
}
- 若android版本比較新,可能還需要添加上下列代碼:

-keepattributes Annotation
-keepattributes JavascriptInterface“`

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章