1. AndroidManifest.xml中必須使用許可 "android.permission.INTERNET", 否則會出Web page not available錯誤。
<uses-permission android:name="android.permission.INTERNET"/>
2. 如果訪問的頁面中有Javascript,則webview必須設置支持Javascript。
1 WebSettings webSetting = webview.getSettings(); 2 webSetting.setJavaScriptEnabled(true);
3.如果頁面中鏈接,如果希望點擊鏈接繼續在當前browser中響應,而不是新開Android的系統browser中響應該鏈接,必須覆蓋 webview的WebViewClient對象或者覆蓋webview的 setWebChromeClient
1 mWebView.setWebViewClient(new WebViewClient(){ 2 public boolean shouldOverrideUrlLoading(WebView view, String url) { 3 view.loadUrl(url); 4 return true;
5 } 6 });
1 mWebView.setWebChromeClient(new MyWebChromeClient() 2 @Override 3 public boolean onJsAlert(WebView view, String url, String message, JsResult result) { 4 Log.d(LOG_TAG, message); 5 result.confirm(); 6 return true; 7 });
4. 如果不做任何處理,瀏覽網頁,點擊系統“Back”鍵,整個Browser會調用finish()而結束自身,如果希望瀏覽的網 頁回退而不是推出瀏覽器,需要在當前Activity中處理並消費掉該Back事件。
1 public boolean onKeyDown(int keyCode, KeyEvent event) { 2 if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) { 3 mWebView.goBack(); 4 return true; 5 } 6 return super.onKeyDown(keyCode, event); 7 }
5. javascript對象 與 android 對象綁定
WebView注入Java對象
對象注入即通過webview 建立 javascript對象 與 android 原生對象的綁定關系,下面代碼中,obj1對象在android程序中可以操作,obj2在js程序中可以操作,兩者操作的均為同一個內存對象,即可以理解為,兩個綁定的對象是同一個對象在不同運行環境下的一個別名(僅個人理解,有誤請大牛指正)
1 webview.getSetting().setJavaScriptEnable(true); 2 class JsObject { 3 @JavascriptInterface 4 public String toString() { return "injectedObject"; } 5 } 6 webView.addJavascriptInterface(new JsObject()obj1, "injectedObject"obj2);
上面的程序建立 javascript 與android 程序的綁定關系,android 4.2 之后版本提供給js調用的函數必須帶有注釋語句@JavascriptInterface ,4.2版本之前向webview注入的對象所暴露的接口不是必須帶有@JavascriptInterface注釋語句(需要注意,android adt,eclipse生成的工程,低版本中會自動帶有 anotations.jar,支持@JavascriptInterface, 而高版本中工程中,不會自動帶有anotations.jar包,所以要加入注釋語句@JavascriptInterface,首先要自己手動加入anotations.jar包,不要忘記import 哦!本人就犯過這么低級的錯誤哦)
官方文檔解釋是因為這個接口允許JavaScript 控制宿主應用程序,這是個很強大的特性,但同時,在4.2的版本前存在重大安全隱患,因為JavaScript 可以使用反射訪問注入webview的java對象的public fields,在一個包含不信任內容的WebView中使用這個方法,會允許攻擊者去篡改宿主應用程序,使用宿主應用程序的權限執行java代碼。因此4.2以后,任何為JS暴露的接口,都需要加 @JavascriptInterface 注釋,這樣,這個Java對象的fields 將不允許被JS訪問。[2]
注:如果將targetSdkVersion 設置為17或者更高,但卻沒有給暴露的js接口加@JavascriptInterface注釋,則logcat會報如下輸出:
Console: Uncaught TypeError: Object [object Object] has no method 'toString'
(需要特注意的一點,這里的限制是通過 targetSdkVersion 為標准,即如果工程采用了android sdk的版本是4.2以上,但是 targetSdkVersion 的版本在17之下,那么該狀態下生成的應用,不過報錯,如果targetSdkVersion 設置為>=17 就需要特別主意,要加上 @JavascriptInterface注釋語句了, 所有建議在各種版本下都采用@JavascriptInterface注釋,就萬無一失了)
6. 在做webview開發是經常會加載本機的html文件如下:
file:///android_asset/teste.html 加載項目assets下的文件teste.html
file:///sdcard/index.html 加載sdcard下的index.html文件
源代碼:
android
1 private WebView mWebView; 2 private Handler mHandler = new Handler(); 3 4 @Override 5 protected void onCreate(Bundle savedInstanceState) { 6 super.onCreate(savedInstanceState); 7 setContentView(R.layout.main); 8 mWebView = (WebView) findViewById(R.id.webview); 9 10 WebSettings webSettings = mWebView.getSettings(); 11 webSettings.setJavaScriptEnabled(true); 12 webSettings.setSavePassword(false); 13 webSettings.setSaveFormData(false); 14 webSettings.setSupportZoom(false); 15 16 mWebView.setWebChromeClient(new MyWebChromeClient()); 17 mWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo"); 18 // mWebView.loadUrl("http://www.baidu.com/"); 19 mWebView.loadUrl("file:///android_asset/demo.html"); 20 } 21 22 final class DemoJavaScriptInterface { 23 DemoJavaScriptInterface() { 24 Log.i("aaaa", "create DemoJavaScriptInterface"); 25 } 26 /** 27 * This is not called on the UI thread. Post a runnable to invoke 28 * loadUrl on the UI thread. 29 */ 30 @JavascriptInterface 31 public void clickOnAndroid() { 32 mHandler.post(new Runnable() { 33 public void run() { 34 mWebView.loadUrl("javascript:wave()"); 35 } 36 }); 37 } 38 } 39 /** 40 * Provides a hook for calling "alert" from javascript. Useful for 41 * debugging your javascript. 42 */ 43 final class MyWebChromeClient extends WebChromeClient { 44 @Override 45 public boolean onJsAlert(WebView view, String url, String message, JsResult result) { 46 result.confirm(); 47 return true; 48 } 49 }
html源文件
1 <!DOCTYPE html> 2 <html> 3 <script language="javascript"> 4 /* This function is invoked by the activity */ 5 function wave() { 6 alert("1"); 7 document.getElementById("droid").src="android_waving.png"; 8 alert("2"); 9 } 10 </script> 11 <body> 12 <!-- Calls into the javascript interface for the activity --> 13 <a onClick="window.demo.clickOnAndroid()"> 14 <div style="width:80px; 15 margin:0px auto; 16 padding:10px; 17 text-align:center; 18 border:2px solid #202020;" > 19 <img id="droid" src="android_normal.png"/><br> 20 Click me! 21 </div></a> 22 </body> 23 </html>
參考文檔:
[1]. WebView注入Java對象注意事項 參考:http://blog.csdn.net/zgjxwl/article/details/9627685
[2]. Android WebView的Js對象注入漏洞解決方案 http://my.oschina.net/u/1402271/blog/306364
[3]. https://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface
