ExMobi+Agile Lite开发内置浏览器APP

Stella981
• 阅读 790

微信对内置浏览器的定制封装,使得H5的流量入口再次重新被定义。在原生程序中使用H5也成为非常必要的一种搭配。这也得益于H5对于简单的浏览性质的内容可以很好的进行展现和传播。

由于在实际项目中有需要在移动端使用到H5,而大部分H5页面都是来源于网络的,所以这里尝试使用ExMobi+Agile Lite来开发一个内置浏览器的功能。

相对于传统的浏览器功能,由于移动端具有丰富的本地能力可以调用,比如:二维码扫描、本地存储、各类第三方SDK分享等等,让移动端的浏览器可以更加个性化。

而我们一般看到的移动端浏览器功能通常包括:

1.输入地址跳转页面或者输入关键字搜索。

2.更够扫描二维码读取地址信息等进行展示。

3.能够前进、后退、刷新页面等基本导航操作。

4.可以收藏某些页面

5.可以将页面进行社会化分享。

更大一些的浏览器还可以做自己的门户,有自己的用户体系等等。

选择ExMobi + Agile Lite,主要是由于ExMobi有强大的UI展现能力可以支持原生UI和webview的多窗口混合展现,以及丰富的本地能力以及与第三方SDK集成的接口,可以方便调用摄像头、GPS、第三方SDK等能力,而Agile Lite作为开源、灵活的H5框架,对H5门户的UI和交互处理非常便捷,而且它内置了很多操作ExMobi本地能力的JS桥接类。

由于现在处于起步阶段,暂时功能做到1/2/3,首页的门户也比较简单,后续会把各个部分和多窗口支持起来。

目前代码很简单,只需要两个页面,若干图片和Agile Lite框架就可以。

先上效果图再上源码:

首页门户,目前只是一些热门的网站的链接,后续可以借助ExMobi服务端的集成能力抓爬和采集一些热门的资讯/新闻/天气等信息进行展现,还可以结合企业系统把企业的一些待办信息在此进行展示,形成一个以h5为入口的企业门户。

ExMobi+Agile Lite开发内置浏览器APP

点击门户的淘宝icon就会跳转打开淘宝手机版页面。当然如果做为企业使用,也可以通过门户来打开独立的app程序而不仅仅是H5链接地址。

ExMobi+Agile Lite开发内置浏览器APP

如果用户输入的是关键字,自动调用百度进行搜索,后续规划中会搭建一个内部搜索系统,可以对内部信息和系统进行查询,返回符合企业信息的数据,展示的内容相较于百度搜索会更加丰富,可以是图文/音频/链接/app等,甚至还有一些实时的推送消息。

ExMobi+Agile Lite开发内置浏览器APP

目前的浏览器客户端还很简单,只有两个页面,一个是UIXML,一个是HTML页面,其中UIXML页面作为程序首页展现一个原生窗口和部分原生UI,中间放置一个webview组件指向HTML页面展示门户。

UIXML页面的代码如下:

<header>
        <div style="border-size:0; background-color: #ffffff;">
            <input type="text" id="urlDom" style="width:80%;border-size: 0;" prompt="请输入网址或关键字"></input>
            <div style="width: 20%; text-align: right; padding:0 6 0 0;" id="goBtn" href="doGo()">
                <img class="footer_menu" src="res:image/app/ic_menu_search_holo_light.png"></img>
            </div>
            <hr/>
        </div>        
        
    </header>
    
    <body style="padding:0;margin:0;" onload="doLoad()">
        <webview id="wvDom" url="" plusready="doReady()" backmonitor="true"></webview>
    </body>
    <footer style="padding:10 0;">
        <div style="width: 25%; text-align: center;">
            <img class="footer_menu" id="backBtn" href="doBack()" src="res:image/app/back.png"></img>
        </div>
        <div style="width: 25%; text-align: center;">
            <img class="footer_menu" id="forwardBtn" href="doForward()" src="res:image/app/forward.png"></img>
        </div>
        <div style="width: 25%; text-align: center;">
            <img class="footer_menu" id="refreshBtn" href="doRefresh()" src="res:image/app/ refresh.png"></img>
        </div>
        <div style="width: 25%; text-align: center;">
            <img class="footer_menu" id="scalBtn" href="doScal()" src="res:image/app/qrcode.png"></img>
        </div>
    </footer>

