WebView与JS的几种交互

http://www.jianshu.com/p/0042d8eb67c0

最近整理了一下原生与H5之间的交互方式,简单的做个总结。
OC端与JS的交互,大致有这几种:拦截协议、JavaScriptCore库、WKWebView、自定义NSURLProtocol拦截、WebViewJavascriptBridge。

  1. JavaScriptCore一个iOS7引进的标准库,iOS7以前也有开发者自行导入使用。Web端也比较容易统一。
  2. WebViewJavascriptBridge是一个第三方库,其原理还是使用了对web view的请求拦截,支持WKWebview。封装了完整的OC与JS相互调用的方法,不过需要Web端配合编写相应的方法。安卓方面听说有一个同名的库,如果不是统一使用的话,需要Web端写2套JS的话,那就有点蛋疼了。
  3. WKWebView,iOS8加入的WebKit。相对于UIWebView,具有更强大的功能。提供一个WKScriptMessageHandler,可以实现JS对WebView的调用。
  4. 协议的拦截,比较常用的一种方式。
  5. 在自定义NSURLProtocol中,拦截请求,也可以实现相应的方法调用。

1. JavaScriptCore



JavaScriptCore中类及协议:

  • JSContext:给JavaScript提供运行的上下文环境,通过-evaluateScript:方法就可以执行一JS代码
  • JSValue:封装了JS与ObjC中的对应的类型,以及调用JS的API等
  • JSManagedValue:管理数据和方法的类
  • JSVirtualMachine:处理线程相关,使用较少
  • JSExport:这是一个协议,如果采用协议的方法交互,自己定义的协议必须遵守此协议,在协议中声明的API都会在JS中暴露出来,才能调用

对于JSContext和JSValue的更多使用方式可以看下这篇,介绍的比较完整ios7 JavaScriptCore.framework 本文主要简单总结下交互相关内容。

ObjC调用JS

在JavaScriptCore中提供的调用JS的方法
- (JSValue *)evaluateScript:(NSString *)script;方法就可以执行一段JavaScript脚本,并且如果其中有方法、变量等信息都会被存储在其中以便在需要的时候使用。
JSValue提供了- (JSValue *)callWithArguments:(NSArray *)arguments;方法可以反过来将参数传进去来调用方法

 // 一个JSContext对象,就类似于Js中的window,
 // 只需要创建一次即可。
JSContext *context = [[JSContext alloc] init];
// 执行一段js
[context evaluateScript:@"function add(a, b) { return a + b; }"];
// 根据下标取出方法
JSValue *add = context[@"add"];
NSLog(@"Func: %@", add);
// 传入参数 调用取到的方法
JSValue *sum = [add callWithArguments:@[@(7), @(21)]];
NSLog(@"Sum: %d",[sum toInt32]);
//OutPut:
// Func: function add(a, b) { return a + b; }
// Sum: 28

再来个栗子

 self.jsContext = [[JSContext alloc] init];

 [self.jsContext evaluateScript:@"var num = 10"];
 [self.jsContext evaluateScript:@"var squareFunc = function(value) { return value * 2 }"];
 // 调用 计算面积
 JSValue *square = [self.jsContext evaluateScript:@"squareFunc(num)"];

 // 可以通过下标的方式获取到方法
 JSValue *squareFunc = self.jsContext[@"squareFunc"];
 // 传入参数 调用取到的方法
 JSValue *value = [squareFunc callWithArguments:@[@"20"]];
 NSLog(@"%@", square.toNumber);
 NSLog(@"%@", value.toNumber);

JS调用OC

使用JavaScriptCore进行原生与js的交互主要是2种方式,block注入模型使用协议代理

Block方式

JSContext *context = [[JSContext alloc] init];
// 定义一个block
context[@"log"] = ^() {
  NSLog(@"+++++++Begin Log+++++++");  

  NSArray *args = [JSContext currentArguments];
  for (JSValue *jsVal in args) {
   NSLog(@"%@", jsVal);
  }

  JSValue *this = [JSContext currentThis];
  NSLog(@"this: %@",this);
  NSLog(@"-------End Log-------");
};
// 调用js执行log方法
 [context evaluateScript:@"log(‘ider‘, [7, 21],
 { hello:‘world‘, js:100 });"];

