zoukankan      html  css  js  c++  java
  • 【转】 Android经验: proguard 阻碍 webview 正常工作

    转自:http://blog.csdn.net/span76/article/details/9065941

    WebView 常识

    使用 Alert  提供消息

    我在页面经常用 Alert 提供消息,  但 Android 需要你编写 MyWebChromeClient

    mWebView.setWebChromeClient(new MyWebChromeClient());  

    [html] view plaincopy
     
    1. final class MyWebChromeClient extends WebChromeClient {    
    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.         }    
    8.     }    


    当然类似还有 onJsConfirm , onJsPrompt 等, ref: http://developer.android.com/reference/android/webkit/WebChromeClient.html

    Android 与 JavaScript  的交互

    WebSettings webSettings = mWebView.getSettings(); 
            webSettings.setJavaScriptEnabled(true);  
            mWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");  

    [html] view plaincopy
     
    1. final class DemoJavaScriptInterface {    
    2.         public void clickOnAndroid() {    
    3.             mHandler.post(new Runnable() {    
    4.                 public void run() {    
    5.                     mWebView.loadUrl("javascript:wave()");    
    6.                 }    
    7.             });    
    8.     
    9.         }    
    10.     }   



    [html] view plaincopy
     
    1. <html>    
    2.     <script language="javascript">    
    3.         /* This function is invoked by the activity */    
    4.         function wave() {    
    5.             alert("1");    
    6.             document.getElementById("droid").src="android_waving.png";    
    7.             alert("2");    
    8.         }    
    9.     </script>    
    10.     <body>    
    11.         <!-- Calls into the javascript interface for the activity -->    
    12.         <a onClick="window.demo.clickOnAndroid()"><div style="80px;    
    13.             margin:0px auto;    
    14.             padding:10px;    
    15.             text-align:center;    
    16.             border:2px solid #202020;" >    
    17.                 <img id="droid" src="android_normal.png"/><br>    
    18.                 Click me!    
    19.         </div></a>    
    20.     </body>    
    21. </html>    


    程序详细内容 ref: http://bolutes.iteye.com/blog/1320344

    实战

    最近跑 0xbench 中 Android WebView 测试 sunspider 测试, 发现 sunspider 跑一阵就停留在白色屏幕,不知为何?

    打开 0xbench/src/org/zeroxlab/benchmark/TesterJavascript.java 看了看, 这个testcase比较简单

    [html] view plaincopy
     
    1. public class TesterJavascript extends Tester {  
    2.   
    3.     protected WebView mWebView;  
    4.     protected WebSettings mSettings;  
    5.   
    6.     private double mTotalTime = 0.0;  
    7.     private String mResult = "";  
    8.     private String mFormattedResult = "";  
    9.   
    10.     @Override  
    11.     public void onCreate(Bundle savedInstanceState) {  
    12.         super.onCreate(savedInstanceState);  
    13.         setContentView(R.layout.javascript);  
    14.         mWebView = (WebView) findViewById(R.id.web);  
    15.   
    16.         mSettings = mWebView.getSettings();  
    17.         mSettings.setJavaScriptEnabled(true);  
    18.         mWebView.addJavascriptInterface(new MsgCallback(), "ANDROID_OBJ");  
    19.   
    20.         startTester();  
    21.     }  
    22.   
    23.     @Override  
    24.     public void onResume() {  
    25.         super.onResume();  
    26.     }  
    27.   
    28.     @Override  
    29.     protected String getTag() {  
    30.         return "JavaScript";  
    31.     }  
    32.   
    33.     @Override  
    34.     protected int sleepBeforeStart() {  
    35.         return 1000;  
    36.     }  
    37.   
    38.     @Override  
    39.     protected int sleepBetweenRound() {  
    40.         return 1000;  
    41.     }  
    42.   
    43.     @Override  
    44.     protected void oneRound() {  
    45.         mWebView.loadUrl("file:///android_asset/driver.html");  
    46.     }  
    47.   
    48.     @Override  
    49.     protected boolean saveResult(Intent intent) {  
    50.         intent.putExtra(CaseJavascript.SUNSPIDER_RESULT, mResult);  
    51.         intent.putExtra(CaseJavascript.SUNSPIDER_FORMATTED_RESULT, mFormattedResult);  
    52.         intent.putExtra(CaseJavascript.SUNSPIDER_TOTAL, mTotalTime);  
    53.         return true;  
    54.     }  
    55.   
    56.     class MsgCallback {  
    57.         public void finish(String result, String formatted_result) {  
    58.             mResult = result;  
    59.             mFormattedResult = formatted_result;  
    60.             decreaseCounter();  
    61.         }  
    62.     }  
    63. }  


    就是打开 driver.html, 让其自动运行其中的 JS, 而后通过 JS callback MsgCallback.finish 把测试结果数据返回 

    在看看 0xbench/assets/driver.html 的代码段, 其中 

    [html] view plaincopy
     
    1. function finish()  
    2. {  
    3.     initialize();  
    4.     computeItemTotals();  
    5.     computeTotals();  
    6.     computeMeans();  
    7.     computeStdDevs();  
    8.     computeStdErrors();  
    9.   
    10.   
    11.     var formattedOutput = getOutputForUpload();  
    12.     var finalOutput = getOutput();  
    13.     window.ANDROID_OBJ.finish(finalOutput, formattedOutput);  
    14.   
    15.   
    16. }  

    其中: window.ANDROID_OBJ.finish(finalOutput, formattedOutput); 正是回调, ANDROID_OBJ 是 inject 的 obj 就是 MsgCallback 的实例

    让 html 调试方便

    每次都改 assets中的 html, 再安装调试是痛苦的

    在 TesterJavascript.java 把 mWebView.loadUrl("file:///android_asset/driver.html"); 改为

    mWebView.loadUrl("file:///sdcard/sunspider/driver.html");

    再把 asset 中的中文件 copy 到 sdcard/sunspider/ 下面

    以后每次调试只需要改写下 html ,而后可直接重新运行

    定位问题:
    [html] view plaincopy
     
    1. window.alert("before calling finish")  
    2. window.ANDROID_OBJ.finish(finalOutput, formattedOutput)  
    3. window.alert("after calling finish")  

    发现只弹出第一个对话框, 看来回调不成功, 后来又看了 log, 发现与设想一致

    E/Web Console(  343): Uncaught TypeError: Object org.zeroxlab.zeroxbenchmark.TesterJavascript$MsgCallback@a5972b68 has no method 'finish' at file ...

    解决:
    根据关键字google 了一些, 发现问题很可能是 proguard 把程序优化了(正如下面这篇文章提到的) , 因为 eclipse 编译的 0xbench 能在系统上跑, 而出问题的 0xbench 不是在 eclipse 中编译出来的

    http://stackoverflow.com/questions/7424510/uncaught-typeerror-when-using-a-javascriptinterface

    于是又回到那个简单的webviewdemo 程序, 检查build 系统是否出问题

    运行以前那个小程序, 发现同样问题, 再用 jd-gui 查看build系统 progruad刚处理过 proguard.classes.jar 果然方法被过滤掉了, 而proguard 处理之前的 jar 是有的

    在 Android.mk 中加入

    LOCAL_PROGUARD_FLAG_FILES := proguard.cfg

    在 Android.mk 同级目录中建立 proguard.cfg 内容是:

    [html] view plaincopy
     
    1. -keepclassmembers class com.pnp.webview.WebViewDemo.DemoJavaScriptInterface {  
    2.     <methods>;  
    3. }  


    但编译过程中, proguard 不认

    Proguard 编译命令是

    [html] view plaincopy
     
    1. external/proguard/bin/proguard.sh -injars out/target/common/obj/APPS/WebView_intermediates/classes.jar -outjars out/target/common/obj/APPS/WebView_intermediates/proguard.classes.jar -libraryjars out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/classes.jar -include build/core/proguard.flags -forceprocessing -printmapping out/target/common/obj/APPS/WebView_intermediates/proguard_dictionary -include out/target/common/obj/APPS/WebView_intermediates/proguard_options   -include webview/proguard.cfg   

    报错是

    [html] view plaincopy
     
    1. Reading program jar [/home/payne/2jb/out/target/common/obj/APPS/WebView_intermediates/classes.jar]  
    2. Reading library jar [/home/payne/2jb/out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/classes.jar]  
    3. Note: the configuration refers to the unknown class 'com.pnp.webview.WebViewDemo.DemoJavaScriptInterface'  
    4. Note: there were 1 references to unknown classes.  
    5.       You should check your configuration for typos.  

    ( 后来查明查明应该用)

    [html] view plaincopy
     
    1. -keepclassmembers class com.pnp.webview.WebViewDemo$DemoJavaScriptInterface {  
    2.     <methods>;  
    3. }  

    另外还可以用

    [html] view plaincopy
     
    1. -keep class com.pnp.webview.JavascriptCallback  
    2. -keep class * implements com.pnp.webview.JavascriptCallback  
    3. -keepclassmembers class * implements com.pnp.webview.JavascriptCallback {  
    4.     <methods>;  
    5. }  

    用jd-gui 打开, 却找不到相应的类

    终于想到了, jd-gui 也有可能出问题. 所以不管 jd-gui 了, 直接安装程序运行, 得到了想要的结果.

  • 相关阅读:
    VisualSVN-Server windows 版安装时报错 "Service 'VisualSVN Server' failed to start. Please check VisualSVN Server log in Event Viewer for more details."
    Pytest 单元测试框架之初始化和清除环境
    Pytest 单元测试框架入门
    Python(email 邮件收发)
    Python(minidom 模块)
    Python(csv 模块)
    禅道简介
    2020年最好的WooCommerce主题
    Shopify网上开店教程(2020版)
    WooCommerce VS Magento 2020:哪个跨境电商自建站软件更好?
  • 原文地址:https://www.cnblogs.com/Mr-Nobody/p/3546641.html
Copyright © 2011-2022 走看看