这里充分利用的了ExMobi的UIXML原生组件进行布局,构建原生的窗口,在窗口顶部和底部放置原生的按钮组件以及支持h5的webview组件,通过JS来达到原生UI与h5的交互,实现前进、后退、刷新、扫描、搜索等功能,这个页面里执行了一些函数,如下:

var BMC = function(options){
            this.opts = {
                wvDom : document.getElementById(options.wvDom),
                firstUrl : options.firstUrl
            };
        };
        
        BMC.prototype.utils = {};
        BMC.prototype.utils.checkURL = function(URL){
            var str= URL||'';
            var Expression = /^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/;
            var objExp = new RegExp(Expression);
            return objExp.test(str);
        };
        
        BMC.prototype.utils.showToast = function(msg){
            var toast = new Toast();
             toast.setText(msg);
             toast.setDuration(1000);
             toast.show();
        };
        
        BMC.prototype.getOpts = function(){
            return this.opts;
        };
        
        BMC.prototype.init = function(){
            var opts = this.opts;
            opts.wvDom.loadUrl(opts.firstUrl);
        };
        
        BMC.prototype.go = function(url){
            if(!url){
                alert('请输入网址');
                return;
            }
            if(this.utils.checkURL(url)){
                this.opts.wvDom.loadUrl(url);
            }else if(this.utils.checkURL('http://'+url)){
                this.opts.wvDom.loadUrl('http://'+url);
            }else{
                this.opts.wvDom.loadUrl('http://m.baidu.com/s?word='+EncryptionUtil.urlEncode(url, 1));
            }
        };
        
        BMC.prototype.refresh = function(){
            this.opts.wvDom.refresh();
        };
        
        BMC.prototype.back = function(){
            if(!this.opts.wvDom.canBack()){
                this.utils.showToast('已经是第一页了');
                return;
            }
            this.opts.wvDom.back();
        };
        
        BMC.prototype.forward = function(){
            if(!this.opts.wvDom.canForward()){
                this.utils.showToast('已经是最后一页了');
                return;
            }
            this.opts.wvDom.forward();
        };

        function doLoad(){
            var url = 'res:page/www/index.html';
            var bmc = new BMC({
                wvDom : 'wvDom',
                firstUrl : url
            });
            
            window.doReady = function(){
                var opts = bmc.getOpts();
                var url = opts.wvDom.getUrl();
                var urlDom = document.getElementById('urlDom');
                urlDom.value = url.indexOf('file')==0?'':url;

                opts.wvDom.executeScript('document.addEventListener("backmonitor",function(){ nativePage.executeScript("doCheckBack()"); history.go(-1);}, false);');    
            }
            
            window.doGo = function(){
                var url = document.getElementById('urlDom').value;
                bmc.go(url);
            };
            
            window.doBack = function(){
                bmc.back();
            };
            
            window.doForward = function(){
                bmc.forward();
            };
            
            window.doRefresh = function(){
                bmc.refresh();
            };
            
            window.decode = new Decode();
            window.doScal = function(){
                decode.onCallback = decodeCallback;/*设置解码结束回调函数*/
                decode.startDecode();/*开始解码*/
            };
        
            window.decodeCallback = function(){        
                if(!decode.isSuccess()){/*返回解码是否成功*/
                       bmc.utils.showToast('二维码错误');
                }else{
                    bmc.go(decode.result);
                }
            };

            window.doCheckBack = function(){
                var opts = bmc.getOpts();
                if(!opts.wvDom.canBack()) close();
            }
            
            bmc.init();
        }

可以看出,代码中主要操作的就是ExMobi的webview组件,以达到对h5页面的控制。、

再来看看HTMML页面代码:

