WebView上實現Java與JavaScript互動,webviewjavascript
在安卓開發上,考慮到開發效率和介面更新,有時使用WebView結合web頁面技術,可以快速迭代地開發行動裝置 App。WebView載入資源的速度並不慢,但是如果資源多了,就很慢。圖片、css、js、html這些資源每個大概需要10-200ms,一般都是30ms以內就行了。但是,WebView是等全部資源載入完成才開始渲染的,所以最後用原生js來寫,別用太多jQuery之類的架構,以改善使用者體驗。
在混合開發中,有時會用到安卓原生SDK,如調用相機、查看相簿、錄音等,這就需要web頁面中的JavaScript能調用到安卓SDK介面。由於Android的WebView是基於webkit核心的,整合了js與java互調的介面函數,可以方便地進行開發使用。
介面布局xml:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" > 5 6 <WebView 7 android:id="@+id/webView" 8 android:layout_width="fill_parent" 9 android:layout_height="fill_parent"10 android:layout_above="@+id/linearLayout"11 />12 <LinearLayout 13 android:id="@+id/linearLayout"14 android:layout_width="match_parent"15 android:layout_height="wrap_content"16 android:layout_alignParentBottom="true"17 >18 <Button19 android:id="@+id/btn"20 android:layout_width="wrap_content"21 android:layout_height="wrap_content"22 android:text="Java調用JavaScript介面"23 >24 </Button>25 </LinearLayout>26 </RelativeLayout>
java代碼:
1 private WebView webView; 2 private Handler handler = new Handler(); 3 private Button button; 4 @SuppressLint("SetJavaScriptEnabled") 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 webView = (WebView) findViewById(R.id.webView);10 11 //自訂webView設定12 WebSettings webSettings = webView.getSettings();13 webSettings.setJavaScriptEnabled(true);14 webView.addJavascriptInterface(new MyJavaScriptInterface(MainActivity.this), "javaInterface");15 //如果注釋了,javaScript中的alert彈窗等就會失效,不顯示16 webView.setWebChromeClient(new WebChromeClient());17 //webView.setWebChromeClient(new MyWebChromeClient());18 19 //測試webView載入是否正常20 //webView.loadUrl("http://www.baidu.com/");21 webView.setWebViewClient(new HelloWebView());22 webView.loadUrl("file:///android_asset/index.html");23 24 button = (Button) findViewById(R.id.btn);25 button.setOnClickListener(new View.OnClickListener() {26 27 @Override28 public void onClick(View v) {29 String param = "bb";30 webView.loadUrl("javascript:showTitle('"+param+"')");31 }32 });33 }34 35 private class HelloWebView extends WebViewClient{36 @Override37 public boolean shouldOverrideUrlLoading(WebView view, String url) {38 // TODO Auto-generated method stub39 view.loadUrl(url);40 return true;41 } 42 }43 44 /**45 * 在主線程中定義JavaScript可以調用的安卓介面46 * @author CHQ47 * API 17以後,每個被調用java函數都要叫聲明 @JavascriptInterface48 */49 public class MyJavaScriptInterface{50 private Context context;51 52 public MyJavaScriptInterface(Context context){53 this.context = context;54 }55 @JavascriptInterface56 public String toString() {57 return "this is interface";58 }59 @JavascriptInterface60 public void clickOnAndroid() {61 Toast.makeText(context, "js調用安卓:....", Toast.LENGTH_SHORT).show();62 }63 /**64 * 安卓調用JS介面,要開啟子線程調用65 */66 @JavascriptInterface67 public void call() {68 Toast.makeText(context, "安卓用戶端再調用JavaScript介面", Toast.LENGTH_SHORT).show();69 handler.post(new Runnable() { 70 @Override71 public void run() {72 String param = "bb";73 webView.loadUrl("javascript:showTitle('"+param+"')");74 }75 });76 77 }78 79 }
其中:有幾點必須注意的,網上早期關於WebView的描述中,有幾點變化。1)安卓4.2以上的版本中使用WebView實現Java與Js互調,java介面需要聲明@JavascriptInterface ; 2)WebView要調用setWebChromeClient(),以適應Js等彈窗等實現;3)addJavascriptInterface中綁定的介面中調用JavaScript介面,需要開啟子線程來調用(報錯:Caused by: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. );
HTML代碼:
<html> <script type="text/javascript"> //安卓定義的介面1 function callAndroidInterface() { window.javaInterface.clickOnAndroid(); } // function showTitle(param) { alert("傳參:"+param); var x = document.getElementById("title"); alert("標題:"+x.innerHTML); } </script> <body> <h3 id="title">關於安卓與JavaScript的互動</h3> <input type="button" value="調用介面1" onclick="callAndroidInterface()"></input> <input type="button" value="測試介面可用性" onclick="showTitle('aa')"></input> <input type="button" value="調用介面2" onclick="window.javaInterface.call()"></input> </body></html>
以上html檔案,其中javaInterface就是webView中addJavacriptInterface()方法中注入的介面入口名稱,通過該名稱就可以直接調用Java中的介面。(該html頁面需要保持到項目assets目錄中,由webView.loadUrl("file:///android_asset/index.html")來載入);
:
其中,對話方塊彈出:網址為"file://"的網頁顯示:,如果是伺服器上的web頁面就會顯示源IP地址等等,顯然不是我們想要的。下一篇,我們可以重寫WebChromeClient來修改對話方塊、確認框等webView的最佳化。