文档章节

android + javascript 相互通信实例分析

飓风2000
 飓风2000
发布于 2016/07/30 15:31
字数 1496
阅读 36
收藏 4
点赞 1
评论 0

关键点:
正向通讯(js调用Android方法)
1.在Android程序中为WebView控件增加一个与JS的暗号,demo。如WebView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");
2.在Android程序中的定义一个支持js调用的方法,需要通过注解标志@JavascriptInterface。如 @JavascriptInterface public void clickOnAndroid() {}
3.在WebView打开的网页js中按照暗号要求,定义一个js方法,window.demo.clickOnAndroid()
以上3点完成js调用android的程序

逆向通讯(android调用js方法)
1.在js定义一个方法,function wave(){}
2.在Android程序中调用js方法mWebView.loadUrl("javascript:wave()");

Android与js通讯原理:
1.在Android中定义各种支持请求的监听服务和业务实现,用于接收到js请求,生成Android的Intent对象,并且广播出去,监听服务收到这个广播开始做事情
2.在Android中定义一个专门处理js请求的类,类中的方法需要通过@JavascriptInterface 注解标志(相当于用java代码写js代码)
3.把这个可以处理js请求的java类注册到Android中的WebView控件中,并且需要写一个实例名字(这个实例名字是与js的通信约定)
4.在js中通过实例名称直接调用Android的方法

 

实例分析:

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>

复制代码

 

 

本文转载自:http://www.cnblogs.com/yaozhongxiao/p/3408948.html

共有 人打赏支持
飓风2000
粉丝 29
博文 218
码字总数 119157
作品 0
浦东
高级程序员
Lynx技术分析-JS引擎扩展设计

JS Binding 技术 Lynx(一个高效的跨平台框架) 的 JS Binding 技术最主要的目的是搭建一个高效的与 JS 引擎解耦的通信桥梁,同时具备 JS 引擎切换的能力。该技术经历了多次迭代,最终通过抽...

hxxft ⋅ 05/15 ⋅ 0

使用Kotlin:让Android与JS交互的详解

先来说说什么是JS交互: 说的俗一点就是通过我们项目中的控件来调用HTML里的JS代码,也可以通过JS来调用项目中的代码。 Android与JS之间的桥梁就是WebView了,我们是通过WebView来实现他们的...

富江___ ⋅ 06/11 ⋅ 0

weex eros框架源码解析

weex eros是基于alibaba weex框架进行二次封装的客户端跨平台开发框架,主要是为前端开发者(可以不用熟悉客户端开发)提供的一站式客户端app开发解决方案。官网地址为:https://bmfe.github...

雅爸学技术 ⋅ 05/27 ⋅ 0

Airbnb: React Native 从选择到放弃

Airbnb 最近在 Medium 上发布了一系列文章详细描述了 Airbnb 与 React Native 从选择到放弃的整个心路历程。 React Native at Airbnb The Technology Building a Cross-Platform Mobile Tea...

banxi ⋅ 06/20 ⋅ 0

安卓应用安全指南 4.9 使用`WebView`

4.9 使用 原书:Android Application Secure Design/Secure Coding Guidebook 译者:飞龙 协议:CC BY-NC-SA 4.0 使你的应用能够集成 HTML / JavaScript 内容。 4.9.1 示例代码 我们需要采取...

apachecn_飞龙 ⋅ 03/24 ⋅ 0

android h5 js 匿名函数通信

android js 互相调用 支持js匿名函数接收 支持js json对象接收 支持js函数返回值获取 通过注解注入js方法,支持自定义方法名 github https://github.com/lwugang/android-js-bridge Add it i...

liwg ⋅ 04/25 ⋅ 0

React Native SDK for OSS

此文主要介绍 React Native SDK for OSS的方方面面,包括相关基本概念、项目背景、项目方案、环境搭建运行、使用姿势、注意事项等。文末的附件可运行Example Zip压缩包和针对新手的入门实用文...

zuozhao ⋅ 05/18 ⋅ 0

目前有成熟的App代码翻译技术吗?

