阅读 635

前端学习笔记:通过H5页面调用不同客户端的原生页面

前言

昨天遇到一个非常有趣的需求场景,背景如下:我们是一家电商平台,经常会做一些商品的促销专题活动。昨天我司产品经理找到我和APP的开发工程师,希望我们解决一个问题:在APP端点击专题活动中的商品,打开的页面是H5页面,而不是客户端的原生页面。产品经理希望打开原生页面,以让用户获得更好的体验。见下图,左图是在APP中打H5页面,右图是在APP中打开APP原生页面。

原因

发现了问题以后,我初步了解了导致这个问题的原因。原来,APP端展示的专题活动页面和小程序一样,采用的是webview的解决方案,即APP指定一个对象(我觉得是路径,不过据我司APP开发工程师介绍,APP中只有对象的说法,没有路径的说法),接收H5页面的链接,并将链接中的HTML铺到APP的对象(路径)中。用户点击专题中的商品链接也是同样的方式,因此最后展示出来的商品详情页就是H5页面,而不是客户端的原生页面。

小程序、安卓、苹果各不相同

小程序的处理逻辑

我目前在公司主要是负责小程序端的。在此之前,我接触过小程序类似的业务场景。在小程序中如果想要实现类似的逻辑,需要在H5页面的头部引入一段JS代码。这段JS代码的主要作用,是在window对象中加入一个新的名为wx的属性。这个属性是一个对象,有自己的属性和方法。通过调用wx.miniProgram.getEnv()方法,并传入一个回调函数,即

wx.miniProgram.getEnv(res => {
    if(res.miniProgram) {
        //小程序环境
        let url;
        wx.miniProgram.navigateTo({url: url});
    } else {
        //微信中打开内置浏览器
    }
})
复制代码

以上判断完成之后,就完成了在小程序端跳转到原生页面的逻辑。

安卓客户端的处理逻辑

因为有这个基础,我下意识认为APP端如果想要实现类似的逻辑,也需要先引入一段类似的JS代码。但和APP工程师沟通后发现,客户端的API已经支持了这段JS代码需要实现的功能。我司APP工程师还给我展示了一段之前使用的代码:

if(window.android) { //判断android对象是否存在
   window.android.navigateTo(url); //调用android分享
} else {
   //调用ios支付方法!
   window.webkit.messageHandlers.navigateTo.postMessage(url);
}
复制代码

我的猜想是这样的:客户端(Android、iOS)中APP工程师通过API提供的方法,给JS的执行环境window增加了对应的属性:Android客户端增加的属性是android,iOS客户端增加的属性是webkit。这两个属性都是对象,在给这两个属性增加对应的方法以后,就可以直接在JS代码中引用了。为了证明我的猜想,我特意百度了一下“通过js调用android原生方法”,发现了以下这段代码。

//设置webview
myWebView = (WebView) findViewById(R.id.myWebView);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(new JavaScriptinterface(this),"android");
myWebView.setWebViewClient(new myWebViewClient());

//创建JavaScriptinterface类
public class JavaScriptinterface {
    Context context;
    public JavaScriptinterface(Context c) {
        context= c;
    }

    /**
     * 与js交互时用到的方法,在js里直接调用的
     */
    @JavascriptInterface
    public void showToast(String ssss) {

        Toast.makeText(mContext, ssss, Toast.LENGTH_LONG).show();
    }
}

//在JS中调用android原生方法
<script type="text/javascript">   
function showToast() {       
    android.showToast("哈哈啊哈 ");
     }
</script>

</head>
<body>
<input type="button" value="调用"
     onClick="showToast()"/>
</body>
复制代码

虽然没有学过客户端的相关知识,但这个逻辑还是一目了然的。从这段代码也可以看出,安卓客户端除了可以指定方法的名称外,还可以指定设置在window对象下的属性的名称,也就是上一行代码中的window.android。你可以改成window.Android、window.app,由app工程师指定。

确认该属性的名称后,再为这个属性添加方法,这个方法由H5页面的前端工程师和app开发工程师约定名字。app开发工程师实现逻辑跳转,前端工程师直接引用,即可实现跳转到app的原生页面。

苹果客户端的解决逻辑

与安卓客户端的实现逻辑一样,苹果客户端也是在window对象下添加指定的属性,在该属性下面添加方法,即可跳转到指定的app原生页面。不过需要注意的是,由于客户端API版本的不同,可能引用的方式也不同。目前我已经接触到了以下两个引用方式:

//第一种引用方式
window.webkit.messageHandlers.shareLink.postMessage(shareData);
//第二种引用方式
window.RequiredSkill.shareLink(shareData)
复制代码

总结

由于之前主要工作在小程序端,所以初次接触该问题时,习惯性的用了小程序的处理思路。也是第一次接触到和客户端的JS交互方式,感觉比较有意思,所以记录下来。

另外一个收获是,以前一直以为window对象就是指浏览器中的window;但通过解决这个问题发现,小程序、APP端也有相应的window对象,而且小程序和APP端的window对象还有独有的属性。想想确实是这个道理,不同的浏览器window对象的属性都不同,更何况不同的客户端?

关注下面的标签,发现更多相似文章
评论