当web端调用log方法,传入相关参数,就能调用OC端的block。实现交互。

通过注入模型的方式交互

  • OC端要做的事情

首先,我们自定义一个协议,而且这个协议必须要遵守JSExport协议
协议暴露的方法,是供JS调用的方法。还可以实现回调

@protocol JavaScriptObjectiveCDelegate <JSExport>

// JS调用此方法来调用OC的相机
- (void)callSystemCamera;

// 在JS中调用时,函数名应该为showAlertMsg(arg1, arg2)
// 这里是只两个参数的。
- (void)showAlert:(NSString *)title msg:(NSString *)msg;

// 通过JSON传过来
- (void)callWithDict:(NSDictionary *)params;
// JS调用Oc,然后在OC中通过调用JS方法来传值给JS。
- (void)jsCallObjcAndObjcCallJsWithDict:(NSDictionary *)params;

@end

接下来,我们还需要定义一个模型:

// 此模型用于注入JS的模型,这样就可以通过模型来调用方法。
@interface HYBJsObjCModel : NSObject <JavaScriptObjectiveCDelegate>

@property (nonatomic, weak) JSContext *jsContext;
@property (nonatomic, weak) UIWebView *webView;

@end

模型的实现:

@implementation HYBJsObjCModel

- (void)callWithDict:(NSDictionary *)params {
 NSLog(@"Js调用了OC的方法,参数为:%@", params);
}

// JS调用了callSystemCamera
- (void)callSystemCamera {
 NSLog(@"JS调用了OC的方法,调起系统相册");

 // JS调用后OC后,可以传一个回调方法的参数,进行回调JS
 JSValue *jsFunc = self.jsContext[@"jsFunc"];
 [jsFunc callWithArguments:nil];
}

- (void)jsCallObjcAndObjcCallJsWithDict:(NSDictionary *)params {
 NSLog(@"jsCallObjcAndObjcCallJsWithDict was called, params is %@", params);

 // 调用JS的方法
 JSValue *jsParamFunc = self.jsContext[@"jsParamFunc"];
 [jsParamFunc callWithArguments:@[@{@"age": @10, @"name": @"lili", @"height": @158}]];
}

// 指定参数的用法
// 在JS中调用时,函数名应该为showAlertMsg(arg1, arg2)
- (void)showAlert:(NSString *)title msg:(NSString *)msg {
 dispatch_async(dispatch_get_main_queue(), ^{
   UIAlertView *a = [[UIAlertView alloc] initWithTitle:title message:msg delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
   [a show];
 });
}
@end

JavaScriptCore使用注意

JavaScript调用本地方法是在子线程中执行的,这里要根据实际情况考虑线程之间的切换。

模型实现完了,在哪里注入呢。在controller的webView加载完成后
我们是通过webView的valueForKeyPath获取的,其路径为documentView.webView.mainFrame.javaScriptContext
这样就可以获取到JS的context,然后为这个context注入我们的模型对象。

#pragma mark - UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
 self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
  // 通过模型调用方法,这种方式更好些。
  HYBJsObjCModel *model  = [[HYBJsObjCModel alloc] init];
  // 模型
  self.jsContext[@"OCModel"] = model;
  model.jsContext = self.jsContext;
  model.webView = self.webView;
  // 增加异常的处理
  self.jsContext.exceptionHandler = ^(JSContext *context,
 JSValue *exceptionValue) {
    context.exception = exceptionValue;
    NSLog(@"异常信息:%@", exceptionValue);
 };
}

另外关于模型,也可根据需求直接将模型作为controller,去实现相关的方法实现,省去模型这一层。 如下:

#pragma mark - UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
  self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
  self.jsContext[@"OCModel"] = self;
  self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
  context.exception = exceptionValue;
  NSLog(@"异常信息:%@", exceptionValue);
 };
}
  • WEB端

    代码内容

