HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

关于js对sqlite的支持

HTML5+
 看到问题咨询里有一些关于js是否支持Sqlite的问题,这里抛砖引玉。答案是可以支持。  
 在github上已经有关于这块的代码支持:[https://github.com/kripken/sql.js/](https://github.com/kripken/sql.js/),打开链接地址我们可以看到各种连接办法。例如:node.js,浏览器支持等。  
如果我们手上已经有了sqlite的数据库,可以直接添加到我们的app项目中来,通过如下代码方式直接访问:
var xhr = new XMLHttpRequest();  
xhr.open('GET', 'assets/test.db', true);//在App中的相对路径  
xhr.responseType = 'arraybuffer';  

xhr.onload = function(e) {  
  var uInt8Array = new Uint8Array(this.response);  
  var db = new SQL.Database(uInt8Array);  
  var contents = db.exec("SELECT * FROM my_table");//执行查询语句  
  // contents is now [{columns:['col1','col2',...], values:[[first row], [second row], ...]}]  
  //查询结果获取办法contents [i].values  
};  
xhr.send();
继续阅读 »
 看到问题咨询里有一些关于js是否支持Sqlite的问题,这里抛砖引玉。答案是可以支持。  
 在github上已经有关于这块的代码支持:[https://github.com/kripken/sql.js/](https://github.com/kripken/sql.js/),打开链接地址我们可以看到各种连接办法。例如:node.js,浏览器支持等。  
如果我们手上已经有了sqlite的数据库,可以直接添加到我们的app项目中来,通过如下代码方式直接访问:
var xhr = new XMLHttpRequest();  
xhr.open('GET', 'assets/test.db', true);//在App中的相对路径  
xhr.responseType = 'arraybuffer';  

xhr.onload = function(e) {  
  var uInt8Array = new Uint8Array(this.response);  
  var db = new SQL.Database(uInt8Array);  
  var contents = db.exec("SELECT * FROM my_table");//执行查询语句  
  // contents is now [{columns:['col1','col2',...], values:[[first row], [second row], ...]}]  
  //查询结果获取办法contents [i].values  
};  
xhr.send();
收起阅读 »

HTML5+ API文档 CHM精编版

HTML5+ 文档 chm

在线文档无索引,搜索不方便,搞了个工具生成~~~
这两天官网都要被我抓烂了哈哈哈哈~~

不多说,文档在附件,全部文件都已离线封装。
split版本为分割子对象、属性为独立页面,方便像我这种记性不好的前进后退查阅,不用再上下滚来滚去找来找去了~~

另外~我把build工具也放出来文档更新可以直接重修build一下大家随意随意~

【update】
5.30 修正部分文档链接错误

继续阅读 »

在线文档无索引,搜索不方便,搞了个工具生成~~~
这两天官网都要被我抓烂了哈哈哈哈~~

不多说,文档在附件,全部文件都已离线封装。
split版本为分割子对象、属性为独立页面,方便像我这种记性不好的前进后退查阅,不用再上下滚来滚去找来找去了~~

另外~我把build工具也放出来文档更新可以直接重修build一下大家随意随意~

【update】
5.30 修正部分文档链接错误

收起阅读 »

[分享]简单使用模板,代替字符串拼接。

js 模板

1.移动互联网应用非常重要的是网络数据的交互,而获取的数据如何转化为我们希望的页面效果,使我们这节课讨论的重点。我们使用固定的数据源做演示。
2.经常会将数据在前台展示,一般情况下,我们会拼接字符串,或者使用第三方提供的模板引擎,这里我们推荐一种简单粗暴的方式(不建议使用到大项目中),但是对于中小型项目可以考虑使用。
其思想和模板引擎的思想类似,没有那么复杂。

直接说如何使用:
①引入JS
②定义模板
③加载数据
④对特殊数据处理(回调函数)
代码中有注释,很容易理解。

html文件  
<html>  
    <head>  
        <title></title>  
        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">  
        <link rel="stylesheet" type="text/css" href="../static/styles/mui.min.css" />  
        <link rel="stylesheet" href="../static/styles/ui-box.css">  
        <link rel="stylesheet" href="../static/styles/ui-base.css">  
        <link rel="stylesheet" href="../static/styles/ui-input.css">  
        <link rel="stylesheet" href="../static/styles/style.css">  
        <link rel="stylesheet" href="../static/styles/infor.css">  
        <link rel="stylesheet" type="text/css" href="../static/styles/animate.min.css" />  
    </head>  
    <body class="um-vp c-gra1">  
        <div class="mui-content">  
            <div class="ub-f1">  
                <table class='listTable' border='0' cellpadding='0' cellspacing='0' id="cminfo">  

                </table>  
            </div>  
        </div>  
    </body>  
    <script src="../static/scripts/mui.min.js" type="text/javascript" charset="utf-8"></script>  
    <script src="../static/scripts/zy_tmpl.js" type="text/javascript" charset="utf-8"></script>  
    <script type="text/javascript">  
        (function($, doc) {  
            $.init();  
            //$.plusReady(function() {  
                //数据加载(这里演示就不从后台获取了,直接将获取的数据拿过来)  
                var data = '[{"id":"43743","cm_id":"0011504030001","cm_areaname":"0.001.001.001.001.003","cm_name":"毕祖辉","cm_tel":"","cm_work_tel":"8570269","cm_color":"10","fphoto":"","cm_sex":"男"},{"id":"43762","cm_id":"0011504030002","cm_areaname":"0.001.001.001.002","cm_name":"严丽华","cm_tel":"","cm_work_tel":"6110357","cm_color":"11","fphoto":"","cm_sex":"女"},{"id":"43709","cm_id":"0011504030001","cm_areaname":"0.001.001.001.001","cm_name":"马强","cm_tel":"","cm_work_tel":"5946083","cm_color":"12","fphoto":"","cm_sex":"男"},{"dataCount":"4731"}]';  
                //转化为JSON对象  
                var dataObj = JSON.parse(data);  
                var dataCount = dataObj.pop();//数据总数量,不是本数据数量(直接忽略)  
                //定义模板  
                var t = _t.toString();  
                var tmp = t.substr(17,t.length-21);  
                //加载数据 参数解释(模板,数据数量,回调函数[可以不传]);  
                var res = tmpl(tmp,dataObj,tmpl_count(dataObj),tmpCallBack);  
                doc.querySelector('#cminfo').innerHTML = res;  
            //})  
            function _t(){/*  
                <tr id='${id}' cm_id='${cm_id}' cm_areaname='${cm_areaname}' style="color:${cb:cm_color}">  
                <td class="preTd">  
                <img src='${cb:fphoto}' class='preIcon uc-a2'></td>  
                <td class="td_name_style">  
                <div class="td_div">${cm_name}</div>  
                <p class="ulim">${cb:cm_tel}</p></td>  
                <td onclick="dialPhone('${cb:cm_tel}')" class='more' width='10%'><img src='../static/imgs/call.png' class='lastIcon'></td>  
                </tr>  
            */}  
            function tmpCallBack(a,b)  
            {  
                switch (b[1]){  
                    case 'cm_tel':  
                        return !isNull(a.cm_tel)?a.cm_work_tel:a.cm_tel;  
                        break;  
                    case "fphoto":  
                        if(!isNull(a.fphoto))  
                        {  
                            var src = a.cm_sex&&~(a.cm_sex).indexOf('女')?"../static/imgs/head-picn.png":"../static/imgs/head-pic.png";  
                            return src;  
                        }else{  
                            return a.fphoto;//如果有则先加载到本地  
                        }  
                        break;  
                    case "cm_color":  
                        return !isNull(a.cm_color)?'':HTMLColor(a.cm_color);  
                        break;  
                    default:  
                        break;  
                }  
                return '';  
            }  
            //下面的方法可以写为公共的方法  
            function isNull(value)  
            {  
                if(value == null || value == "" || value == "undefined" || value == undefined || value == "null" || value == "(null)" || value == 'NULL' || typeof(value) == 'undefined'){  
                    return false;  
                }  
                else{  
                    value = value+"";  
                    value = value.replace(/\s/g,"");  
                    if(value == ""){  
                        return false;  
                    }  
                    return true;  
                    }  
            }  
            function HTMLColor(num)  
            {  
                var htmlColor = ",Aqua,Black,Blue,Fuchsia,Gray,Green,Lime,Maroon,Navy,Olive,Purple,Red,Silver,Teal,White,Yellow";  
                var hcs = htmlColor.split(",");  
                return num > 0 && num < hcs.length ? hcs[num] : '' ;  
            }  
        }(mui, document))  
    </script>  
</html>
tmpl.js文件  

    var tmpl_count=function(dd)  
    {  
        if(Object.prototype.toString.apply(dd)==="[object Array]")  
        {  
            return dd.length;  
        }  
        else  
        {     
            var c=0;  
            for(var i in dd)  
                c++;  
            return c;  
        }  
    }     
    var _f = function(d,c,k1,k2,l){  
        var q = c.match(/(first:|last:)(\"|\'*)([^\"\']*)(\"|\'*)/);  
        if(!q) return;  
        if(q[1]==k1){  
            if(q[2]=='\"'||q[2]=='\''){  
                return q[3];  
            }  
            else  
                return d[q[3]];  
        }  
        else if(q[1]==k2 && l>1)  
            return "";  
    }  
    var t_f = function(t,d,i,l,cb){  
            return t.replace( /\$\{([^\}]*)\}/g,function(m,c){  
            if(c.match(/index:/)){  
                return i;  
            }  
            if(c.match(/cb:/) && cb){  
                return cb(d,c.match(/cb:(.*)/));  
            }  
            if(i==0){  
                var s=_f(d,c,"first:","last:",l);  
                if(s) return s;  
            }  
            if(i==(l-1)){  
                var s= _f(d,c,"last:","first:",l);  
                if(s) return s;  
            }  
            var ar=c.split('.');  
            var res=d;  
            for(var key in ar)  
                res=res[ar[key]];  
            return res||"";  
        });  
    }  

var tmpl = function(t,dd,l,cb,scb){  
    var r = "";  
    {  
        var index=0;  
        for(var i in dd)  
        {  
            if(scb)  
                scb(0,i,dd[i]);  
            var rr=t_f(t,dd[i],index,l,cb);  
            if(scb)  
                scb(1,rr,dd[i]);  
            r+=rr;  
            index++;  
        }  
    }  
    return r;     
}  

var tmpl_s = function(t,dd,cb)  
{  
    return t_f(t,dd,-1,-1,cb);  
}  
继续阅读 »

1.移动互联网应用非常重要的是网络数据的交互,而获取的数据如何转化为我们希望的页面效果,使我们这节课讨论的重点。我们使用固定的数据源做演示。
2.经常会将数据在前台展示,一般情况下,我们会拼接字符串,或者使用第三方提供的模板引擎,这里我们推荐一种简单粗暴的方式(不建议使用到大项目中),但是对于中小型项目可以考虑使用。
其思想和模板引擎的思想类似,没有那么复杂。

直接说如何使用:
①引入JS
②定义模板
③加载数据
④对特殊数据处理(回调函数)
代码中有注释,很容易理解。

html文件  
<html>  
    <head>  
        <title></title>  
        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">  
        <link rel="stylesheet" type="text/css" href="../static/styles/mui.min.css" />  
        <link rel="stylesheet" href="../static/styles/ui-box.css">  
        <link rel="stylesheet" href="../static/styles/ui-base.css">  
        <link rel="stylesheet" href="../static/styles/ui-input.css">  
        <link rel="stylesheet" href="../static/styles/style.css">  
        <link rel="stylesheet" href="../static/styles/infor.css">  
        <link rel="stylesheet" type="text/css" href="../static/styles/animate.min.css" />  
    </head>  
    <body class="um-vp c-gra1">  
        <div class="mui-content">  
            <div class="ub-f1">  
                <table class='listTable' border='0' cellpadding='0' cellspacing='0' id="cminfo">  

                </table>  
            </div>  
        </div>  
    </body>  
    <script src="../static/scripts/mui.min.js" type="text/javascript" charset="utf-8"></script>  
    <script src="../static/scripts/zy_tmpl.js" type="text/javascript" charset="utf-8"></script>  
    <script type="text/javascript">  
        (function($, doc) {  
            $.init();  
            //$.plusReady(function() {  
                //数据加载(这里演示就不从后台获取了,直接将获取的数据拿过来)  
                var data = '[{"id":"43743","cm_id":"0011504030001","cm_areaname":"0.001.001.001.001.003","cm_name":"毕祖辉","cm_tel":"","cm_work_tel":"8570269","cm_color":"10","fphoto":"","cm_sex":"男"},{"id":"43762","cm_id":"0011504030002","cm_areaname":"0.001.001.001.002","cm_name":"严丽华","cm_tel":"","cm_work_tel":"6110357","cm_color":"11","fphoto":"","cm_sex":"女"},{"id":"43709","cm_id":"0011504030001","cm_areaname":"0.001.001.001.001","cm_name":"马强","cm_tel":"","cm_work_tel":"5946083","cm_color":"12","fphoto":"","cm_sex":"男"},{"dataCount":"4731"}]';  
                //转化为JSON对象  
                var dataObj = JSON.parse(data);  
                var dataCount = dataObj.pop();//数据总数量,不是本数据数量(直接忽略)  
                //定义模板  
                var t = _t.toString();  
                var tmp = t.substr(17,t.length-21);  
                //加载数据 参数解释(模板,数据数量,回调函数[可以不传]);  
                var res = tmpl(tmp,dataObj,tmpl_count(dataObj),tmpCallBack);  
                doc.querySelector('#cminfo').innerHTML = res;  
            //})  
            function _t(){/*  
                <tr id='${id}' cm_id='${cm_id}' cm_areaname='${cm_areaname}' style="color:${cb:cm_color}">  
                <td class="preTd">  
                <img src='${cb:fphoto}' class='preIcon uc-a2'></td>  
                <td class="td_name_style">  
                <div class="td_div">${cm_name}</div>  
                <p class="ulim">${cb:cm_tel}</p></td>  
                <td onclick="dialPhone('${cb:cm_tel}')" class='more' width='10%'><img src='../static/imgs/call.png' class='lastIcon'></td>  
                </tr>  
            */}  
            function tmpCallBack(a,b)  
            {  
                switch (b[1]){  
                    case 'cm_tel':  
                        return !isNull(a.cm_tel)?a.cm_work_tel:a.cm_tel;  
                        break;  
                    case "fphoto":  
                        if(!isNull(a.fphoto))  
                        {  
                            var src = a.cm_sex&&~(a.cm_sex).indexOf('女')?"../static/imgs/head-picn.png":"../static/imgs/head-pic.png";  
                            return src;  
                        }else{  
                            return a.fphoto;//如果有则先加载到本地  
                        }  
                        break;  
                    case "cm_color":  
                        return !isNull(a.cm_color)?'':HTMLColor(a.cm_color);  
                        break;  
                    default:  
                        break;  
                }  
                return '';  
            }  
            //下面的方法可以写为公共的方法  
            function isNull(value)  
            {  
                if(value == null || value == "" || value == "undefined" || value == undefined || value == "null" || value == "(null)" || value == 'NULL' || typeof(value) == 'undefined'){  
                    return false;  
                }  
                else{  
                    value = value+"";  
                    value = value.replace(/\s/g,"");  
                    if(value == ""){  
                        return false;  
                    }  
                    return true;  
                    }  
            }  
            function HTMLColor(num)  
            {  
                var htmlColor = ",Aqua,Black,Blue,Fuchsia,Gray,Green,Lime,Maroon,Navy,Olive,Purple,Red,Silver,Teal,White,Yellow";  
                var hcs = htmlColor.split(",");  
                return num > 0 && num < hcs.length ? hcs[num] : '' ;  
            }  
        }(mui, document))  
    </script>  
</html>
tmpl.js文件  

    var tmpl_count=function(dd)  
    {  
        if(Object.prototype.toString.apply(dd)==="[object Array]")  
        {  
            return dd.length;  
        }  
        else  
        {     
            var c=0;  
            for(var i in dd)  
                c++;  
            return c;  
        }  
    }     
    var _f = function(d,c,k1,k2,l){  
        var q = c.match(/(first:|last:)(\"|\'*)([^\"\']*)(\"|\'*)/);  
        if(!q) return;  
        if(q[1]==k1){  
            if(q[2]=='\"'||q[2]=='\''){  
                return q[3];  
            }  
            else  
                return d[q[3]];  
        }  
        else if(q[1]==k2 && l>1)  
            return "";  
    }  
    var t_f = function(t,d,i,l,cb){  
            return t.replace( /\$\{([^\}]*)\}/g,function(m,c){  
            if(c.match(/index:/)){  
                return i;  
            }  
            if(c.match(/cb:/) && cb){  
                return cb(d,c.match(/cb:(.*)/));  
            }  
            if(i==0){  
                var s=_f(d,c,"first:","last:",l);  
                if(s) return s;  
            }  
            if(i==(l-1)){  
                var s= _f(d,c,"last:","first:",l);  
                if(s) return s;  
            }  
            var ar=c.split('.');  
            var res=d;  
            for(var key in ar)  
                res=res[ar[key]];  
            return res||"";  
        });  
    }  

var tmpl = function(t,dd,l,cb,scb){  
    var r = "";  
    {  
        var index=0;  
        for(var i in dd)  
        {  
            if(scb)  
                scb(0,i,dd[i]);  
            var rr=t_f(t,dd[i],index,l,cb);  
            if(scb)  
                scb(1,rr,dd[i]);  
            r+=rr;  
            index++;  
        }  
    }  
    return r;     
}  

var tmpl_s = function(t,dd,cb)  
{  
    return t_f(t,dd,-1,-1,cb);  
}  
收起阅读 »

如何安装node.js支持插件

node.js 插件 nodejs node

在eclipse插件中,node.js插件中比较知名的是nodeclipse。

从HBuilder6.3起,工具-插件安装,可直接选择nodeclipse插件安装。
安装完毕后重启HBuilder
新建node项目:依次点击菜单文件→新建→其他如下图
node
5.选择要新建的nodejs项目类型新建项目即可

  1. 在js文件里提示node.js
    nodezhushou

注意:nodeclipse的编辑器和HBuilder的编辑器不同。但node.js和web的js均以.js为扩展名,打开js文件时需分清使用哪个js编辑器打开。
一般而言,由于nodeclipse是后安装的,所以.js文件默认以node的编辑器打开,在此编辑器中是不提示HBuilder的语法助手的。
要更换打开方式,在项目管理器里对js文件点右键-打开方式,选择自己想要的编辑器打开。
还可以在菜单里设置永久文件关联,你可以设置你最常使用的方式打开。推荐设置.js文件默认使用HBuilder的js编辑器打开后,然后在打开node.js的js文件时点右键选择nodeclipse编辑器打开。

历史材料归档:
HBuilder6.3以下的版本安装nodeclipse插件的方法如下:
前言,nodeclipse是基于jsdt的,HBuilder没有内置jsdt,如果要安装nodeclipse,则先要安装jsdt插件。
安装JSDT

  1. 依次点击工具→插件安装→手动安装eclipse插件,点击“可用软件站点”如下图
  2. 勾选 indigo(注:勾选后,HBuilder启动时会检查indigo已安装的插件是否有升级,从而导致软件启动过慢或者启动后很长时间内比较卡,所以安装完jdt后请将此勾重新去掉)如下图
  3. 点击确定后,点下拉箭头选择indigo的站点如下图,然后等待加载(此过程有点长,如有设置代理会加快加载速度)
  4. 加载完毕后,找到programming languages如下图
  5. 勾选programming languages下的JavaScript Development Tools如下图

    6.点击下一步,接受许可协议并安装,安装完毕后重启即可
    安装nodeclipse
  6. 依次点击工具→插件安装→浏览eclipse插件市场→搜索node.js→在搜索结果里找nodeclipse如下图
    nodeclipse
    2.点击上图中的install开始加载,加载完毕点下一步接受许可协议静待安装完成即可
  7. 安装完毕后重启HBuilder
  8. 新建node项目:依次点击菜单文件→新建→其他如下图
    node
    5.选择要新建的nodejs项目类型新建项目即可
  9. 在js文件里提示node.js
    nodezhushou
继续阅读 »

在eclipse插件中,node.js插件中比较知名的是nodeclipse。

从HBuilder6.3起,工具-插件安装,可直接选择nodeclipse插件安装。
安装完毕后重启HBuilder
新建node项目:依次点击菜单文件→新建→其他如下图
node
5.选择要新建的nodejs项目类型新建项目即可

  1. 在js文件里提示node.js
    nodezhushou

注意:nodeclipse的编辑器和HBuilder的编辑器不同。但node.js和web的js均以.js为扩展名,打开js文件时需分清使用哪个js编辑器打开。
一般而言,由于nodeclipse是后安装的,所以.js文件默认以node的编辑器打开,在此编辑器中是不提示HBuilder的语法助手的。
要更换打开方式,在项目管理器里对js文件点右键-打开方式,选择自己想要的编辑器打开。
还可以在菜单里设置永久文件关联,你可以设置你最常使用的方式打开。推荐设置.js文件默认使用HBuilder的js编辑器打开后,然后在打开node.js的js文件时点右键选择nodeclipse编辑器打开。

历史材料归档:
HBuilder6.3以下的版本安装nodeclipse插件的方法如下:
前言,nodeclipse是基于jsdt的,HBuilder没有内置jsdt,如果要安装nodeclipse,则先要安装jsdt插件。
安装JSDT

  1. 依次点击工具→插件安装→手动安装eclipse插件,点击“可用软件站点”如下图
  2. 勾选 indigo(注:勾选后,HBuilder启动时会检查indigo已安装的插件是否有升级,从而导致软件启动过慢或者启动后很长时间内比较卡,所以安装完jdt后请将此勾重新去掉)如下图
  3. 点击确定后,点下拉箭头选择indigo的站点如下图,然后等待加载(此过程有点长,如有设置代理会加快加载速度)
  4. 加载完毕后,找到programming languages如下图
  5. 勾选programming languages下的JavaScript Development Tools如下图

    6.点击下一步,接受许可协议并安装,安装完毕后重启即可
    安装nodeclipse
  6. 依次点击工具→插件安装→浏览eclipse插件市场→搜索node.js→在搜索结果里找nodeclipse如下图
    nodeclipse
    2.点击上图中的install开始加载,加载完毕点下一步接受许可协议静待安装完成即可
  7. 安装完毕后重启HBuilder
  8. 新建node项目:依次点击菜单文件→新建→其他如下图
    node
    5.选择要新建的nodejs项目类型新建项目即可
  9. 在js文件里提示node.js
    nodezhushou
收起阅读 »

iOS离线打包-友盟统计配置

离线打包

添加友盟统计插件

注:Linker Flags的添加方法请参考这个文档

  1. 添加以下静态库:liblibStatistic.a

  2. 添加以下framework: "UMAnalytics.framework",
    "UMCommon.framework",

  3. 添加以下系统库:SystemConfiguration.framework,CoreTelephony.framework, libz.tbd, libsqlite3.tbd

配置友盟统计插件

1.到友盟开放平台申请Appkey

2.打开Info.plist文件找到umeng项,如果没有按图片中的格式添加该项,在下图中的红色区域输入申请的Appkey

注意:

IDFA说明

友盟统计SDK默认采集idfa标识,用来更准确的分析核对数据。对于应用本身没有获取idfa的情况,建议将应用提交至AppStore时按如下方式配置:(以避免被苹果以“应用不含广告功能,但获取了广告标示符IDFA”的而拒绝其上架。))

继续阅读 »

添加友盟统计插件

注:Linker Flags的添加方法请参考这个文档

  1. 添加以下静态库:liblibStatistic.a

  2. 添加以下framework: "UMAnalytics.framework",
    "UMCommon.framework",

  3. 添加以下系统库:SystemConfiguration.framework,CoreTelephony.framework, libz.tbd, libsqlite3.tbd

配置友盟统计插件

1.到友盟开放平台申请Appkey

2.打开Info.plist文件找到umeng项,如果没有按图片中的格式添加该项,在下图中的红色区域输入申请的Appkey

注意:

IDFA说明

友盟统计SDK默认采集idfa标识,用来更准确的分析核对数据。对于应用本身没有获取idfa的情况,建议将应用提交至AppStore时按如下方式配置:(以避免被苹果以“应用不含广告功能,但获取了广告标示符IDFA”的而拒绝其上架。))

收起阅读 »

搞一搞百度定位

定位

如果有版式问题,移步到这phillyx

关于百度定位

  1. 这是官方定位的解释:geolocation
  2. 地图插件配置
  3. 我在问答里面找到了这位童鞋的百度定位,地址变更提醒
    不过,童鞋倒是给具体的示例啊,木有\~\~\~\~(>_<)\~\~\~\~  
    官方的插件配置也看的懵懵懂懂,一塌糊涂  
    ok,自己搞,搞了大半天基本上弄清楚了,下面就总结一下自己的心血历程吧!!!~~~~~  

  4. 首先要到百度lbs开放平台注册开发者账号
  5. 在应用里面创建应用我的应用
  6. 服务器、Android、ios、浏览器逐个建立一个遍
    • 安卓和ios的安全码采用dcloud官方的“BA:AD:09:3A:82:82:9F:B4:32:A7:B2:8C:B4:CC:F0:E9:F3:7D:AE:58;io.dcloud.HBuilder”
    • 服务器和浏览器的Refer白名单默认“*”
  7. 下面就是挖坑填坑的经历了
    • 刚开始的使用JavaScript API大众版, 根据demo:helloworld照葫芦画瓢,可是太尼玛慢
    • 接着看到了JavaScript API极速版, ok 这次快了好多,能不能更快呢,当然可以O(∩_∩)O~
    • 秘诀就是这Web服务API
      使用Geocoding API
      通过逆地理编码服务获取数据
      我们可以将以下链接放到浏览器地址栏中试一下
      http://api.map.baidu.com/geocoder/v2/?ak=E4805d16520de693a3fe707cdc962045&callback=renderReverse&location=39.983424,116.322987&output=json&pois=1

      到这终于可以松一口气了,差多搞定了,下面就是码转了,为了方便,直接贴代码了

<!--废弃-->  
<!--<script type="text/javascript" src="http://api.map.baidu.com/api?type=quick&ak=你的key&v=1.0"></script>-->
(function($) {  
    /**  
     * @description 获取百度定位信息  
     * @param {Function} callback  
     */  
    function getPosition(callback) {  
        try {  
            plus.geolocation.getCurrentPosition(function(position) {  
                console.log(JSON.stringify(position));  
                var codns = position.coords; //获取地理坐标信息;  
                //              var geoc = new BMap.Geocoder();  
                //              var pt = new BMap.Point(codns.longitude, codns.latitude);  
                //              geoc.getLocation(pt, function(rs) {  
                //                  var addComp = rs.addressComponents;  
                //                  console.log(JSON.stringify(addComp));  
                //                  var lo =addComp.province+','+addComp.city;  
                //                  callback(lo);  
                //              });  
                var req = 'http://api.map.baidu.com/geocoder/v2/';  
                var parms = {  
                    ak: '你的key',  
                    callback: 'renderReverse',  
                    output: 'json',  
                    location: codns.latitude + ',' + codns.longitude  
                    //,pois:1(周边poi数组) //不建议要,周边数据太杂,不需要  
                };  
                mui.ajax(req, {  
                    data: parms,  
                    dataType: 'json', //服务器返回json格式数据  
                    type: 'post', //HTTP请求类型  
                    timeout: 10000, //超时时间设置为10秒;  
                    success: function(data) {  
                        console.log(JSON.stringify(data));  
                        myStorage.setItem('geolocation',data);  
                        if (data.status == 0) {  
                            var lo = data.result.addressComponent.province + ',' + data.result.addressComponent.city;  
                            callback(lo);  
                        } else {  
                            callback(false);  
                        }  
                    },  
                    error: function(xhr, type, errorThrown) {  
                        callback(false);  
                    }  
                });  
            }, function(e) {  
                console.log("获取定位位置信息失败:" + e.message);  
                callback(false);  
            }, {  
                provider: 'baidu'  
            });  

        } catch (e) {  
            callback(false);  
            console.error(e.message);  
        }  
    }  
    $.getbaiduposition = getPosition;  
}(mui));
tip:帖子使用[Haroopad](http://pad.haroopress.com/user.html)构建,狂拽酷炫吊炸天  
继续阅读 »

如果有版式问题,移步到这phillyx

关于百度定位

  1. 这是官方定位的解释:geolocation
  2. 地图插件配置
  3. 我在问答里面找到了这位童鞋的百度定位,地址变更提醒
    不过,童鞋倒是给具体的示例啊,木有\~\~\~\~(>_<)\~\~\~\~  
    官方的插件配置也看的懵懵懂懂,一塌糊涂  
    ok,自己搞,搞了大半天基本上弄清楚了,下面就总结一下自己的心血历程吧!!!~~~~~  

  4. 首先要到百度lbs开放平台注册开发者账号
  5. 在应用里面创建应用我的应用
  6. 服务器、Android、ios、浏览器逐个建立一个遍
    • 安卓和ios的安全码采用dcloud官方的“BA:AD:09:3A:82:82:9F:B4:32:A7:B2:8C:B4:CC:F0:E9:F3:7D:AE:58;io.dcloud.HBuilder”
    • 服务器和浏览器的Refer白名单默认“*”
  7. 下面就是挖坑填坑的经历了
    • 刚开始的使用JavaScript API大众版, 根据demo:helloworld照葫芦画瓢,可是太尼玛慢
    • 接着看到了JavaScript API极速版, ok 这次快了好多,能不能更快呢,当然可以O(∩_∩)O~
    • 秘诀就是这Web服务API
      使用Geocoding API
      通过逆地理编码服务获取数据
      我们可以将以下链接放到浏览器地址栏中试一下
      http://api.map.baidu.com/geocoder/v2/?ak=E4805d16520de693a3fe707cdc962045&callback=renderReverse&location=39.983424,116.322987&output=json&pois=1

      到这终于可以松一口气了,差多搞定了,下面就是码转了,为了方便,直接贴代码了

<!--废弃-->  
<!--<script type="text/javascript" src="http://api.map.baidu.com/api?type=quick&ak=你的key&v=1.0"></script>-->
(function($) {  
    /**  
     * @description 获取百度定位信息  
     * @param {Function} callback  
     */  
    function getPosition(callback) {  
        try {  
            plus.geolocation.getCurrentPosition(function(position) {  
                console.log(JSON.stringify(position));  
                var codns = position.coords; //获取地理坐标信息;  
                //              var geoc = new BMap.Geocoder();  
                //              var pt = new BMap.Point(codns.longitude, codns.latitude);  
                //              geoc.getLocation(pt, function(rs) {  
                //                  var addComp = rs.addressComponents;  
                //                  console.log(JSON.stringify(addComp));  
                //                  var lo =addComp.province+','+addComp.city;  
                //                  callback(lo);  
                //              });  
                var req = 'http://api.map.baidu.com/geocoder/v2/';  
                var parms = {  
                    ak: '你的key',  
                    callback: 'renderReverse',  
                    output: 'json',  
                    location: codns.latitude + ',' + codns.longitude  
                    //,pois:1(周边poi数组) //不建议要,周边数据太杂,不需要  
                };  
                mui.ajax(req, {  
                    data: parms,  
                    dataType: 'json', //服务器返回json格式数据  
                    type: 'post', //HTTP请求类型  
                    timeout: 10000, //超时时间设置为10秒;  
                    success: function(data) {  
                        console.log(JSON.stringify(data));  
                        myStorage.setItem('geolocation',data);  
                        if (data.status == 0) {  
                            var lo = data.result.addressComponent.province + ',' + data.result.addressComponent.city;  
                            callback(lo);  
                        } else {  
                            callback(false);  
                        }  
                    },  
                    error: function(xhr, type, errorThrown) {  
                        callback(false);  
                    }  
                });  
            }, function(e) {  
                console.log("获取定位位置信息失败:" + e.message);  
                callback(false);  
            }, {  
                provider: 'baidu'  
            });  

        } catch (e) {  
            callback(false);  
            console.error(e.message);  
        }  
    }  
    $.getbaiduposition = getPosition;  
}(mui));
tip:帖子使用[Haroopad](http://pad.haroopress.com/user.html)构建,狂拽酷炫吊炸天  
收起阅读 »

Android平台离线打包推送插件配置

离线打包 5+App开发 SDK

个推推送平台配置

需要拷贝的文件

需要引入工程的jar/aar文件
需要将以下jar/aar文件放到工程的libs目录下

路径 文件
SDK\libs(1.9.9.52372之前) aps.jar, aps-igexin.jar, GetuiSDK2.10.3.5.jar
SDK\libs(1.9.9.52372之后) aps-release.aar, aps-igexin-release.aar

需要将以下so文件放到工程的libs\armeabi目录下(1.9.9.52372版本之后不需要设置此项)

路径 文件名
SDK\libs\armeabi libgetuiext2.so
SDK\libs\armeabi-v7a libgetuiext2.so
SDK\libs\x86 libgetuiext2.so

需要引入工程的资源文件
需要将以下文件放到工程的res/layout目录下(1.9.9.52372版本之后不需要设置此项)

路径 文件名
SDK\res\layout getui_notification.xml
SDK\res\raw keep.xml

Androidmainfest.xml文件需要修改的项

需要在application节点前添加权限
因Android L(android 5.0)系统自身限制,多个应用安装时,如果拥有同一个Service权限,会导致权限冲突,只能安装一个带有此权限的应用。对此,个推SDK在声明自定义权限时需要添加apk的包名以避免和其他使用个推的应用冲突。

<uses-permission android:name="android.permission.INTERNET"/>  
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>  
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
<uses-permission android:name="android.permission.WAKE_LOCK"/>  
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
<uses-permission android:name="android.permission.VIBRATE"/>  
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>  
<uses-permission android:name="android.permission.CALL_PHONE"/>  
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>  
<uses-permission android:name="getui.permission.GetuiService.$你的APK包名"/>  
<permission android:name="getui.permission.GetuiService.$你的APK包名" android:protectionLevel="normal"/>  

<application>节点下配置如下代码

        <meta-data android:name="PUSH_APPID" android:value="$你自己的APPID"/>  
        <meta-data android:name="PUSH_APPKEY" android:value="$你的appkey"/>  
        <meta-data android:name="PUSH_APPSECRET" android:value="$你的appsecret"/>  
        <service  
            android:name="com.igexin.sdk.PushService"  
            android:exported="true"  
            android:label="NotificationCenter"  
            android:process=":pushservice">  
            <intent-filter>  
                <action android:name="com.igexin.sdk.action.service.message"/>  
            </intent-filter>  
        </service>  
        <receiver android:name="com.igexin.sdk.PushReceiver">  
            <intent-filter>  
                <action android:name="android.intent.action.BOOT_COMPLETED"/>  
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>  
                <action android:name="android.intent.action.USER_PRESENT"/>  
                <action android:name="com.igexin.sdk.action.refreshls"/>  
                <action android:name="android.intent.action.MEDIA_MOUNTED"/>  
                <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>  
                <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>  
            </intent-filter>  
        </receiver>  
        <activity  
            android:name="com.igexin.sdk.PushActivity"  
            android:excludeFromRecents="true"  
            android:exported="false"  
            android:process=":pushservice"  
            android:taskAffinity="com.igexin.sdk.PushActivityTask"  
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>  
        <activity  
            android:name="com.igexin.sdk.GActivity"  
            android:excludeFromRecents="true"  
            android:exported="true"  
            android:process=":pushservice"  
            android:taskAffinity="com.igexin.sdk.PushActivityTask"  
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>  
        <receiver android:name="io.dcloud.feature.apsGt.GTNotificationReceiver">  
            <intent-filter>  
                <action android:name="android.intent.action.BOOT_COMPLETED"/>  
                <action android:name="填写APK的包名.__CREATE_NOTIFICATION"/>  
                <action android:name="填写APK的包名.__REMOVE_NOTIFICATION"/>  
                <action android:name="填写APK的包名.__CLEAR_NOTIFICATION"/>  
                <action android:name="填写APK的包名.__CLILK_NOTIFICATION"/>  
            </intent-filter>  
        </receiver>  
        <service  
            android:name="io.dcloud.feature.apsGt.GTNormalIntentService"/>  

dcloud_properties.xml需要添加如下代码
dcloud_properties.xml文件在assets/data目录下
features节点下添加

<feature name="Push" value="io.dcloud.feature.aps.APSFeatureImpl"><module name="igexin" value="io.dcloud.feature.apsGt.GTPushService"/></feature>

services节点下添加

<service  
            name="push"  
            value="io.dcloud.feature.aps.APSFeatureImpl" />

小米推送

需要拷贝的文件

需要将以下jar/aar文件拷贝到工程中

路径 文件
SDK\libs(1.9.9.52372之前) aps.jar,aps-xiaomi.jar,MiPush_SDK_Client_3_1_2.jar,
SDK\libs(1.9.9.52372之后) aps-release.aar, aps-xiaomi-release.aar

Androidmainfest.xml文件需要修改的项

需要在application节点前添加权限

        <uses-permission android:name="android.permission.INTERNET"/>  
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>  
        <uses-permission android:name="android.permission.READ_PHONE_STATE"/>  
        <uses-permission android:name="android.permission.GET_TASKS"/>  
        <uses-permission android:name="android.permission.VIBRATE"/>  
        <uses-permission android:name="android.permission.GET_TASKS"/>  
        <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>  
<uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"/>   
<permission android:name="填写APK的包名.permission.MIPUSH_RECEIVE" android:protectionLevel="signature"/>  
<uses-permission android:name="填写APK的包名.permission.MIPUSH_RECEIVE"/>

application节点下配置如下代码

<service android:enabled="true" android:process=":pushservice" android:name="com.xiaomi.push.service.XMPushService"/>  
<service android:name="com.xiaomi.push.service.XMJobService" android:enabled="true" android:exported="false" android:permission="android.permission.BIND_JOB_SERVICE" android:process=":pushservice"/>  
<service android:enabled="true" android:exported="true" android:name="com.xiaomi.mipush.sdk.PushMessageHandler"/>  
<service android:enabled="true" android:name="com.xiaomi.mipush.sdk.MessageHandleService"/>  
<receiver android:exported="true" android:name="com.xiaomi.push.service.receivers.NetworkStatusReceiver">  
<intent-filter>  
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>  
<category android:name="android.intent.category.DEFAULT"/>  
</intent-filter>  
</receiver>  
<receiver android:exported="false" android:process=":pushservice" android:name="com.xiaomi.push.service.receivers.PingReceiver">  
<intent-filter>  
<action android:name="com.xiaomi.push.PING_TIMER"/>  
</intent-filter>  
</receiver>  
<receiver android:exported="true" android:name="io.dcloud.feature.apsXm.XMMessageReceiver">  
<intent-filter>  
<action android:name="com.xiaomi.mipush.RECEIVE_MESSAGE"/>  
</intent-filter>  
<intent-filter>  
<action android:name="com.xiaomi.mipush.MESSAGE_ARRIVED"/>  
</intent-filter>  
<intent-filter>  
<action android:name="com.xiaomi.mipush.ERROR"/>  
</intent-filter>  
</receiver>  
<receiver android:exported="true" android:name="io.dcloud.feature.apsXm.XMNotificationReceiver">  
<intent-filter>  
<action android:name="android.intent.action.BOOT_COMPLETED"/>  
<action android:name="%填写APK的包名%.__CREATE_NOTIFICATION"/>  
<action android:name="%填写APK的包名%.__REMOVE_NOTIFICATION"/>  
<action android:name="%填写APK的包名%.__CLEAR_NOTIFICATION"/>  
<action android:name="%填写APK的包名%.__CLILK_NOTIFICATION"/>  
</intent-filter>  
</receiver>  
<meta-data android:name="PUSH_APPID" android:value="_%小米推送的APPID%"/>  
<meta-data android:name="PUSH_APPKEY" android:value="_%小米推送的APPKEY%"/>

dcloud_properties.xml需要添加如下代码

dcloud_properties.xml文件在ADT工程assets/data目录下
Features节点下添加

<feature name="Push" value="io.dcloud.feature.aps.APSFeatureImpl">  
<module name="xiaomi" value="io.dcloud.feature.apsXm.XMPushService"/>  
</feature>

Service节点下添加

<service name="push" value="io.dcloud.feature.aps.APSFeatureImpl"/>
继续阅读 »

个推推送平台配置

需要拷贝的文件

需要引入工程的jar/aar文件
需要将以下jar/aar文件放到工程的libs目录下

路径 文件
SDK\libs(1.9.9.52372之前) aps.jar, aps-igexin.jar, GetuiSDK2.10.3.5.jar
SDK\libs(1.9.9.52372之后) aps-release.aar, aps-igexin-release.aar

需要将以下so文件放到工程的libs\armeabi目录下(1.9.9.52372版本之后不需要设置此项)

路径 文件名
SDK\libs\armeabi libgetuiext2.so
SDK\libs\armeabi-v7a libgetuiext2.so
SDK\libs\x86 libgetuiext2.so

需要引入工程的资源文件
需要将以下文件放到工程的res/layout目录下(1.9.9.52372版本之后不需要设置此项)

路径 文件名
SDK\res\layout getui_notification.xml
SDK\res\raw keep.xml

Androidmainfest.xml文件需要修改的项

需要在application节点前添加权限
因Android L(android 5.0)系统自身限制,多个应用安装时,如果拥有同一个Service权限,会导致权限冲突,只能安装一个带有此权限的应用。对此,个推SDK在声明自定义权限时需要添加apk的包名以避免和其他使用个推的应用冲突。

<uses-permission android:name="android.permission.INTERNET"/>  
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>  
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
<uses-permission android:name="android.permission.WAKE_LOCK"/>  
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
<uses-permission android:name="android.permission.VIBRATE"/>  
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>  
<uses-permission android:name="android.permission.CALL_PHONE"/>  
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>  
<uses-permission android:name="getui.permission.GetuiService.$你的APK包名"/>  
<permission android:name="getui.permission.GetuiService.$你的APK包名" android:protectionLevel="normal"/>  

<application>节点下配置如下代码

        <meta-data android:name="PUSH_APPID" android:value="$你自己的APPID"/>  
        <meta-data android:name="PUSH_APPKEY" android:value="$你的appkey"/>  
        <meta-data android:name="PUSH_APPSECRET" android:value="$你的appsecret"/>  
        <service  
            android:name="com.igexin.sdk.PushService"  
            android:exported="true"  
            android:label="NotificationCenter"  
            android:process=":pushservice">  
            <intent-filter>  
                <action android:name="com.igexin.sdk.action.service.message"/>  
            </intent-filter>  
        </service>  
        <receiver android:name="com.igexin.sdk.PushReceiver">  
            <intent-filter>  
                <action android:name="android.intent.action.BOOT_COMPLETED"/>  
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>  
                <action android:name="android.intent.action.USER_PRESENT"/>  
                <action android:name="com.igexin.sdk.action.refreshls"/>  
                <action android:name="android.intent.action.MEDIA_MOUNTED"/>  
                <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>  
                <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>  
            </intent-filter>  
        </receiver>  
        <activity  
            android:name="com.igexin.sdk.PushActivity"  
            android:excludeFromRecents="true"  
            android:exported="false"  
            android:process=":pushservice"  
            android:taskAffinity="com.igexin.sdk.PushActivityTask"  
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>  
        <activity  
            android:name="com.igexin.sdk.GActivity"  
            android:excludeFromRecents="true"  
            android:exported="true"  
            android:process=":pushservice"  
            android:taskAffinity="com.igexin.sdk.PushActivityTask"  
            android:theme="@android:style/Theme.Translucent.NoTitleBar"/>  
        <receiver android:name="io.dcloud.feature.apsGt.GTNotificationReceiver">  
            <intent-filter>  
                <action android:name="android.intent.action.BOOT_COMPLETED"/>  
                <action android:name="填写APK的包名.__CREATE_NOTIFICATION"/>  
                <action android:name="填写APK的包名.__REMOVE_NOTIFICATION"/>  
                <action android:name="填写APK的包名.__CLEAR_NOTIFICATION"/>  
                <action android:name="填写APK的包名.__CLILK_NOTIFICATION"/>  
            </intent-filter>  
        </receiver>  
        <service  
            android:name="io.dcloud.feature.apsGt.GTNormalIntentService"/>  

dcloud_properties.xml需要添加如下代码
dcloud_properties.xml文件在assets/data目录下
features节点下添加

<feature name="Push" value="io.dcloud.feature.aps.APSFeatureImpl"><module name="igexin" value="io.dcloud.feature.apsGt.GTPushService"/></feature>

services节点下添加

<service  
            name="push"  
            value="io.dcloud.feature.aps.APSFeatureImpl" />

小米推送

需要拷贝的文件

需要将以下jar/aar文件拷贝到工程中

路径 文件
SDK\libs(1.9.9.52372之前) aps.jar,aps-xiaomi.jar,MiPush_SDK_Client_3_1_2.jar,
SDK\libs(1.9.9.52372之后) aps-release.aar, aps-xiaomi-release.aar

Androidmainfest.xml文件需要修改的项

需要在application节点前添加权限

        <uses-permission android:name="android.permission.INTERNET"/>  
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>  
        <uses-permission android:name="android.permission.READ_PHONE_STATE"/>  
        <uses-permission android:name="android.permission.GET_TASKS"/>  
        <uses-permission android:name="android.permission.VIBRATE"/>  
        <uses-permission android:name="android.permission.GET_TASKS"/>  
        <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>  
<uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"/>   
<permission android:name="填写APK的包名.permission.MIPUSH_RECEIVE" android:protectionLevel="signature"/>  
<uses-permission android:name="填写APK的包名.permission.MIPUSH_RECEIVE"/>

application节点下配置如下代码

<service android:enabled="true" android:process=":pushservice" android:name="com.xiaomi.push.service.XMPushService"/>  
<service android:name="com.xiaomi.push.service.XMJobService" android:enabled="true" android:exported="false" android:permission="android.permission.BIND_JOB_SERVICE" android:process=":pushservice"/>  
<service android:enabled="true" android:exported="true" android:name="com.xiaomi.mipush.sdk.PushMessageHandler"/>  
<service android:enabled="true" android:name="com.xiaomi.mipush.sdk.MessageHandleService"/>  
<receiver android:exported="true" android:name="com.xiaomi.push.service.receivers.NetworkStatusReceiver">  
<intent-filter>  
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>  
<category android:name="android.intent.category.DEFAULT"/>  
</intent-filter>  
</receiver>  
<receiver android:exported="false" android:process=":pushservice" android:name="com.xiaomi.push.service.receivers.PingReceiver">  
<intent-filter>  
<action android:name="com.xiaomi.push.PING_TIMER"/>  
</intent-filter>  
</receiver>  
<receiver android:exported="true" android:name="io.dcloud.feature.apsXm.XMMessageReceiver">  
<intent-filter>  
<action android:name="com.xiaomi.mipush.RECEIVE_MESSAGE"/>  
</intent-filter>  
<intent-filter>  
<action android:name="com.xiaomi.mipush.MESSAGE_ARRIVED"/>  
</intent-filter>  
<intent-filter>  
<action android:name="com.xiaomi.mipush.ERROR"/>  
</intent-filter>  
</receiver>  
<receiver android:exported="true" android:name="io.dcloud.feature.apsXm.XMNotificationReceiver">  
<intent-filter>  
<action android:name="android.intent.action.BOOT_COMPLETED"/>  
<action android:name="%填写APK的包名%.__CREATE_NOTIFICATION"/>  
<action android:name="%填写APK的包名%.__REMOVE_NOTIFICATION"/>  
<action android:name="%填写APK的包名%.__CLEAR_NOTIFICATION"/>  
<action android:name="%填写APK的包名%.__CLILK_NOTIFICATION"/>  
</intent-filter>  
</receiver>  
<meta-data android:name="PUSH_APPID" android:value="_%小米推送的APPID%"/>  
<meta-data android:name="PUSH_APPKEY" android:value="_%小米推送的APPKEY%"/>

dcloud_properties.xml需要添加如下代码

dcloud_properties.xml文件在ADT工程assets/data目录下
Features节点下添加

<feature name="Push" value="io.dcloud.feature.aps.APSFeatureImpl">  
<module name="xiaomi" value="io.dcloud.feature.apsXm.XMPushService"/>  
</feature>

Service节点下添加

<service name="push" value="io.dcloud.feature.aps.APSFeatureImpl"/>
收起阅读 »

5+动画详解

截屏动画 pop_in 动画 窗口动画

转场动画是App非常重要的处理环境,要做到流畅不丢帧、快速渲染。

一般的动画只有300毫秒,要在短短的300毫秒内完成很多事情,包括新窗体创建、加载HTML、渲染内容、以60fps的方式移动窗体。。。
想想也是大难题。
所以开发者要非常重视动画的优化,否则很容易动画卡顿或页面渲染慢。

动画类型简述

5+中,Webview和nview均支持动画转场。这些动画都是native的动画,而不是css动画。
实际开发中,完全使用nview的动画转场比较少见,后面会单独介绍它的特殊用法,大多是Webview动画或含有subnview的Webview动画。

动画分进入和返回,这里是5+Webview的进入动画参数文档
http://html5plus.org/doc/zh_cn/webview.html#plus.webview.AnimationTypeShow

一般情况下,开发者只需要设置进入动画,返回动画是自动反向的。
比如设置进入是pop-in,那返回默认就是pop-out。
当然开发者也可以在返回时指定不同的动画类型,参考http://html5plus.org/doc/zh_cn/webview.html#plus.webview.AnimationTypeClose

常见的动画类型包括:
slide-in-right(从右侧横向滑入新窗体,覆盖老窗体)
pop-in(从右侧横向滑入新窗体,老窗体同时向左小幅移动,即新旧窗体联动挤压)
fade-in(从透明到不透明逐渐显示效果,常见于选项卡tab切换)

如果不指定动画类型,动画默认是slide-in-right。
pop-in是前后2个窗体联动挤压式动画,资源消耗大于slide-in-right,如果不注意优化,在Android手机上会有性能问题。

动画优化的常见策略

如果你的页面简单,使用默认的slide-in-right毫无性能问题,或者只是在iOS上使用pop-in,那可以暂时忽略本章节。
如果你页面复杂,或者使用了更耗资源的popin动画,或者动画已经出现卡顿、花屏、白屏等体验问题,请认真往下阅读。
做好动画的性能优化,一般有5招:

1. 动画期原生渲染

在Webview的style里设置titleNView和subnview,在动画期间让nview来渲染界面,而不是Webview。
nview的渲染速度比Webview快太多,并且动画稳定程度很高。
titleNView是几乎每个页面都必备的,subnview视情况而定。如果页面动画效果不够好,可以用这个来深度优化。
下面的视频是使用了subnview的流应用和原生应用的对比视频,可以看出subnview的效果非常好。https://v.qq.com/x/page/k05051mc143.html

2. 预载和重用

如果是列表到详情的转场,推荐使用预载+重用的方案。
在Hello mui的底部,有一个“从列表到详情的最佳实践”,就是把详情页面预载并重用了。每次点击列表上的item时,瞬间就出现了。
如果是本地数据或服务器联网非常快,这种方案甚至不需要动画过渡,把动画设为none,点击后界面立即出现。
具体方案有单独文章介绍:http://ask.dcloud.net.cn/article/12575
下面的视频就是应用了预载和重用的界面切换效果的视频对比:https://v.qq.com/x/page/v0507i0f05w.html

3. 截屏

动画期移动Webview的压力还是比较大的,尤其在低端机上运行popin动画,此时出现了一种截屏方案,即动画是移动的不是Webview,而是截图。
在窗体动画的规范里,http://html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewExtraOptions,有一个acceleration参数,值域包括 "auto" - 自动优化窗口动画; "none" - 关闭窗口动画加速功能; "capture" - 使用截屏方式加速窗口动画。 默认值为"auto"。
这里的capture,就是指动画时飘动的是截图而不是真的webview。
此时5+引擎在执行动画前,会先对新入的webview进行静态截屏,然后动画过程会移动静态截屏进来,这样的动画就会流畅稳定。而真实的Webview并不会移动。
但截屏方案也有需要注意的事项:

  • 注意1:截屏需要消耗时间,会导致动画的启动速度变慢几十或几百毫秒。如果是返回动画应用了截屏,那么会发现点了back后延迟了一点动画才启动。
  • 注意2:截屏后,动画期间就是静态图,不会在动画期间看到页面内容持续增加渲染的过程。
  • 注意3:变色问题。使用截屏加速动画如果发现动画界面的背景色变色,一般是因为新入窗体背景色设置了透明度,就是rgba里面的那个a,或者设置了渐变色。
    截屏动画使用的图像是不支持透明和渐变色的,建议把新webview里的透明度、渐变色相关设置去掉。不止是为了截屏动画不失真,在手机端透明度和渐变色本身也是非常耗费手机资源的,能不用就不用。

acceleration的默认值auto的策略需要详细解释下:
auto的意思是由5+引擎根据情况自动配置是否使用截屏加速,HBuilder8.3.3起,这个auto策略调整如下:

  • pop-in/pop-out动画
    Android5.0及以上:默认不使用截屏加速
    Android5.0以下:如果Webview中存在subNView则pop-in动画默认不使用截图加速,pop-out动画默认使用截图加速;如果Webview中不存在subNView则默认不使用截图加速
    使用截屏加速可能会引起动画延迟响应(截屏操作耗时),因此调整默认保证pop-in动画流畅, pop-out动画避免闪屏。

  • slide-*动画
    默认不使用截图加速
    此种情况下如果碰到页面分块渲染,应该避免在页面中使用高分辨率图片,或者关闭硬件加速,或者使用subNView来优化页面。具体参考http://ask.dcloud.net.cn/article/12837
    (之前版本在Android5.0及以下设备上窗口关闭时使用截图加速)

  • fade-in/fade-out动画
    默认使用截图加速

如果默认的auto策略不称心,开发者可以自行调整。创建Webview时生效,不支持创建后动态调整。

4. 减少动画期的其他运算

动画未完成时,也就是在动画运行的200-300毫秒期间,不管新入页面,还是老页面,都要注意节约计算和渲染资源,不要做消耗资源的其他事情。
新入页面的运算和渲染,要分层处理,与动画显示无关的部分,应该延后到动画结束后再处理。
举个例子,如果新入的界面里设置了plus提前生效并立即预载了另一个页面C,由于预载会占用cpu,过早预载就造成pop-in动画快结束时卡一下。其实页面C的预载不需要这么急,应该在新入页面loaded之后延时1秒再预载不迟。

5. 减少HTML页面的渲染复杂度

这是老生常谈的问题,但现实中还是大量App因为这个问题而导致性能体验出问题。
编写干净整洁、一次渲染的页面非常重要。
现在太多开发者在研究模式、框架,让页面渲染要经历二次、甚至四五次重绘才能完成。在短短几百毫秒的动画期间,这么干要不让页面卡、要不让渲染慢。
减少js二次渲染很重要的就是减少使用js渲染页面,页面结构要用简单朴素的HTML写,js可以动态填充数据,但如果js动态绘制页面主体,那渲染速度上不去。
减少css二次渲染,就是少用复杂的选择器,少用padding、margin这些会二次修正页面的css。

Android下popin动画的额外限制

两个webview挤压是比较容易做的,但3个或更多webview挤压会产生很多问题。目前只有iOS支持3个webview挤压动画。Android不支持3个webview的挤压动画。
从HBuilder8起,官方已经废除多Webview同屏并显、父子Webview之类的方案。如果开发者使用nview替代了同屏多Webview,就不会遇到这个坑。

nview动画在SPA应用中的使用场景

上面讲的基本是Webview的动画。其实5+还支持纯nview的动画。
假使开发者已经完成了一个SPA的单页应用,但动画肯定是卡的不行,此时可以把这个项目导入到HBuilder中,利用nview动画做一个封面动画,来弥补SPA的动画卡顿问题。比如点击列表项时:

  1. 使用js创建一个独立nview(不创建Webview,也不设置subnview,就是一个独立nview),在nview上自己画title和一些界面元素。
  2. 把这个nview做动画移动进来。这样动画看起来很平顺,虽然是一个假的封面吧。
  3. 不要再使用div动画了,让spa的详情视图的div直接渲染内容,渲染完毕后关闭nview,漏出SPA的div界面。
  4. 注意这种用法,nview的创建、位移、隐藏、关闭、重用,全部需要使用js api手动控制。
    具体参考http://html5plus.org/doc/zh_cn/nativeobj.html#plus.nativeObj.View

uni-app

uni-app框架层使用了自动的预载技术,转场非常快。
但有时新页面渲染太快,且新页面里渲染大图和新页面动画一起进行,就会抢资源,引发动画掉帧。
如果遇到这种问题,可适当延时新页面的大图加载,或优化图片尺寸。
uni-app还支持nvue的weex渲染,性能也很高。

继续阅读 »

转场动画是App非常重要的处理环境,要做到流畅不丢帧、快速渲染。

一般的动画只有300毫秒,要在短短的300毫秒内完成很多事情,包括新窗体创建、加载HTML、渲染内容、以60fps的方式移动窗体。。。
想想也是大难题。
所以开发者要非常重视动画的优化,否则很容易动画卡顿或页面渲染慢。

动画类型简述

5+中,Webview和nview均支持动画转场。这些动画都是native的动画,而不是css动画。
实际开发中,完全使用nview的动画转场比较少见,后面会单独介绍它的特殊用法,大多是Webview动画或含有subnview的Webview动画。

动画分进入和返回,这里是5+Webview的进入动画参数文档
http://html5plus.org/doc/zh_cn/webview.html#plus.webview.AnimationTypeShow

一般情况下,开发者只需要设置进入动画,返回动画是自动反向的。
比如设置进入是pop-in,那返回默认就是pop-out。
当然开发者也可以在返回时指定不同的动画类型,参考http://html5plus.org/doc/zh_cn/webview.html#plus.webview.AnimationTypeClose

常见的动画类型包括:
slide-in-right(从右侧横向滑入新窗体,覆盖老窗体)
pop-in(从右侧横向滑入新窗体,老窗体同时向左小幅移动,即新旧窗体联动挤压)
fade-in(从透明到不透明逐渐显示效果,常见于选项卡tab切换)

如果不指定动画类型,动画默认是slide-in-right。
pop-in是前后2个窗体联动挤压式动画,资源消耗大于slide-in-right,如果不注意优化,在Android手机上会有性能问题。

动画优化的常见策略

如果你的页面简单,使用默认的slide-in-right毫无性能问题,或者只是在iOS上使用pop-in,那可以暂时忽略本章节。
如果你页面复杂,或者使用了更耗资源的popin动画,或者动画已经出现卡顿、花屏、白屏等体验问题,请认真往下阅读。
做好动画的性能优化,一般有5招:

1. 动画期原生渲染

在Webview的style里设置titleNView和subnview,在动画期间让nview来渲染界面,而不是Webview。
nview的渲染速度比Webview快太多,并且动画稳定程度很高。
titleNView是几乎每个页面都必备的,subnview视情况而定。如果页面动画效果不够好,可以用这个来深度优化。
下面的视频是使用了subnview的流应用和原生应用的对比视频,可以看出subnview的效果非常好。https://v.qq.com/x/page/k05051mc143.html

2. 预载和重用

如果是列表到详情的转场,推荐使用预载+重用的方案。
在Hello mui的底部,有一个“从列表到详情的最佳实践”,就是把详情页面预载并重用了。每次点击列表上的item时,瞬间就出现了。
如果是本地数据或服务器联网非常快,这种方案甚至不需要动画过渡,把动画设为none,点击后界面立即出现。
具体方案有单独文章介绍:http://ask.dcloud.net.cn/article/12575
下面的视频就是应用了预载和重用的界面切换效果的视频对比:https://v.qq.com/x/page/v0507i0f05w.html

3. 截屏

动画期移动Webview的压力还是比较大的,尤其在低端机上运行popin动画,此时出现了一种截屏方案,即动画是移动的不是Webview,而是截图。
在窗体动画的规范里,http://html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewExtraOptions,有一个acceleration参数,值域包括 "auto" - 自动优化窗口动画; "none" - 关闭窗口动画加速功能; "capture" - 使用截屏方式加速窗口动画。 默认值为"auto"。
这里的capture,就是指动画时飘动的是截图而不是真的webview。
此时5+引擎在执行动画前,会先对新入的webview进行静态截屏,然后动画过程会移动静态截屏进来,这样的动画就会流畅稳定。而真实的Webview并不会移动。
但截屏方案也有需要注意的事项:

  • 注意1:截屏需要消耗时间,会导致动画的启动速度变慢几十或几百毫秒。如果是返回动画应用了截屏,那么会发现点了back后延迟了一点动画才启动。
  • 注意2:截屏后,动画期间就是静态图,不会在动画期间看到页面内容持续增加渲染的过程。
  • 注意3:变色问题。使用截屏加速动画如果发现动画界面的背景色变色,一般是因为新入窗体背景色设置了透明度,就是rgba里面的那个a,或者设置了渐变色。
    截屏动画使用的图像是不支持透明和渐变色的,建议把新webview里的透明度、渐变色相关设置去掉。不止是为了截屏动画不失真,在手机端透明度和渐变色本身也是非常耗费手机资源的,能不用就不用。

acceleration的默认值auto的策略需要详细解释下:
auto的意思是由5+引擎根据情况自动配置是否使用截屏加速,HBuilder8.3.3起,这个auto策略调整如下:

  • pop-in/pop-out动画
    Android5.0及以上:默认不使用截屏加速
    Android5.0以下:如果Webview中存在subNView则pop-in动画默认不使用截图加速,pop-out动画默认使用截图加速;如果Webview中不存在subNView则默认不使用截图加速
    使用截屏加速可能会引起动画延迟响应(截屏操作耗时),因此调整默认保证pop-in动画流畅, pop-out动画避免闪屏。

  • slide-*动画
    默认不使用截图加速
    此种情况下如果碰到页面分块渲染,应该避免在页面中使用高分辨率图片,或者关闭硬件加速,或者使用subNView来优化页面。具体参考http://ask.dcloud.net.cn/article/12837
    (之前版本在Android5.0及以下设备上窗口关闭时使用截图加速)

  • fade-in/fade-out动画
    默认使用截图加速

如果默认的auto策略不称心,开发者可以自行调整。创建Webview时生效,不支持创建后动态调整。

4. 减少动画期的其他运算

动画未完成时,也就是在动画运行的200-300毫秒期间,不管新入页面,还是老页面,都要注意节约计算和渲染资源,不要做消耗资源的其他事情。
新入页面的运算和渲染,要分层处理,与动画显示无关的部分,应该延后到动画结束后再处理。
举个例子,如果新入的界面里设置了plus提前生效并立即预载了另一个页面C,由于预载会占用cpu,过早预载就造成pop-in动画快结束时卡一下。其实页面C的预载不需要这么急,应该在新入页面loaded之后延时1秒再预载不迟。

5. 减少HTML页面的渲染复杂度

这是老生常谈的问题,但现实中还是大量App因为这个问题而导致性能体验出问题。
编写干净整洁、一次渲染的页面非常重要。
现在太多开发者在研究模式、框架,让页面渲染要经历二次、甚至四五次重绘才能完成。在短短几百毫秒的动画期间,这么干要不让页面卡、要不让渲染慢。
减少js二次渲染很重要的就是减少使用js渲染页面,页面结构要用简单朴素的HTML写,js可以动态填充数据,但如果js动态绘制页面主体,那渲染速度上不去。
减少css二次渲染,就是少用复杂的选择器,少用padding、margin这些会二次修正页面的css。

Android下popin动画的额外限制

两个webview挤压是比较容易做的,但3个或更多webview挤压会产生很多问题。目前只有iOS支持3个webview挤压动画。Android不支持3个webview的挤压动画。
从HBuilder8起,官方已经废除多Webview同屏并显、父子Webview之类的方案。如果开发者使用nview替代了同屏多Webview,就不会遇到这个坑。

nview动画在SPA应用中的使用场景

上面讲的基本是Webview的动画。其实5+还支持纯nview的动画。
假使开发者已经完成了一个SPA的单页应用,但动画肯定是卡的不行,此时可以把这个项目导入到HBuilder中,利用nview动画做一个封面动画,来弥补SPA的动画卡顿问题。比如点击列表项时:

  1. 使用js创建一个独立nview(不创建Webview,也不设置subnview,就是一个独立nview),在nview上自己画title和一些界面元素。
  2. 把这个nview做动画移动进来。这样动画看起来很平顺,虽然是一个假的封面吧。
  3. 不要再使用div动画了,让spa的详情视图的div直接渲染内容,渲染完毕后关闭nview,漏出SPA的div界面。
  4. 注意这种用法,nview的创建、位移、隐藏、关闭、重用,全部需要使用js api手动控制。
    具体参考http://html5plus.org/doc/zh_cn/nativeobj.html#plus.nativeObj.View

uni-app

uni-app框架层使用了自动的预载技术,转场非常快。
但有时新页面渲染太快,且新页面里渲染大图和新页面动画一起进行,就会抢资源,引发动画掉帧。
如果遇到这种问题,可适当延时新页面的大图加载,或优化图片尺寸。
uni-app还支持nvue的weex渲染,性能也很高。

收起阅读 »

一次app提交到商店错误的记录

提交app,上传过程中出现error

经检测 错误原因为manifest.json中 share appkey中有多余空格

继续阅读 »

提交app,上传过程中出现error

经检测 错误原因为manifest.json中 share appkey中有多余空格

收起阅读 »

Android平台通过native.js实现接收系统消息,如监听安装卸载apk事件

Native.JS 广播 Broadcast

今天以监听apk安装、卸载为例,来说明系统广播(BroadcastReceiver)如何监听,代码如下:

    var receiver;  
    main = plus.android.runtimeMainActivity();//获取activity  
    receiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver',{  
        onReceive : function(context,intent){//实现onReceiver回调函数  
        plus.android.importClass(intent);//通过intent实例引入intent类,方便以后的‘.’操作  
        console.log(intent.getAction());//获取action  
        main.unregisterReceiver(receiver);//取消监听  
    }});  
    var IntentFilter = plus.android.importClass('android.content.IntentFilter');  
    var Intent = plus.android.importClass('android.content.Intent');  
    var filter = new IntentFilter();  
    filter.addAction(Intent.ACTION_PACKAGE_ADDED);//监听apk安装  
    filter.addAction(Intent.ACTION_PACKAGE_REMOVED);//监听apk卸载  
    filter.addDataScheme("package");  
    main.registerReceiver(receiver,filter);//注册监听
继续阅读 »

今天以监听apk安装、卸载为例,来说明系统广播(BroadcastReceiver)如何监听,代码如下:

    var receiver;  
    main = plus.android.runtimeMainActivity();//获取activity  
    receiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver',{  
        onReceive : function(context,intent){//实现onReceiver回调函数  
        plus.android.importClass(intent);//通过intent实例引入intent类,方便以后的‘.’操作  
        console.log(intent.getAction());//获取action  
        main.unregisterReceiver(receiver);//取消监听  
    }});  
    var IntentFilter = plus.android.importClass('android.content.IntentFilter');  
    var Intent = plus.android.importClass('android.content.Intent');  
    var filter = new IntentFilter();  
    filter.addAction(Intent.ACTION_PACKAGE_ADDED);//监听apk安装  
    filter.addAction(Intent.ACTION_PACKAGE_REMOVED);//监听apk卸载  
    filter.addDataScheme("package");  
    main.registerReceiver(receiver,filter);//注册监听
收起阅读 »

使用mui和h5+后依然存在跨域问题的解决方案

跨域请求

将AndroidManifest.xml文件中的android:targetSdkVersion去掉就可以了。

将AndroidManifest.xml文件中的android:targetSdkVersion去掉就可以了。