//判断访问终端
function browserVersion(){
var u = navigator.userAgent;
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('Adr') > -1, //android终端
iPhone: u.indexOf('iPhone') > -1 , //是否为iPhone或者QQHD浏览器
iPad: u.indexOf('iPad') > -1, //是否iPad
webApp: u.indexOf('Safari') == -1, //是否web应该程序,没有头部与底部
weixin: u.indexOf('MicroMessenger') > -1, //是否微信 (2015-01-22新增)
qq: u.match(/sQQ/i) == " qq" //是否QQ
};
移动开发中,JS与客户端的交互是一个关键议题。特别是在实现诸如通过JS获取手机GPS数据等可定制的功能时。这需要我们深入研究技术层面的探索,以及针对不同操作系统的处理方法,这些都是值得详细讨论的。
JS与客户端通信的必要性
在众多移动应用中,我们常需JS与客户端沟通。比如,在导航应用里,获取GPS数据以实现精确定位是关键。然而,这并非易事,因为背后涉及众多接口和安全机制。不同操作系统对信息获取的难度各不相同。以iOS系统为例,其封闭性使得没有现成的JS调用API来获取GPS数据,这就迫使我们必须寻找其他解决方案。
// rn js code
从实际应用和开发层面来看,若无法实现此类通信,众多功能将无法正常运作,这将对用户的使用体验造成重大影响。以一个定位社交应用为例,若无法获取位置坐标,其查找附近好友等核心功能将无法执行。
iOS中的特殊情况与解决
iOS有其独特之处。自从苹果在iOS8中推出了新的组件容器,只要APP支持iOS8或更高版本,就能使用这个新的浏览器控件。这样一来,JavaScript与客户端之间的交流就拥有了新的途径。
// h5 js code 将它封装一下
function createIframe(url){
var url = 'jsbridge://getShare?title=分享标题&desc=分享描述&link=http%3A%2F%2Fwww.douyu.com&cbName=jsCallClientBack';
var iframe = document.createElement('iframe');
iframe.style.width = '1px';
iframe.style.height = '1px';
iframe.style.display = 'none';
iframe.src = https://segmentfault.com/a/url;
document.body.appendChild(iframe);
setTimeout(function() {
iframe.remove();
}, 100);
}
在iOS系统上,若需通过JavaScript调用客户端功能,比如获取GPS数据,我们可以使用特定的网络请求技术。比如,通过发送遵循特定协议的请求,比如在URL后加上’://.?=’+(obj)这样的格式并附加参数,接着在客户端对请求进行拦截和解析,以此执行相应逻辑。这样的方法巧妙地解决了iOS系统缺少相应API的问题。
从提升开发速度的角度分析,虽然这种方法涉及必要的规则设定和代码撰写,但相比之下,它比探索其他繁琐的替代方案要简便且高效得多。以iOS通信框架中的业务层回调函数处理为例,该框架内也有一套完整的处理逻辑。
// IOS swift code
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
let url = request.URL
let scheme = url?.scheme
let method = url?.host
let query = url?.query
if url != nil && scheme == "jsbridge" {
switch method! {
case "getShare":
self.getShare()
default:
print("default")
}
return false
} else {
return true
}
}
安卓中的通信方式
安卓设备在通讯方面有特定的选择。从用户界面角度出发,我们建议使用协议来交流。通常情况下,会在几种方案中挑选一种,这样做有利于前端底层代码的维护和更新。
调试期间,安卓系统通过特定的符号“://”来进行调试,这一步骤有时还需借助翻墙等手段。相较之下,iOS系统则通过mac的选项进行调试。安卓与iOS在调试方法上的区别,实际上揭示了它们在系统构建和安全措施上的不同点。尽管安卓在特定协议下的调试可能有些繁琐,但它确实能确保通信流程的顺畅进行。
// IOS swift code
webview.stringByEvaluatingJavaScriptFromString("window.methodName()")
根据实际开发经验,安卓系统通过协议进行集成,这种方式使得与前端代码的融合更为便捷。它减少了模块之间的相互依赖,一旦出现故障,也能迅速找到并解决问题。
RN组件下的通信特点
RN组件实际上是对原生容器进行了二次包装。在RN环境中,通信过程相对简便,无需像在其他情况下那样直接依赖协议进行。只需借助浏览器进行信息传递,便可以达到常规通信的效果。
RN具备独特的通讯机制,如同为开发者搭建了一条高速通道。所有通信任务均由RN自动执行,这大大减少了开发者的时间和人力投入。
观察RN组件在多个成功项目中的应用,我们发现开发者无需过多精力投入于繁杂的通信底层逻辑,因而能将更多精力集中在业务逻辑的开发上。
// android JAVA code
class JSInterface {
@JavascriptInterface
public String getShare() {
//...
return "share";
}
}
webView.addJavascriptInterface(new JSInterface(), "AndroidNativeApi");
封装与优化的意义
// android JAVA code
class WebChromeClient extends WebChromeClient {
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
// 重写window下的prompt,通过result返回结果
}
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
}
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
}
}
将iOS和安卓系统进行统一封装,是业务层开发中一个高效的方法。这样做能有效降低开发人员因不同平台间通信差异而带来的麻烦。
比如,在核心封装的基础上进行改进,确保每个回调函数在执行完毕后自动销毁并释放内存。这样做有助于提升系统的性能和稳定性。若不进行此类优化,随着时间流逝和应用的持续使用,很可能会出现内存泄漏等问题,进而导致应用运行缓慢甚至出现崩溃。
// android JAVA code
webView.loadUrl("javascript:window.jsBridge.getShare()");
综合考虑整个项目的维护费用,统一封装和优化可以显著降低代码规模,增强代码的易读性和维护性,这对于项目的长期成长具有重要意义。
通信开发中的挑战与应对
// h5 js code
window.postMessage(data);
// rn js code
{
let { data } = e.nativeEvent;
//...
}}
/>
通信开发领域遇到了诸多挑战。调试不同操作系统时,比如在RN环境中,只能对RN代码进行调试,不能对其他代码进行调试。此外,在://符号下,还会出现样式上的问题。
面对这些挑战,开发者需不断提升个人技术水平,对各类操作系统特性有深入掌握。例如,在初期就设定样式规范和兼容策略,可避免问题蔓延。此外,开发团队内部需加强交流合作,对于调试等问题,要及时交流并共同寻求解决办法。
this.refs.webView.postMessage({
cbName: 'xxx',
param: {}
});
在开发过程中,你是否也遇到了JS与客户端间交流的难题?欢迎留言交流,同时别忘了点赞并转发本篇文章。