<!DOCTYPE html>
<html>
<head lang="en">
     <meta charset="UTF-8">
</head>
<body>
     <div style="margin-top: 100px">
        <h1>Objective-C和JavaScript交互的那些事</h1>
        <input type="button" value="CallCamera" onclick="OCModel.callCamera()">
      </div>

       <div>
         <input type="button" value="Share" onclick="callShare()">
       </div>
<script>
       var callShare = function() {
          OCModel.share({‘title‘: ‘标题‘, ‘desc‘: ‘内容‘, ‘shareUrl‘: ‘http://www.jianshu.com/p/f896d73c670a‘);
       }

       var picCallback = function(photos) {
       alert(photos);
       } 

       var shareCallback = function(){
       alert(‘success‘);
       }
</script>
</body>
</html>

以上就是简单的利用JavaScriptCore framework进行JS交互的用法,
感谢
iOS与JS交互实战篇(ObjC)
Objective-C与JavaScript交互的那些事
提供的资料参考,仅仅是做个总结

2. WebViewJavascriptBridge

这个第三方库起先是在UIWebView与JS的深度交互大神文中知悉。其还是使用拦截WebView请求方法,但是做了完整的封装后,使用起来还是很简单的。

1) 导入

#import "WKWebViewJavascriptBridge.h"

2) 初始化

self.bridge = [WebViewJavascriptBridge bridgeForWebView:webView];
// 开启日志,方便调试
[WebViewJavascriptBridge enableLogging];

3) Web端setupWebViewJavascriptBridge

function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement(‘iframe‘);
WVJBIframe.style.display = ‘none‘;
WVJBIframe.src = ‘wvjbscheme://__BRIDGE_LOADED__‘;
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}

4)call setupWebViewJavascriptBridge

setupWebViewJavascriptBridge(function(bridge) {

/* Initialize your app here */

bridge.registerHandler(‘JS Echo‘, function(data, responseCallback) {
    console.log("JS Echo called with:", data)
    responseCallback(data)
})
bridge.callHandler(‘ObjC Echo‘, function responseCallback(responseData) {
    console.log("JS received response:", responseData)
})
})

  • ObjC API

OC端初始化时 默认消息处理器

实例化WebViewJavascriptBridge并定义native端的默认消息处理器。

JS调用bridge.send()即可触发默认处理。

    _bridge = [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponse *response) {
        NSLog(@"ObjC received message from JS: %@", data);
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"ObjC got message from Javascript:" message:data delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
    }];

OC端调用[self.bridge send];即可触发JS端的默认处理。

    [self.bridge send:@"Give me a response, will you?" responseCallback:^(id responseData) {
    NSLog(@"ObjC got its response! %@", responseData);
    }];

OC端registerHandler接收JS调用

在JS中调用了bridge.callHandler(‘getScreenHeight‘)就会触发OC注册的对应的handler,responseCallback中回调JS传递参数

    [self.bridge registerHandler:@"getScreenHeight" handler:^(id data, WVJBResponseCallback responseCallback) {
      NSLog(@"ObjC Echo called with: %@", data);
      responseCallback([NSNumber numberWithInt:[UIScreen
      mainScreen].bounds.size.height]);
    }];

或者 JS传递data给OC,OC打印

    [self.bridge registerHandler:@"log" handler:^(id data, WVJBResponseCallback responseCallback) {
    NSLog(@"Log: %@", data);
    }];

OC端callHandler调用JS

调用JS showAlert,传递data

[self.bridge callHandler:@"showAlert" data:@"Hi from ObjC to JS!"];

调用JS getCurrentPageUrl,在block中获取参数

[self.bridge callHandler:@"getCurrentPageUrl" data:nil responseCallback:^(id responseData) {
    NSLog(@"Current UIWebView page URL is: %@", responseData);
}];
还可设置代理监听
[bridge setWebViewDelegate:(UIWebViewDelegate*)webViewDelegate];
  • Javascript API