<!-- HTML5文件 -->
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
        <title>首页</title>
        <link rel="stylesheet" href="assets/agile/css/agile.layout.css">
        <link rel="stylesheet" href="assets/agile/css/flat/flat.component.css">
        <link rel="stylesheet" href="assets/agile/css/flat/flat.color.css">
        <link rel="stylesheet" href="assets/agile/css/flat/iconline.css">
        <link rel="stylesheet" href="assets/agile/css/flat/iconlogo.css">
    </head>
    <body >
        <div id="section_container">
            <section id="icon_logo_section" data-role="section" class="active">
                <article data-role="article" id="main_article" data-scroll="verticle" class="active" style="top:0px;bottom:0px;">
                    <div class="scroller padded text-center"> 
                        <div class="grid" data-col="3">
                            <div class="grid-cell" data-href="http://www.qq.com">
                              <div class="grid-img bg-alizarin"><span class="iconfont iconlogo-logo-qq"></span></div>
                              <label class="grid-label">腾讯</label>
                            </div>


                            <div class="grid-cell" data-href="http://www.taobao.com">
                              <div class="grid-img bg-carrot"><span class="iconfont iconlogo-logo-taobao"></span></div>
                              <label class="grid-label">淘宝</label>
                            </div>

                            <div class="grid-cell" data-href="http://m.baidu.com">
                              <div class="grid-img bg-peter-river"><span class="iconfont iconlogo-logo-baidu"></span></div>
                              <label class="grid-label">百度</label>
                            </div>

                            <div class="grid-cell" data-href="http://m.weibo.cn">
                              <div class="grid-img bg-wet-asphalt"><span class="iconfont iconlogo-logo-sinaweibo"></span></div>
                              <label class="grid-label">微博</label>
                            </div>

                            <div class="grid-cell" data-href="http://weixin.qq.com/">
                              <div class="grid-img bg-nephritis"><span class="iconfont iconlogo-logo-wechat"></span></div>
                              <label class="grid-label">微信</label>
                            </div>

                            <div class="grid-cell" data-href="http://www.fhss.com.cn/">
                              <div class="grid-img bg-orange"><span class="iconfont iconlogo-logo-starrysky"></span></div>
                              <label class="grid-label">烽火</label>
                            </div>
                            <div class="clearfix"></div>
                        </div>
                    </div>  

                </article>
            </section>
        </div>
        
        <!--- third --->
        <script src="assets/third/jquery/jquery-2.1.3.min.js"></script>
        <script src="assets/third/jquery/jquery.mobile.custom.min.js"></script>
        <script src="assets/third/iscroll/iscroll-probe.js"></script>
        <script src="assets/third/arttemplate/template-native.js"></script>
        <!-- agile -->
        <script type="text/javascript" src="assets/agile/js/agile.js"></script>        
        <!-- app -->
        <script type="text/javascript" src="assets/app/js/app.js"></script>
        <script>
            $('[data-href]').on(A.options.clickEvent, function(){
                location.href = $(this).data('href');
                return false;
            })
        </script>
    </body>
</html>

由于功能比较简单,主要是引用了Agile Lite框架的基本JS和CSS进行布局。

我们可以看到,在UIXML中的布局既有UIXML原生组件,也可以由webview组件展示H5,可以让原生UI和H5界面展现更好的融合在一起,相互搭配。

而UIXML中也调用了ExMobi提供的二维码扫描JS API,后面要做的本地收藏、社会化分享等ExMobi都有很好的支持。特别是ExMobi特有的支持的多窗口模式,一个应用中可以打开多个UIXML文件,也就是一个一个独立的窗口,并且都具有原生窗口的生命周期事件继承,可以让页面之间的交互更加灵活。

后续的新功能再更新咯。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Android与H5混合开发
    Android和H5在移动开发应用中非常广泛。市面上很多App都是使用Android开发的,但使用Android来开发一些比较复杂附属类,提示性的页面是得不偿失的。而H5在制作炫酷动画网页方面比较给力,且具有开发速度快,更新不用依赖于App的更新,只需要服务端更新相应的页面即可,所以App和H5页面相结合就显得尤为重要。而android
Easter79 Easter79
3年前
Taro小程序自定义顶部导航栏
微信自带的顶部导航栏是无法支持自定义icon和增加元素的,在开发小程序的时候自带的根本满足不了需求,分享一个封装好的组件,支持自定义icon、扩展dom,适配安卓、ios、h5,全面屏。我用的是京东的Taro多端编译框架写的小程序,原生的也可以适用,用到的微信/taro的api做调整就行,实现效果如下。!在这里插入图片描述(https://i
Wesley13 Wesley13
3年前
APP-H5- 小程序区别 (转载)
APP、H5、小程序区别●运行环境原生App直接运行在操作系统的单独进行中(安卓中可以开启多进程),而小程序运行环境是微信开发团队基于浏览器内核完全重构的一个内置解析器,针对性做了优化,配合自已定义的开发语言标准,提升了小程序的性能。是一种应用,并非完整的浏览器,只用到一部分H5技术,无法调用window对象和docu
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这