Friday, April 25, 2014

使用Webview時,遇到Uncaught ReferenceError: is not defined.

文章攢寫時間︰2014/04/25 16:50
Admob使用版本︰Goole Play Service 4.0版

一、問題

今天在Debug模式下,
可以正常和網頁透過Javscript interface溝通,
但是一旦使用正式金鑰釋岀apk時,
卻遇到

"Uncaught TypeError: Object [object Object] has not method 'xxxxx'", source: http://xxxxxx

的問題。

二、解決辦法

這個問題也是因為proguard沒有宣告規則導致的問題。
需要在proguard.cfg檔裡宣告如下
# 添加以下的程式碼才能讓webview的javascript能正常運作
-keep public class com.yourpackage.WebViewActivity$yourwebview_interface
-keep public class * implements com.yourpackage.WebViewActivity$yourwebview_interface
-keepclassmembers class com.yourpackage.WebViewActivity$yourwebview_interface { 
    ; 
}
-keepattributes JavascriptInterface

舉個例來看, 下面是我在Java裡使用Webview的簡單例子
 private void setWebview(){
webView.getSettings().setJavaScriptEnabled(true);
  webView.addJavascriptInterface(new WebViewHandler(), "handler");
  webView.setWebViewClient(new WebViewClient() {
  
  @Override
  public void onPageFinished(WebView view, String url) {
   LogPrint.i(TAG, "onPageFinished ,url: "+url);

   //呼叫網頁當下頁面的js函式:getVXML(),然後網頁js會呼叫回來下方的函式︰receiveValueFromJs()
   webView.loadUrl("javascript:getVXML()");

   super.onPageFinished(view, url);
  }
  
          @Override
          public boolean shouldOverrideUrlLoading(WebView view, String url) {
            return super.shouldOverrideUrlLoading(view, url);
          }
  
     });      
     webView.loadUrl(webViewUrl);
        }

     class WebViewHandler {
  //網頁當下頁面的js函式:getVXML()會呼叫這隻Native函式︰receiveValueFromJs(String data)
  public void receiveValueFromJs(String data) {

  }
 }

那麼,
在proguard.cfg檔裡,
則要宣告混淆規則如下︰
# 添加以下的程式碼才能讓webview的javascript能正常運作
-keep public class com.yourpackage.WebViewActivity$WebViewHandler
-keep public class * implements com.yourpackage.WebViewActivity$WebViewHandler
-keepclassmembers class com.yourpackage.WebViewActivity$WebViewHandler { 
    ; 
}
-keepattributes JavascriptInterface

填寫完混淆規則後,
輸岀正式金鑰的apk檔,
這時候Webview javascript interface就能繼續正常使用了。