JS registerHandler接收OC调用

注册handle,OC可以通过[bridge callHandler:"handlerName" data:@"Foo"][bridge callHandler:"handlerName" data:@"Foo" responseCallback:^(id responseData) { ... }]进行调用JS

OC传递data进行调用

bridge.registerHandler("showAlert", function(data) { alert(data) })

参数结果回传给OC

bridge.registerHandler("getCurrentPageUrl", function(data, responseCallback) {
responseCallback(document.location.toString())
})
bridge.callHandler("handlerName", data)

JS 调用OC

JS调用bridge.callHandler("handlerName", data)bridge.callHandler("handlerName", data, function responseCallback(responseData) { ... })

调用OC端打印

bridge.callHandler("Log", "Foo")

调用OC端获取高度,在block中使用

bridge.callHandler("getScreenHeight", null, function(response) {
alert(‘Screen height:‘ + response)
})

3.WKWebView - iOS8 or Later

iOS8,苹果新推出了WebKit,用WKWebView代替UIWebView和WebView。相关的使用和特性可以细读。
WKWeb?View
iOS 8 WebKit框架概览(下)
WKWebView特性及使用

  • WKWebView新特性

    性能、稳定性、功能大幅度提升
    允许JavaScript的Nitro库加载并使用(UIWebView中限制)
    支持了更多的HTML5特性
    高达60fps的滚动刷新率以及内置手势
    GPU硬件加速
    KVO
    重构UIWebView成14类与3个协议,查看官方文档

需要注意的是WKWebView貌似不支持NSURLProtocol和NSURLCache。不能做缓存的话,就蛋疼了。

关于WKWebView的代理方法 这篇有比较完整的介绍
http://www.jianshu.com/p/1d7a8525ad16

下面是相关的交互方法


  • app调js方法

WKWebView调用js方法和UIWebView类似,一个是evaluateJavaScript,一个是stringByEvaluatingJavaScriptFromString。获取返回值的方式不同,WKWebView用的是回叫函数获取返回值

 //直接调用js
    webView.evaluateJavaScript("hi()", completionHandler: nil)
//调用js带参数
    webView.evaluateJavaScript("hello(‘liuyanwei‘)", completionHandler: nil)
// 调用js获取返回值
   webView.evaluateJavaScript("getName()") { (any,error) -> Void in
        NSLog("%@", any as! String)
    }
  • js调app方法

UIwebView没有js调app的方法,而在WKWebView中有了改进。具体步骤分为app注册handler,app处理handler委托,js调用三个步骤

  1. 注册handler需要在webView初始化之前,如示例,注册了一个webViewApp的handler

         config = WKWebViewConfiguration()
          //注册js方法
         config.userContentController.addScriptMessageHandler(self, name: "webViewApp")
          // 初始化
         webView = WKWebView(frame: self.webWrap.frame, configuration: config)
  2. 处理handler委托。ViewController实现WKScriptMessageHandler委托的func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage)代理方法。在里面处理事件。
         //实现WKScriptMessageHandler委托
         class ViewController:WKScriptMessageHandler
         //实现js调用ios的handle委托
         func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
         //接受传过来的消息从而决定app调用的方法
          let dict = message.body as! Dictionary<String,String>
          let method:String = dict["method"]!
          let param1:String = dict["param1"]!
          if method=="hello"{
              hello(param1)
            }
          }
  3. js调用 。通过window.webkit.messageHandlers.webViewApp找到之前注册的handler对象,然后调用postMessage方法把数据传到app,app通过上一步的方法解析方法名和参数。webViewApp是之前注册的name
     var message = {
                     ‘method‘ : ‘hello‘,
                     ‘param1‘ : ‘liuyanwei‘,
                     };
     window.webkit.messageHandlers.webViewApp.postMessage(message);

如果需要app对js的调用有所响应,可以通过回叫函数的方式回应js。可以在调用app的时候增加一个js回叫函数名 ,app在处理完之后可以呼叫回叫函数并把需要的参数通过回叫函数的方式进行传递

  • 使用用户脚本来注入 JavaScript

