Android的webview是基于webkit内核的,webview中集成了js与java互调的接口函数,通过addJavas criptInterface方法,可以将Java的类注册进webkit,给网页上的js进行调用,而且还可以通过loadUrl方法是给webkit传递一个URL,供浏览器来进行解析,实现Java和js交互。要想运行网页上的js脚本,webview必须设置支持Javas cript。Java代码1mWebview.getSettings().setJavas criptEnabled(true);然后是设置webview要加载的网页:web的网页:webView.loadUrl("");本地的网页:webView.loadUrl(""); //本地的存放在:assets文件夹中webview做完基本的初始化后咱们还要要给它,加进一个回调的代理类Javas criptInterface,并给它一个调用的名称:ncpJava代码1mWebView.addJavas criptInterface(new Javas criptInterface(),"ncp");Javas criptInterface可以是一个普通的Java类,类实现的方法,均可被js回调:Java代码final class Javas criptInterface {public int callOnJs() {return 1000;}public void callOnJs2(String mode) {//TODO}}Java要调用js的方法,只需知道js的方法名称即可:Java代码1mWebView.loadUrl("javas cript:onSaveCallback()");js 这边就更简单:Js代码window.Onload= function(){document.getElementById('btn_1').addEventListener('click', onBtnClick, false);var _int_value = window.ncp.callOnJs();alert("get int from java:" + _int_value );}function onBtnClick() {window.ncp.callOnJs2("click");}
找一下appcan或者phonegap框架,这两个都有本地化的JS库可以进行你要的操作
1. 随着在MacOS上的Safari。点击Safari菜单,选择"Preferences…"(或按Command+,)
如果您使用的是Windows上的Safari。点击Gear icon,选择"Preferences"。
2. "Preferences"窗口中选择"Security"选项卡。
"Security"选项卡部分"Web content"标记"Enable Javascript"复选框。
3. 关闭Preferences弹出窗口,并刷新您的网页。
适用于iOS的Safari浏览器中的Javascript启用(iphone, ipod, ipad)
1. 命中Settings图标。
2. 向下滚动,直到您看到"Safari"点击它调出选项页。
3. "Javascript"选项,打开你做了iOS上的Safari中启用Javascript。
在我开始使用OpenAphid-Engine的时候,已经有几种类似的iOS/Android 项目.这些商业项目或者开源项目使用Javascript实现代码特性。比如,Titanium 和PhoneGap 允许开发者使用Javascript开发本地 iOS/Android apps;ngCore 更是可以使用纯正的Javascript构建跨平台的游戏。Javascript已经成为了编程语言中的佼佼者,也因为更容易学习吸引了众多开发者参与到这一领域。
怎样在IOS/Android上使用Javascript
主要有两种方法。一种是使用系统的浏览器组件(IOS中的UIWebView和Android中的WebView),另一方法就是使用整合好的Javascript引擎。
使用系统的浏览器组件比较容易实现但是更复杂,效率也低。 WebView提供了 addJavascriptInterface 把Java classes注入到Javascript文本的方法。但是它只支持最原始的几种数据类型,因此也局限了API设计。并且在Android 2.3模拟器上不稳定,在真机上也会遇到 issue #12987的问题。在IOS上更糟 UIWebView没有公共的APIs支持Javascript到Objective-C的交互(你必须使用似有的APIs才能达到与addJavascriptInterface相同的功能)。
PhoneGap 是基于 UIWebView and WebView的比较出名的项目。开发者被迫使用回调函数从Javascript APIs得到返回值。这在游戏上效率极低,也更为复杂。
早期的ngCore同样依赖UIWebView来支持iOS。但是这个机制由于其糟糕的表现被取代。
为了获得更好的表现、灵活性、兼容性,嵌入全功能的Javascript引擎变得更为有效。
选择Javascript 引擎
据我所知,iOS 或 android 上能够运行的Javascript 引擎有4个: JavascriptCore, SpiderMonkey, V8 and Rhino.下面这个表格展示各个引擎在iOS 和 Android 的兼容性
当我设计 OpenAphid-Engine 成为一个合适的Javascript的引擎的时候,我主要考量以下指标:
兼容性:同时支持iOS 和 Android 在x86 和 ARM 平台上的 模拟器和 设备。
稳定性. 稳定的运行在对应的平台和CPU的架构上。
扩展性. 能够很方便的利用本地特性进行扩展。例如OpenAphid-Engine 通过一个桥接层,实现了通过Javascript 进行OpenGL ES 的使用。
性能好:一个快速的Javascript 引擎主要归结为两个因素:有效的绑定机制和进行较低的开销。. OpenAphid-Engine 在渲染一帧页面的时候通过Javascript触发数百个OpenGL ES调用来进行渲染。这点是非常有意义的,如果只是把开销放到单纯的执行Javascript上进行将会导致渲染很慢,。
体积小.:在内存的占用上和自身的执行文件上都要比较小。
Rhino和 V8出现的最早,但是不支持iOS。我非常希望可以使用 V8开发 OpenAphid-Engine ,在初次使用时就发现它拥有优雅的代码结构,良好的表现,但是我非常失望,因为 V8只能在JIT模式下使用,而IOS不支持。除非你使用jailbroken设备。(详情请参考 issue #1312)
我在JavascriptCore和SpiderMonkey间纠结了很久。在成功部署了Android和IOS项目后,我通过实验找到更好的一个。
SpiderMonkey 容易得到开发权限,但是在与JavascriptCore比较时甘拜下风。SpiderMonkey产生了大量的二进制文件 (在ARMv7上大约1.3MB);Javascript执行得更慢,在Javascript和C++的桥接表现更为重要。另外一个让我远离SpiderMonkey的原因是在iOS模拟器上出现随机崩溃现象。
Javascript引擎会受很多东西影响,比如交叉编译器的版本、引擎的版本和操作系统的种类等。下表列举了几种运行在iPod Touch 4上引擎的运行时间。(有兴趣请于Google Doc查看精确的时间)
JavascriptCore 大比分领先。
我没有找到SpiderMonkey,所以就使用了下面的三种自定义搭建Cocos2d-iPhone-2.1-beta4, Cocos2d-x-2.1-beta3和iMonkey。
所有测试的apps都基于LLVM 4.1版本,所有的引擎都运行在解释器模式(iOS受限)。
几种基准的介绍:
1m-js_loop执行空循环一百万次。
1m-native_function请求调用一百万次返回undefined的本地函数
1m-js_function跟上面一个相同,只是换成了Javascript。
fib(30)递归的方式计算Fibonacci(30)。
sudoku-5用这里的算法解决Sudoku问题。
1m-native_function JavascriptCore使用可移植的C APIs实现,当然这不是最有效引入本地函数的方法。
SpiderMonkey 在台式电脑上由于高级的JIT追踪方法运行更快,但是在IOS设备上却与之相反。
在大部分的基准上,使用iMonkey比SpiderMonkey更快
很明显的,使用SpiderMonkey将会在iOS上获得更好的表现。ngCore 1.10在iOS上加入自定义功能,所以要更优于像SpiderMonkey这样的变体。
对于Javascript Code 的挑战
在我专心于 JavascriptCore之后,我的研究更进了一步:
1. 它在运行 一百万 次 native_function和 一百万次Math.abs(0) 的时间六倍于 使用 JavascriptCore.我观察到同样的性能问题出现在通过注入的方式访问对象的属性。
2. 利用 C APIs 进行设计虽然开发简单,但是缺乏灵活的内存管理机制。缺乏一个高级的内部垃圾回收机制很难解决类似于 circular references 的问题。
3. 众多的 JavascriptCore 正式版本都是可用的 。 不过 OpenAphid-Engine 是更好的一个,它不但速度快,而且相当小。
我抛弃了原来的使用 C APIs 方案因此解决了 问题 1 和 2. 使用的JSC 版本来自于iOS4.3.3,因为同样在解析器模式下这个版本相比来自于iOS 5 的版本更快,执行文件更小。
在其他产品上使用的JS引擎
在开发OpenAphid-Engine期间,我一直保持对其他引擎的关注,以下这个表格总结了其他JS引擎的使用情况
Javascript是前端开发的主要语言,我们可以通过编写Javascript程序来判断浏览器的类型及版本。Javascript判断浏览器类型一般有两种办法,一种是根据各种浏览器独有的属性来分辨,另一种是通过分析浏览器的userAgent属性来判断的。在许多情况下,值判断出浏览器类型之后,还需判断浏览器版本才能处理兼容性问题,而判断浏览器的版本一般只能通过分析浏览器的userAgent才能知道。
浏览器类型
⑴浏览器特有属性
⑵根据userAgent
浏览器版本
⑴根据userAgent
对于手机浏览器判断
1.如何判断是否为移动终端 利用正则match,
匹配navigator.userAgent是否含有字符串AppleWebKit*****Mobile
安卓qq浏览器HD版 只有AppleWebKit
2手机语言版本的判断
使用navigator.browserLanguage 便可得出windows phone语言版本,
当然可恶的小小手机语言版本也有兼容性的差异,兼容Mozilla,以及AppleWebKit内核的浏览器访问其语言版本,它会列出 navigator.language
CODE:
script type="text/Javascript"
var browser={
versions:function(){
var u = navigator.userAgent, app = navigator.appVersion;
return { //移动终端浏览器版本信息
trident: u.indexOf('Trident') -1, //IE内核
presto: u.indexOf('Presto') -1, //opera内核
webKit: u.indexOf('AppleWebKit') -1, //苹果、谷歌内核
gecko: u.indexOf('Gecko') -1 u.indexOf('KHTML') == -1, //火狐内核
mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
android: u.indexOf('Android') -1 || u.indexOf('Linux') -1, //android终端或uc浏览器
iPhone: u.indexOf('iPhone') -1 , //是否为iPhone或者QQHD浏览器
iPad: u.indexOf('iPad') -1, //是否iPad
webApp: u.indexOf('Safari') == -1 //是否web应该程序,没有头部与底部
};
}(),
language:(navigator.browserLanguage || navigator.language).toLowerCase()
}
document.writeln("语言版本: "+browser.language);
document.writeln(" 是否为移动终端: "+browser.versions.mobile);
document.writeln(" ios终端: "+browser.versions.ios);
document.writeln(" android终端: "+browser.versions.android);
document.writeln(" 是否为iPhone: "+browser.versions.iPhone);
document.writeln(" 是否iPad: "+browser.versions.iPad);
document.writeln(navigator.userAgent);
/script
比较特别的地方
UC浏览器没有安卓报头,只返回:linux ,这里粗略的根据linux来判断是安卓(前提必须满足是移动终端,UC这点是满足的)
安卓QQ浏览器HD版检测的结果是:mac, Safari
在 APP 中,免不了与 H5页面打交道,所以掌握 与 JS 交互就显的至关重要,本文总结了常见的与 JS 交互方式。
注意事项
在 OC 原生中
在 html 文件中
早期的JS与原生交互的开源库很多都是用得这种方式来实现的,例如:PhoneGap、 WebViewJavascriptBridge 。
效果图
使用WKNavigationDelegate中的代理方法,拦截自定义的 URL 来实现 JS 调用 OC 方法。
注意点
关于如何区分执行不同的OC 方法,也与UIWebView的处理方式一样,通过URL 的host 来区分执行不同的方法:
JS 调用OC 方法后,有的操作可能需要将结果返回给JS。这时候就是OC 调用JS 方法的场景。
WKWebView 提供了一个新的方法 evaluateJavascript:completionHandler: ,实现OC 调用JS 等场景。
注意点
运行结果
在iOS 7之后,apple添加了一个新的库JavascriptCore,用来做JS交互,因此JS与原生OC交互也变得简单了许多。
首先导入JavascriptCore库, 然后在OC中获取JS的上下文。
再然后定义好JS需要调用的方法,例如JS要调用share方法:
则可以在UIWebView加载url完成后,在其代理方法中添加要调用的share方法:
OC 调用 JS 方法有多种,首先介绍使用JavascriptCore框架的方式。
使用JSContext 的方法 -evaluateScript ,可以实现 OC 调用 JS 方法
效果图
使用WKWebView的时候,如果想要实现JS调用OC方法,除了拦截URL之外,还有一种简单的方式。那就是利用WKWebView的新特性MessageHandler来实现JS调用原生方法。
创建 WKWebViewConfiguration 对象,配置各个API对应的MessageHandler。
然后在界面即将显示的时候添加MessageHandler
需要注意的是addScriptMessageHandler很容易引起循环引用,导致控制器无法被释放,所以需要移除MessageHandler
这里实现了两个协议 WKUIDelegate,WKScriptMessageHandler , WKUIDelegate 是因为我在JS中弹出了alert 。 WKScriptMessageHandler 是因为我们要处理JS调用OC方法的请求。
WKScriptMessage 有两个关键属性 name 和 body 。
因为我们给每一个OC 方法取了一个name,那么我们就可以根据name 来区分执行不同的方法。body 中存着JS 要给OC 传的参数。
关于参数body 的解析,我就举一个body中放字典的例子,其他的稍后可以看demo。
解析JS 调用OC 实现分享的参数:
message.boby 就是JS 里传过来的参数。我们不同的方法先做一下容错性判断。然后正常取值就可以了。
下面只列举一个shareClick()方法,其他看Demo
这里使用WKWebView 实现OC 调用JS方法与之前说的文章一样,通过
- evaluateJavascript:completionHandler:
效果图如下图所示
详情看下面文章链接
iOS下 JS 与 OC 互相调用(五) - UIWebView+WebViewJavascriptBridge
详情看下面文章链接
iOS下 JS 与 OC 互相调用(六) - WKWebView+WKWebViewJavascriptBridge
iOS下 JS 与OC 互相调用(一) - UIWebView 拦截 URL
iOS下 JS 与OC 互相调用(二) - JavascriptCore
iOS 下 JS 与 OC 互相调用(三) - WKWebView 拦截 URL
iOS下JS与OC互相调用(四)-MessageHandler
iOS下 JS 与 OC 互相调用(五) - UIWebView+WebViewJavascriptBridge
iOS下 JS 与 OC 互相调用(六) - WKWebView+WKWebViewJavascriptBridge