大家好: 本人多年技术老鸟,现有抛出一个思考。针对目前市面上的移动互联网项目(主要指客户端)类型,无非以下几种主要类型: 原生App: iOS/Android H5响应式 H5套壳(PhoneGap/微信小程序/国...

瑾少 ⋅ 04/14 ⋅ 0

CC框架实践(3): 让jsBridge更优雅

前言 CC框架下如何让我们的jsBridge更加优雅? jsBridge是作为js和java之间通信的桥梁,本身它的职责只是完成通信。 本文不是介绍js与java通信过程的实现,你可以使用第三方库(如:JsBridg...

lucky_billy ⋅ 06/20 ⋅ 0

开发原生安卓cordova插件(有原生界面)

上文开发的插件没有调用原生界面,本文介绍开发带有activity的插件 本文很多操作与上文重复,重复部分会省略 首先打开plug1,先开发插件的原生代码 在以下命名空间创建一个activity 名称为A...

canneljls ⋅ 04/21 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Cube、Cuboid 和 Cube Segment

1.Cube (或Data Cube),即数据立方体,是一种常用于数据分析与索引的技术;它可以对原始数据建立多维度索引。通过 Cube 对数据进行分析,可以大大加快数据的查询效率 2.Cuboid 在 Kylin 中特...

无精疯 ⋅ 26分钟前 ⋅ 0

github太慢

1:用浏览器访问 IPAddress.com or http://tool.chinaz.com 使用 IP Lookup 工具获得github.com和github.global.ssl.fastly.net域名的ip地址 2:/etc/hosts文件中添加如下格式(IP最好自己查一...

whoisliang ⋅ 28分钟前 ⋅ 0

非阻塞同步之 CAS

为解决线程安全问题,互斥同步相当于以时间换空间。多线程情况下,只有一个线程可以访问同步代码。这种同步也叫阻塞同步(Blocking Synchronization). 这种同步属于一种悲观并发策略。认为只...

长安一梦 ⋅ 39分钟前 ⋅ 0

云计算的选择悖论如何对待?

人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云计算为...

linux-tao ⋅ 41分钟前 ⋅ 0

我的第一篇个人博客

虽然这是个技术博客,但是,我总是想写一些自己的东西,所有就大胆的在这里写下了第一篇非技术博客。技术博客也很久没有更新,个人原因。 以后自己打算在这里写一些非技术博客,可能个人观点...

Mrs_CoCo ⋅ 42分钟前 ⋅ 0

Redis 注册为 Windows 服务

Redis 注册为 Windows 服务 redis 注册为 windows 服务相关命令 注册服务 redis-server.exe –service-install redis.windows.conf 删除服务 redis-server –service-uninstall 启动服务 re......

Os_yxguang ⋅ 42分钟前 ⋅ 0

世界那么大,语言那么多,为什么选择Micropython,它的优势在哪?

最近国内MicroPython风靡程序界,是什么原因导致它这么火呢?是因为他功能强大,遵循Mit协议开源么? 错!因为使用它真的是太舒服了!!! Micropython的由来,这得益于Damien George这位伟大...

bodasisiter ⋅ 46分钟前 ⋅ 0

docker 清理总结

杀死所有正在运行的容器 docker kill $(docker ps -a -q) 删除所有已经停止的容器(docker rm没有加-f参数,运行中的容器不会删掉) docker rm $(docker ps -a -q) 删除所有未打 dangling 标...

vvx1024 ⋅ 56分钟前 ⋅ 0

关于学习

以前学车的时候,教练说了这样的一句话:如果一个人坐在车上一直学,一直学,反而不如大家轮流着学。因为一个人一直学,就没有给自己留空间来反思和改进。而轮流着学的时候大家下来之后思考上...

mskk ⋅ 今天 ⋅ 0

压缩工具之gzip-bzip2-xz

win下常见压缩工具:rar zip 7z linux下常见压缩工具:zip gz bz2 xz tar.gz tar.bz2 tar.xz gzip 不支持目录压缩 gzip 1.txt #压缩。执行后1.txt消失,生成1.txt.gz压缩文件 gzip -d 1.txt....

ZHENG-JY ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部