WKUserScript 允许在正文加载之前或之后注入到页面中。这个强大的功能允许在页面中以安全且唯一的方式操作网页内容。

一个简单的例子如下,用户改变背景的用户脚本被插入到网页中:

let source = "document.body.style.background = \"#777\";"
let userScript = WKUserScript(source: source,     injectionTime: .AtDocumentEnd, forMainFrameOnly: true)

let userContentController = WKUserContentController()
userContentController.addUserScript(userScript)

let configuration = WKWebViewConfiguration()
configuration.userContentController = userContentController
self.webView = WKWebView(frame: self.view.bounds, configuration: configuration)

WKUserScript 对象可以以 JavaScript 源码形式初始化,初始化时还可以传入是在加载之前还是结束时注入,以及脚本影响的是这个布局还是仅主要布局。于是用户脚本被加入到 WKUserContentController 中,并且以 WKWebViewConfiguration 属性传入到 WKWebView 的初始化过程中。

4. 拦截协议

最简单也是最容易想到的一种
UIWebView的代理方法,web view发出请求后拦截,查看是否为约定的协议,采取处理。

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSString *url = request.URL.absoluteString;
    if ([url rangeOfString:@"camera://"].location != NSNotFound) {
        // url的协议头是camera
        NSLog(@"callCamera");
        return NO;
    }
    return YES;
}

WKWebView

-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    NSString *url = navigationAction.request.URL.absoluteString;
    NSLog(@"%@",url);

    if (navigationAction.navigationType == WKNavigationTypeLinkActivated  && [url rangeOfString:@"camera://"].location != NSNotFound)
    {
        // url的协议头是camera
        NSLog(@"callCamera");
        decisionHandler(WKNavigationActionPolicyCancel);

        // dosomthing。。。
    }
    else
    {
        decisionHandler(WKNavigationActionPolicyAllow);
    }

}

5. NSURLProtocol拦截

这种方式也是最近才看到,原本利用自定义NSURLProtocol来做缓存处理。相关的文章可以看:
NSURLProtocol和NSRunLoop的那些坑
iOS中的 NSURLProtocol
在自定义的Protocol的- (void)startLoading方法中,可以拦截到请求。一般会在这里做缓存的判断与读取处理。在此处,也可以判断约定的协议,然后发送通知,客户端就可以接收到通知,执行相应的方法。

- (void)startLoading
{
    NSString * url = [[[self request] URL] absoluteString];

    if([url hasPrefix:@"LocalActions/"])
    {
        NSString * actname = [url stringByReplacingOccurrencesOfString:@"LocalActions/" withString:@"LocalAction_"];

        // 发送通知  客户端就可执行方法
        [[NSNotificationCenter defaultCenter] postNotificationName:actname object:nil];
    }
}

需要注意的是WKWebView貌似不支持NSURLProtocol和NSURLCache。不能做缓存的话,就蛋疼了。

相关参考
iOS与JS交互实战篇(ObjC版)
Objective-C与JavaScript交互的那些事

文/谈Xx(简书作者)
原文链接:http://www.jianshu.com/p/0042d8eb67c0
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

时间: 2024-10-05 08:01:31

WebView与JS的几种交互的相关文章

webview与JS的交互

一:hybird app, web app 和 native app 的区别   Web App Hybird App 混合Native App 开发成本 低 中 高 维护更新 简单 简单 复杂 体验 差 优 优 跨平台 优 优 差 Native App是一种基于智能手机本地操作系统如IOS,Android等并运用原生程序编写运行的第三方运用程序,也叫本地App. Web App 是针对Iphone,Android优化后的web站点,前端使用的技术是:html5,css,javascript等,

Android中WebView的JavaScript代码和本地代码交互的三种方式

