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

WebView 常识

使用 Alert  提供消息

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

mWebView.setWebChromeClient(new MyWebChromeClient());

  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");

  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. }
  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="width: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比较简单

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

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

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

  1. function finish()
  2. {
  3. initialize();
  4. computeItemTotals();
  5. computeTotals();
  6. computeMeans();
  7. computeStdDevs();
  8. computeStdErrors();
  9. var formattedOutput = getOutputForUpload();
  10. var finalOutput = getOutput();
  11. window.ANDROID_OBJ.finish(finalOutput, formattedOutput);
  12. }

其中: 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 ,而后可直接重新运行

定位问题:
  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 内容是:

  1. -keepclassmembers class com.pnp.webview.WebViewDemo.DemoJavaScriptInterface {
  2. <methods>;
  3. }

但编译过程中, proguard 不认

Proguard 编译命令是

  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

报错是

  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.

( 后来查明查明应该用)

  1. -keepclassmembers class com.pnp.webview.WebViewDemo$DemoJavaScriptInterface {
  2. <methods>;
  3. }

另外还可以用

  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 了, 直接安装程序运行, 得到了想要的结果.

【转】 Android经验: proguard 阻碍 webview 正常工作的更多相关文章

  1. Android开发必知--WebView加载html5实现炫酷引导页面

    大多数人都知道,一个APP的引导页面还是挺重要的,不过要想通过原生的Android代码做出一个非常炫酷的引导页相对还是比较复杂的,正巧html5在制作炫酷动画网页方面比较给力,我们不妨先利用html5 ...

  2. Chromium Graphics: Android L平台上WebView的变化及其对浏览器厂商的影响分析

    原创文章.转载请以链接形式注明原始出处为http://blog.csdn.net/hongbomin/article/details/40799167. 摘要:Google近期公布的Android L ...

  3. Android混合开发之WebView与Javascript交互

    前言: 最近公司的App为了加快开发效率选择了一部分功能采用H5开发,从目前市面的大部分App来讲,大致分成Native App.Web App.Hybrid App三种方式,个人觉得目前以Hybri ...

  4. Android混合开发之WebView使用总结

    前言: 今天修改项目中一个有关WebView使用的bug,激起了我总结WebView的动机,今天抽空做个总结. 混合开发相关博客: Android混合开发之WebView使用总结 Android混合开 ...

  5. Android安全开发之WebView中的地雷

    Android安全开发之WebView中的地雷 0X01 About WebView 在Android开发中,经常会使用WebView来实现WEB页面的展示,在Activiry中启动自己的浏览器,或者 ...

  6. Android控件之WebView

    如何在Android应用中打开Web网站呢?谷歌为我们提供了解决方案,现在就让我们一起看一下WebView控件吧. 为了方便总结,就以实现下面这个效果为主线,进行总结: 首先我们先看一下它的布局文件吧 ...

  7. android基础开发之WebView

    WebView 是android平台沟通 http & H5 页面的桥梁. 但是google对这块的表述不是很清晰,而且SDK里面基本看不到源码,只有一个接口而已. 传送:http://dev ...

  8. android软件开发之webView.addJavascriptInterface循环渐进【二】

    本篇文章由:http://www.sollyu.com/android-software-development-webview-addjavascriptinterface-cycle-of-gra ...

  9. android软件开发之webView.addJavascriptInterface循环渐进【一】

    本篇文章由:http://www.sollyu.com/android-software-development-webview-addjavascriptinterface-cycle-of-gra ...

随机推荐

  1. 每日一词【命令行CMD】

    CURL 中文:命令行URL下载 英文解释:CommendLine Uniform Resource Locator 使用场景: 文件传输 curl是利用URL语法在命令行方式下工作的开源文件传输工具 ...

  2. springmvc的一个小例子学习(一)

    个人觉得,学框架最好的 方法无外乎两个:一个是实践这个框架,真实的去用它,比如spring框架,先搭一个简单的spring项目,然后一步一步得去丰富它,从中学到spring框架的精髓和知识:另外一个就 ...

  3. Socket 两平台互相 通信 .NET

    两个平台互相通信,对方发送数据过来,我方接收数据,对数据进行处理后发送结果给对方,对方进行相应的操作. 首页,我方开启服务监听: Socket socket = new Socket(AddressF ...

  4. Microsoft SQL2000 错误代码 (@@error)

    Microsoft SQL 2000 错误代码(@@error) 0 操作成功完成.  1 功能错误.  2 系统找不到指定的文件.  3 系统找不到指定的路径.  4 系统无法打开文件.  5 拒绝 ...

  5. mysql数据库用户和权限管理记录

    一.MySQL用户的基本说明: 1.1 用户的基本结构MySQL的用户:用户名@主机 ■用户名:16个字符以内■主机:可以是主机名.IP地址.网络地址等主机名:www.111cn.net,localh ...

  6. lamp环境的配置

    转载请注明原作者出处 write by xiaoyang 一.    先决条件 系统:RHEL Server6.5 工具:MySQL.MySQL Server.PHP.PHP-MySQL.HTTPD等 ...

  7. UI2_ButtonChess

    // // AppDelegate.m // UI2_ButtonChess // // Created by zhangxueming on 15/6/30. // Copyright (c) 20 ...

  8. (转)在 Windows 上安装Rabbit MQ 指南

    rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...

  9. cass实体编码列表

    地物名称 编码 图层 类别 参数一 参数二 实体类型 三角点 131100 KZD 20 gc113 3 SPECIAL,1 三角点分数线 131110 KZD 附 LINE 三角点高程注记 1311 ...

  10. Codevs 2837 考前复习

     时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description Aiden马上要考试了,可他还没怎么复习,于是他 ...