一.Android中WebView的漏洞分析 最近在开发过程中遇到一个问题,就是WebView使用的时候,还是需要解决之前系统(4.2之前)导致的一个漏洞,虽然现在这个系统版本用户很少了,但是也不能忽视,关于这个漏洞,这里就不多做解释了,可能有的同学早就了解了,本来想写一篇文章详细介绍一下,但是网上的知识太多了,而且都很详细,就没弄了,这里大致简单明了的说几句: 第一.漏洞产生的原因 这个漏洞导致的原因主要是因为Android中WebView中的JS访问本地方法的方式存在缺陷,我们做过交互的都知

WebView与Js交互

上周五,老大让暂时搞一个评分app,俩页面.第一个页面显示全部待评分的物业,第二个页面是相应物业的评分页面.评分页面是表格样式的,所以就让web端的同学写个html,我们通过Webview去展示. 这里不不过展示就完了,web页面须要知道我们点击的哪个物业以及所填评委的名字并显示在html上.所以client须要把这两个值传给html.当评委评分完后点击html里的提交button并提交成功后.client也须要进行响应.做法就是client提供接口,js代码去调用来获取值--JS调用Andro

安卓webview和js+html交互利用的addJavascriptInterface和webview.loadUrl(&quot;javascript:**&quot;);

近期做一个项目需要把一个 服务支持的界面用webview来显示..呀 html白雪了js更是一样啥也不会,相信很多初学屌丝员跟我一样,, html开发工具都不知道怎么写..哈哈哈.....现在把做完的结果分享一下先上图了 ,, 这是从项目中特意分离出来的demo这里之上一些关键代码 源码下载地址  http://download.csdn.net/download/yung7086/7554309 步骤 首先在assets目录下建一个html文件 <!DOCTYPE html PUBLIC &quo

android webview和js的交互

第一步: mainfest.xml中加入网络权限 <use-permission android:name="android.permission.INTERNET"/> 如果是访问本地的那就不需要加这个权限了 第二步: 加载本地写好的html文件(定义好js中提供给android调用的方法funFromjs(),和android提供给js调用的对象接口) fun1FromAndroid(String name)),放在assets目录下. eg. <body>

浅谈webview与js交互

浅谈下webview与js的交互,项目中因为需要获取页面中的许多属性,所以用到了这些,让后端在方法中传了过来. 下面的demo是本地的html代码,具体可以仿写,都差不多,注重思想. 1:项目目录 2:jump的代码 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=GBK"/> <script type="text/

android webview与js简单的交互方案

最近研究webview与js交互,看了几个开源库实现,感觉不尽如人意,存在主要问题是,耦合较高,使用不够简洁,后来参考Uri设定规则,格局Uri类似协议自定义了类似的js交互协议 比较简洁,自定义协议内容样式如:jsbridge://android-app/method123?a=123&b=345#jsMethod1(p1,p2) 协议说明: scheme定义为jsbridge,用于区分别的网络请求(http),authority定义为android-app,区分不同平台处理path定义为 调

Android WebView与JS的交互方式 最全面汇总

前言 现在很多App里都内置了Web网页(Hyprid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图 上述功能是由Android的WebView实现的,其中涉及到Android客户端与Web网页交互的实现 今天我将全面介绍Android通过WebView与JS交互的全面方式 阅读本文前请先阅读:Android开发:最全面.最易懂的Webview详解 目录 1. 交互方式总结 Android与JS通过WebView互相调用方法,实际上是: Android去调用JS的代码 JS去调用

Android混合开发之WebViewJavascriptBridge实现JS与java安全交互

前言: 为了加快开发效率,目前公司一些功能使用H5开发,这里难免会用到Js与Java函数互相调用的问题,这个Android是提供了原生支持的,不过存在安全隐患,今天我们来学习一种安全方式来满足Js与java互相调用的需求.它就是WebViewJavascriptBridge. 学习动机: 先看下之前的解决办法:Android混合开发之WebView与Javascript交互 最近棒棒安全的一个市场推广来我们公司推广他们的产品,当时也没太引起我的注意,后来这个市场推广人员把我们的app的进行了他们