HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

微信支付,调用返回-1

微信支付

1.在后台生成的签名,必须是生成预支付id后再次生成的签名
2.APP内json配置支付appid必须与商户内生成的id一致

  1. 必须用自己的证书打包后,才能正常调用
    4.调用微信支付的时候参数顺序
    appid: resObj.data.appid,  
    noncestr: resObj.data.noncestr,  
    package: resObj.data.package,  
    partnerid: resObj.data.partnerid,  
    prepayid: resObj.data.prepayid,  
    timestamp: resObj.data.timestamp,  
    sign: resObj.data.sign

    5.timestamp 类型为number

继续阅读 »

1.在后台生成的签名,必须是生成预支付id后再次生成的签名
2.APP内json配置支付appid必须与商户内生成的id一致

  1. 必须用自己的证书打包后,才能正常调用
    4.调用微信支付的时候参数顺序
    appid: resObj.data.appid,  
    noncestr: resObj.data.noncestr,  
    package: resObj.data.package,  
    partnerid: resObj.data.partnerid,  
    prepayid: resObj.data.prepayid,  
    timestamp: resObj.data.timestamp,  
    sign: resObj.data.sign

    5.timestamp 类型为number

收起阅读 »

客户端破解以后,我们怎么解决,赤裸裸的数据交互解决

数据交互

环境前提:
1.客户端已被破解可以查看到数据交互的api接口
2.账号密码没有存在本地手机存储内
3.登录密码没有第二个人知道
4.服务器登录有Oauth2.0进行授权登录。没有的需要搭建一个授权服务器。
5.手机已经ROOT,可以获得本机设备id和互联网唯一标识id,还有token。
需要解决的问题集合:
1.担心客户端破解以后所有的api接口都暴露出来有攻击的威胁。
2.账号密码存在本地,被root过手机的恶意程序获得账号密码。
3.获得token以后伪造设备id等唯一标识符操作数据,存在威胁。
4.自动登录的问题怎么解决。
安全解决原理:
解决第1个问题:
第一次登录成功账号,则获得一个授权服务器分配的token,以后所有的数据操作都是用token进行操作。
账号密码没有存在本地,则跟服务通讯的时候需要有一个token(令牌)。
token令牌的生成:则需要登录成功以后获得本地手机的设备ID和互联网唯一标识id来绑定这个token只能在这个手机上面进行操作。如果token被坏人截获,在使用token获取api接口数据的时候则自动验证此token失效,因为token匹配手机的设备ID和互联网唯一标识id变动了。token失效以后需要重新登录才可以获得正确的token,因为坏人不知道账号密码所以没有办法登录,手机端被破解以后,账号密码也没有保存在本地所以也不知道账号密码,有小伙伴就问了第一次登录的时候被截获怎么办,那答案就是登录授权服务器的时候用的是https(ssl)加密协议登录的,所以这个破解的几率还是有一点难度。
注解:客户端被破解出来所有的传递的字段都看到了,api接口的地址也知道了,就会有坏人恶意操作,通过这个token就可以解决第一个问题。
解决第2个问题:
因为是使用的token操作,所有本地不存账号密码这些机密数据,及时手机被root了也获得不了账号密码。只能获得token数据。这个token是唯一的只能在本机使用,如果伪造这个本机的设备id和互联网id,则这个账号可以在别的设备上登录,前提是别的设备的编号要可以伪造。
解决第3个问题:
退3步说话,如果token被别人获得了,设备id被别人获得了,那别人就可以伪造id和使用token来操作数据了,是的,这怎么办?你获取的数据基本都是这个token用户的数据,其他的用户你威胁不了,至少区域给你限制住了,ok,继续看下一步,如果你恶意刷新获取服务器公共资源数据,那管理员直接在授权服务器授权每个用户获取公共资源每天的次数限制一下即可,你恶意获取次数是有限的,如果获得这个用户的token修改密码怎么办,好办,在更改密码的时候验证手机号短信即可,验证成功则可以修改密码,验证不成功则不能修改密码。涉及到资金交易的,只需要设置每笔资金交易有交易密码就OK,用token交易的时候没有交易密码也是白扯。
解决第4个问题:
直接传递token去服务器验证即可,验证通过就登录成功,验证不通过就显示登录账户密码进行登录。
收集各位小宇宙的猜想,看看还有什么攻击我没想到,还有什么问题我没解决,大家一起来解决,一起来猜想,多多交流!

继续阅读 »

环境前提:
1.客户端已被破解可以查看到数据交互的api接口
2.账号密码没有存在本地手机存储内
3.登录密码没有第二个人知道
4.服务器登录有Oauth2.0进行授权登录。没有的需要搭建一个授权服务器。
5.手机已经ROOT,可以获得本机设备id和互联网唯一标识id,还有token。
需要解决的问题集合:
1.担心客户端破解以后所有的api接口都暴露出来有攻击的威胁。
2.账号密码存在本地,被root过手机的恶意程序获得账号密码。
3.获得token以后伪造设备id等唯一标识符操作数据,存在威胁。
4.自动登录的问题怎么解决。
安全解决原理:
解决第1个问题:
第一次登录成功账号,则获得一个授权服务器分配的token,以后所有的数据操作都是用token进行操作。
账号密码没有存在本地,则跟服务通讯的时候需要有一个token(令牌)。
token令牌的生成:则需要登录成功以后获得本地手机的设备ID和互联网唯一标识id来绑定这个token只能在这个手机上面进行操作。如果token被坏人截获,在使用token获取api接口数据的时候则自动验证此token失效,因为token匹配手机的设备ID和互联网唯一标识id变动了。token失效以后需要重新登录才可以获得正确的token,因为坏人不知道账号密码所以没有办法登录,手机端被破解以后,账号密码也没有保存在本地所以也不知道账号密码,有小伙伴就问了第一次登录的时候被截获怎么办,那答案就是登录授权服务器的时候用的是https(ssl)加密协议登录的,所以这个破解的几率还是有一点难度。
注解:客户端被破解出来所有的传递的字段都看到了,api接口的地址也知道了,就会有坏人恶意操作,通过这个token就可以解决第一个问题。
解决第2个问题:
因为是使用的token操作,所有本地不存账号密码这些机密数据,及时手机被root了也获得不了账号密码。只能获得token数据。这个token是唯一的只能在本机使用,如果伪造这个本机的设备id和互联网id,则这个账号可以在别的设备上登录,前提是别的设备的编号要可以伪造。
解决第3个问题:
退3步说话,如果token被别人获得了,设备id被别人获得了,那别人就可以伪造id和使用token来操作数据了,是的,这怎么办?你获取的数据基本都是这个token用户的数据,其他的用户你威胁不了,至少区域给你限制住了,ok,继续看下一步,如果你恶意刷新获取服务器公共资源数据,那管理员直接在授权服务器授权每个用户获取公共资源每天的次数限制一下即可,你恶意获取次数是有限的,如果获得这个用户的token修改密码怎么办,好办,在更改密码的时候验证手机号短信即可,验证成功则可以修改密码,验证不成功则不能修改密码。涉及到资金交易的,只需要设置每笔资金交易有交易密码就OK,用token交易的时候没有交易密码也是白扯。
解决第4个问题:
直接传递token去服务器验证即可,验证通过就登录成功,验证不通过就显示登录账户密码进行登录。
收集各位小宇宙的猜想,看看还有什么攻击我没想到,还有什么问题我没解决,大家一起来解决,一起来猜想,多多交流!

收起阅读 »

分享如何将mui.js整合进vue项目

Vue mui

具体vue项目创建不介绍了,你可以按照你的心情创建单/多入口文件的vue项目。
重点是如何整合mui.js
大神自有办法,不用我置喙,这里主要写给想用vue,又想把时间花费在业务上的小伙伴。

打包工具用的webpack。这里示例用的是SPA单页面文件,其实没有影响,随你心情

第一步,配置webpack


module.exports = {  
    entry: {  
        app: './src/main.js'  
    },  
    output: {  
        ...  
    },  
    externals: {  
        mui: 'mui'  
    },  
    .....

如果像我一样单页面,只有一个index.html。直接可以用html打包插件,
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),

第二步 正常编写基础逻辑

<!DOCTYPE html>  
<html>  

<head>  
    <meta charset="utf-8">  
    <title>jmapp</title>  
    <link rel="stylesheet" href="http://dev.dcloud.net.cn/mui/dist/css/mui.min.css">  

</head>  

<body>  
    <div id="app"></div>  
    <!-- built files will be auto injected -->  
    <script src="http://dev.dcloud.net.cn/mui/dist/js/mui.min.js">  
    </script>  
    <script>  
        mui.init();  
        mui.plusReady(function() {  
        });  
    </script>  
</body>  

</html>

第三部,vue工程里正常直接使用,无须引用

methods: {  

    login() {  
      if (this.user.length < 1) {  
        mui.alert("roshan")  
      }  
    }  
  }

说到底就是

externals: {  
        mui: 'mui'  
    },

只有这一句话有作用。

因为mui使用了匿名递归不能直接require 自然也不能用amd方式加载到es6代码中,vue的严格模式下会报错。
变通方法就是自己引入。。。。。。

希望mui源码转向es6版本。

继续阅读 »

具体vue项目创建不介绍了,你可以按照你的心情创建单/多入口文件的vue项目。
重点是如何整合mui.js
大神自有办法,不用我置喙,这里主要写给想用vue,又想把时间花费在业务上的小伙伴。

打包工具用的webpack。这里示例用的是SPA单页面文件,其实没有影响,随你心情

第一步,配置webpack


module.exports = {  
    entry: {  
        app: './src/main.js'  
    },  
    output: {  
        ...  
    },  
    externals: {  
        mui: 'mui'  
    },  
    .....

如果像我一样单页面,只有一个index.html。直接可以用html打包插件,
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),

第二步 正常编写基础逻辑

<!DOCTYPE html>  
<html>  

<head>  
    <meta charset="utf-8">  
    <title>jmapp</title>  
    <link rel="stylesheet" href="http://dev.dcloud.net.cn/mui/dist/css/mui.min.css">  

</head>  

<body>  
    <div id="app"></div>  
    <!-- built files will be auto injected -->  
    <script src="http://dev.dcloud.net.cn/mui/dist/js/mui.min.js">  
    </script>  
    <script>  
        mui.init();  
        mui.plusReady(function() {  
        });  
    </script>  
</body>  

</html>

第三部,vue工程里正常直接使用,无须引用

methods: {  

    login() {  
      if (this.user.length < 1) {  
        mui.alert("roshan")  
      }  
    }  
  }

说到底就是

externals: {  
        mui: 'mui'  
    },

只有这一句话有作用。

因为mui使用了匿名递归不能直接require 自然也不能用amd方式加载到es6代码中,vue的严格模式下会报错。
变通方法就是自己引入。。。。。。

希望mui源码转向es6版本。

收起阅读 »

HBuilder8.8里程碑版本发布,App体验快到震惊!

体验

提起HTML5跨平台应用,大多数人的理解都是:哦,比原生差点,要求不高可以用。
DCloud可不喜欢“比原生差点”这个帽子,这次就要摘掉它!
让我们和原生版好好比比。同时用2台手机操作原生应用和基于HTML5+的流应用,看看到底哪个快?
 

视频对比1:

实验环境说明:
手机设备相同(华为荣耀8青春版,2016年上市,千元机代表)、网络环境相同、使用前均清理了内存,原生应用使用最新版。

实验视频:唯品会、大众点评流应用与原生应用对比

实验结论:
HTML5+版的流应用,新页面渲染速度和原生不相上下,在300毫秒的动画期间即可渲染,而且动画平顺。
惊艳吧?别急着惊艳,好戏还在后头:)

视频对比2:

实验环境说明:
手机设备相同(小米note1代,2015年上市,目前属于低端机代表)、网络环境相同、使用前均清理了内存,原生应用使用最新版。

实验视频:今日头条流应用与原生应用对比
 
实验结论:
HTML5+版的流应用,比原生应用加载还快!!!
这就不是惊艳了,而是惊讶吧。有种世界观被摧毁的感觉Orz。别急,让我们继续帮你建立新的世界观:)

视频对比3:

实验环境说明:
这次手机设备不同,原生应用运行在更好的手机:华为荣耀8高配版,cpu是麒麟950,价位为2千元左右。而HTML5+版的运行在低配的华为荣耀8青春版上,cpu是麒麟655,价位是1千元出头。这次原生应用能借助手机硬件优势扳回一局吗?

实验视频:
蘑菇街流应用与原生应用对比

实验结论:
纵然手机价差近千元,低端机上的HTML5+版流应用加载速度也毫不逊色原生应用。
新的世界观建立了吗?
是的,请摘掉“比原生差点”的帽子!

看视频不够?那就赶紧亲手操作体验吧。
手机浏览器访问:m3w.cn ,下载流应用管理器,点击里面的唯品会、大众点评、今日头条。。。来场震撼体验!

什么,你不知道流应用是啥?所有基于HTML5+开发的移动App,提交到DCloud的发行平台,就是流应用。

嗯,这就是HBuilder8.8,快到没朋友!

FAQ:
Q:加载这么快,是不是提前加载了很多用户可能并不会点的内容?
A:不会。图片也好、新闻内容也好,都是在用户点击后才下载的。咱不搞障眼法。
Q:原生可不可以更快?
A:可以。不管是原生还是流应用,这些应用都没有优化到极限。
Q:js比原生快不合逻辑?
A:其实没有所谓的真原生,java并不是原生,webkit是c写的,使用得当并不慢。
好了,我们并不想引起语言战争。摘掉HTML5+应用体验不如原生的帽子就可以了:)
不过只会一种语言的工程师不是好工程师,建议原生工程师也学学js。

想要你的App也这么快吗?
赶紧升级HBuilder8.8!
研究新版的Hello mui示例里:列表到详情最佳实践模板。大部分场景复制这个模板就可以加速渲染。复杂场景可研究5+新出的subnview神器。(直接打包老App并不会让加载变快)

HBuilder8.8另一个重要升级就是支持了完善的vue语法提示,
详见http://ask.dcloud.net.cn/article/12582

快来和百万HTML5开发者一起使用HBuilder吧。

好消息还有:金立手机已经预置流应用引擎,并在金立应用商店上可以发行秒开的流应用了。不用再说流应用只能在360上运行了。更多手机厂商的合作仍在进行中,敬请期待。详情参考http://mp.weixin.qq.com/s/heWcuLhakJPx5wKoqY5ncQ

HBuilder8.8更新日志:

【重要】App引擎大幅升级体验,新页面加载极速渲染。

IDE

>* 【重要】支持vue.js框架语法提示,参考http://ask.dcloud.net.cn/article/12582

  • 【重要】windows下边改边看浏览器支持手机模拟效果,支持touch事件。移动App项目默认为touch模式,web项目可以在边改边看浏览器上方菜单进行选择
  • 【重要】移动App打包时原生js混淆功能从alpha版升级到正式版,可以安全高效的保护代码和关键配置
  • 添加在编辑器上可以通过shift+鼠标滚轮调节横向滚动条的功能
  • 添加html中script的type=[text/ecmascript-6,text/ecmascript]时代码高亮
  • manifest可视化编辑器添加"Apple应用内支付"的配置项
  • 解决控制台中Ctrl+F快捷键不起作用的问题
  • 解决原生App打包有时弹出异常错误提示的问题
  • 解决原生App打包有时自动下载获取的文件名不正确的问题
  • 解决html中输入script按tab后没有生成script标签的问题
  • 解决有时还原环境后没有自动导入默认目录下所有已存在项目的问题
  • 解决向上移动行(Ctrl+向上)选中的内容首行为空时移动后可能会多复制一行的问题
  • 解决typescript文件某些情况下选中代码提示某项回车后,光标位置不正确的问题

App

>* 【重要】新增Webview窗口支持添加原生View控件(subNViews),原生控件渲染加速页面加载速度 http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewSubNViewStyles

  • 【重要】调整navigationbar为titleNView,与subNView统一理念,并补充buttons配置,方便配置右侧按钮
  • 【重要】新增Webview窗口原生标题栏控件(titleNView)支持沉浸式题图显示效果,图片滚动后原生标题栏渐变出现
  • 新增Webview窗口支持设置原生处理返回键功能(backButtonAutoControl),提升页面关闭响应速度 http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewTitleNViewStyles
  • 新增原生图片轮播控件(plus.nativeObj.ImageSlider),支持点击放大全屏浏览 http://www.html5plus.org/doc/zh_cn/nativeobj.html#plus.nativeObj.ImageSlider
  • Android平台优化应用资源保存目录(由sdcard下目录调整到应用私有目录),防止被清理软件删除引起应用页面无法打开的问题
  • Android平台修复在部分设备上从二级窗口返回可能出现白屏的问题
  • Android平台修复在特定情况下窗口动画效果不正确的问题
  • Android平台修复横竖屏切换后获取屏幕分辨率可能不正确的问题
  • Android平台修复plus.webview.startAnimation方法不设置回调参数可能引起崩溃的问题
  • Android平台修复二维码中字符串中包含换行符时扫描可能出错的问题
  • Android平台修复在特定情况下崩溃日志可能提交不成功的问题
  • Android平台修复设置屏幕亮度(plus.screen.setBrightness)可能不生效的问题
  • Android平台修复友盟统计channel参数设置无效的问题
  • iOS平台修复应用设置为全屏显示时系统状态栏可能不消失的问题
  • iOS平台修复webview作为子窗口时调用isVisible()总是返回false的问题
  • iOS平台修复Webview窗口设置softinputMode属性值为adjustResize时软键盘消失可能显示不正常的问题
  • iOS平台修复wgt更新应用资源后重启应用可能导致系统状态栏样式显示不正确的问题
  • iOS平台修复wgt/wgut更新时如果模块配置不一致可能导致失败的问题
  • iOS平台修复启动第三方应用可能不触发pause/resume事件的问题

MUI

>* 【重要】Hello MUI新增列表到详情最佳实践模板,演示窗口动画期实现详情页渲染,教程参考:http://ask.dcloud.net.cn/article/12575

流应用

>* 金立手机流应用上线,rom级的支持,完美体验。参考http://mp.weixin.qq.com/s/heWcuLhakJPx5wKoqY5ncQ

有人问mui是否支持vue?
mui是一个ui框架,特点是使用原生html、js和css,更高效。
在某些场景下,mui可以和vue结合,在官方最新的Hello mui示例里的“列表到详情最佳实践模板”,就应用了vue。

继续阅读 »

提起HTML5跨平台应用,大多数人的理解都是:哦,比原生差点,要求不高可以用。
DCloud可不喜欢“比原生差点”这个帽子,这次就要摘掉它!
让我们和原生版好好比比。同时用2台手机操作原生应用和基于HTML5+的流应用,看看到底哪个快?
 

视频对比1:

实验环境说明:
手机设备相同(华为荣耀8青春版,2016年上市,千元机代表)、网络环境相同、使用前均清理了内存,原生应用使用最新版。

实验视频:唯品会、大众点评流应用与原生应用对比

实验结论:
HTML5+版的流应用,新页面渲染速度和原生不相上下,在300毫秒的动画期间即可渲染,而且动画平顺。
惊艳吧?别急着惊艳,好戏还在后头:)

视频对比2:

实验环境说明:
手机设备相同(小米note1代,2015年上市,目前属于低端机代表)、网络环境相同、使用前均清理了内存,原生应用使用最新版。

实验视频:今日头条流应用与原生应用对比
 
实验结论:
HTML5+版的流应用,比原生应用加载还快!!!
这就不是惊艳了,而是惊讶吧。有种世界观被摧毁的感觉Orz。别急,让我们继续帮你建立新的世界观:)

视频对比3:

实验环境说明:
这次手机设备不同,原生应用运行在更好的手机:华为荣耀8高配版,cpu是麒麟950,价位为2千元左右。而HTML5+版的运行在低配的华为荣耀8青春版上,cpu是麒麟655,价位是1千元出头。这次原生应用能借助手机硬件优势扳回一局吗?

实验视频:
蘑菇街流应用与原生应用对比

实验结论:
纵然手机价差近千元,低端机上的HTML5+版流应用加载速度也毫不逊色原生应用。
新的世界观建立了吗?
是的,请摘掉“比原生差点”的帽子!

看视频不够?那就赶紧亲手操作体验吧。
手机浏览器访问:m3w.cn ,下载流应用管理器,点击里面的唯品会、大众点评、今日头条。。。来场震撼体验!

什么,你不知道流应用是啥?所有基于HTML5+开发的移动App,提交到DCloud的发行平台,就是流应用。

嗯,这就是HBuilder8.8,快到没朋友!

FAQ:
Q:加载这么快,是不是提前加载了很多用户可能并不会点的内容?
A:不会。图片也好、新闻内容也好,都是在用户点击后才下载的。咱不搞障眼法。
Q:原生可不可以更快?
A:可以。不管是原生还是流应用,这些应用都没有优化到极限。
Q:js比原生快不合逻辑?
A:其实没有所谓的真原生,java并不是原生,webkit是c写的,使用得当并不慢。
好了,我们并不想引起语言战争。摘掉HTML5+应用体验不如原生的帽子就可以了:)
不过只会一种语言的工程师不是好工程师,建议原生工程师也学学js。

想要你的App也这么快吗?
赶紧升级HBuilder8.8!
研究新版的Hello mui示例里:列表到详情最佳实践模板。大部分场景复制这个模板就可以加速渲染。复杂场景可研究5+新出的subnview神器。(直接打包老App并不会让加载变快)

HBuilder8.8另一个重要升级就是支持了完善的vue语法提示,
详见http://ask.dcloud.net.cn/article/12582

快来和百万HTML5开发者一起使用HBuilder吧。

好消息还有:金立手机已经预置流应用引擎,并在金立应用商店上可以发行秒开的流应用了。不用再说流应用只能在360上运行了。更多手机厂商的合作仍在进行中,敬请期待。详情参考http://mp.weixin.qq.com/s/heWcuLhakJPx5wKoqY5ncQ

HBuilder8.8更新日志:

【重要】App引擎大幅升级体验,新页面加载极速渲染。

IDE

>* 【重要】支持vue.js框架语法提示,参考http://ask.dcloud.net.cn/article/12582

  • 【重要】windows下边改边看浏览器支持手机模拟效果,支持touch事件。移动App项目默认为touch模式,web项目可以在边改边看浏览器上方菜单进行选择
  • 【重要】移动App打包时原生js混淆功能从alpha版升级到正式版,可以安全高效的保护代码和关键配置
  • 添加在编辑器上可以通过shift+鼠标滚轮调节横向滚动条的功能
  • 添加html中script的type=[text/ecmascript-6,text/ecmascript]时代码高亮
  • manifest可视化编辑器添加"Apple应用内支付"的配置项
  • 解决控制台中Ctrl+F快捷键不起作用的问题
  • 解决原生App打包有时弹出异常错误提示的问题
  • 解决原生App打包有时自动下载获取的文件名不正确的问题
  • 解决html中输入script按tab后没有生成script标签的问题
  • 解决有时还原环境后没有自动导入默认目录下所有已存在项目的问题
  • 解决向上移动行(Ctrl+向上)选中的内容首行为空时移动后可能会多复制一行的问题
  • 解决typescript文件某些情况下选中代码提示某项回车后,光标位置不正确的问题

App

>* 【重要】新增Webview窗口支持添加原生View控件(subNViews),原生控件渲染加速页面加载速度 http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewSubNViewStyles

  • 【重要】调整navigationbar为titleNView,与subNView统一理念,并补充buttons配置,方便配置右侧按钮
  • 【重要】新增Webview窗口原生标题栏控件(titleNView)支持沉浸式题图显示效果,图片滚动后原生标题栏渐变出现
  • 新增Webview窗口支持设置原生处理返回键功能(backButtonAutoControl),提升页面关闭响应速度 http://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewTitleNViewStyles
  • 新增原生图片轮播控件(plus.nativeObj.ImageSlider),支持点击放大全屏浏览 http://www.html5plus.org/doc/zh_cn/nativeobj.html#plus.nativeObj.ImageSlider
  • Android平台优化应用资源保存目录(由sdcard下目录调整到应用私有目录),防止被清理软件删除引起应用页面无法打开的问题
  • Android平台修复在部分设备上从二级窗口返回可能出现白屏的问题
  • Android平台修复在特定情况下窗口动画效果不正确的问题
  • Android平台修复横竖屏切换后获取屏幕分辨率可能不正确的问题
  • Android平台修复plus.webview.startAnimation方法不设置回调参数可能引起崩溃的问题
  • Android平台修复二维码中字符串中包含换行符时扫描可能出错的问题
  • Android平台修复在特定情况下崩溃日志可能提交不成功的问题
  • Android平台修复设置屏幕亮度(plus.screen.setBrightness)可能不生效的问题
  • Android平台修复友盟统计channel参数设置无效的问题
  • iOS平台修复应用设置为全屏显示时系统状态栏可能不消失的问题
  • iOS平台修复webview作为子窗口时调用isVisible()总是返回false的问题
  • iOS平台修复Webview窗口设置softinputMode属性值为adjustResize时软键盘消失可能显示不正常的问题
  • iOS平台修复wgt更新应用资源后重启应用可能导致系统状态栏样式显示不正确的问题
  • iOS平台修复wgt/wgut更新时如果模块配置不一致可能导致失败的问题
  • iOS平台修复启动第三方应用可能不触发pause/resume事件的问题

MUI

>* 【重要】Hello MUI新增列表到详情最佳实践模板,演示窗口动画期实现详情页渲染,教程参考:http://ask.dcloud.net.cn/article/12575

流应用

>* 金立手机流应用上线,rom级的支持,完美体验。参考http://mp.weixin.qq.com/s/heWcuLhakJPx5wKoqY5ncQ

有人问mui是否支持vue?
mui是一个ui框架,特点是使用原生html、js和css,更高效。
在某些场景下,mui可以和vue结合,在官方最新的Hello mui示例里的“列表到详情最佳实践模板”,就应用了vue。

收起阅读 »

Hello MUI发布列表到详情最佳实践

页面跳转 上拉加载 窗口动画 详情 列表 Vue 下拉刷新 模板

Hello MUI在“模板”分类中增加了“列表到详情最佳实践”,先看效果:

列表到详情最佳实践

从如上gif图中,可看出本示例的主要特点:点击列表瞬间打开详情页,并且详情页已渲染完毕,效果堪比原生App!

本模板设计目标:演示在窗口动画期间完成页面渲染

下面简单介绍一下实现思路,开发者可以套用这个模板,修改服务端地址及对应业务参数,即可实现同样流畅平滑的窗口切换效果。

实现思路:

预加载详情页

在列表页中预加载详情页,列表页中点击某新闻时,通过自定义事件通知详情页加载对应新闻详情,这样可以避免每次打开新闻详情时重新创建webview的资源消耗。

mui.plusReady(function() {  
    //预加载详情页  
    webview_detail = mui.preload({  
        url: 'detail.html',  
        id: 'vue_demo_detail',  
        styles: {  
            "render": "always",//一直渲染  
            "popGesture": "hide",  
            "titleNView": titleNView//使用原生渐变导航  
        }  
    });  
});

复用前页数据

详情页的内容需要通过ajax从服务端动态获取,获取之后再渲染,这里需要耗费一定的时间;如果网络不好,用户就会看到白屏或空页面,体验不好;
实际上,详情页部分内容在列表页已经加载过,可以直接从列表页传递过来(自定义事件耗时<10毫秒),而无需等待网络响应(ajax耗时 > 50毫秒)。因此,在列表页点击事件中,将列表页已加载的、详情页也需要的信息通过自定义事件传递给详情页,详情页将这些数据立即渲染,然后再通过ajax动态获取其余部分的数据。

1、列表页点击事件中传递已加载数据

//触发子窗口变更新闻详情  
mui.fire(webview_detail, 'get_detail', {  
    guid: guid,  
    title:title,  
    author:author,  
    time:time,  
    cover:cover  
});

2、详情页获取前页数据后,立即渲染,再通过ajx请求其余数据

//监听自定义事件,获取新闻详情  
document.addEventListener('get_detail', function(event) {  
    var guid = event.detail.guid;  
    if(!guid) {  
        return;  
    }  
    //前页传入的数据,直接渲染,无需等待ajax请求详情后  
    vm.cover = event.detail.cover;  
    vm.title = event.detail.title;  
    vm.author = event.detail.author;  
    vm.time = event.detail.time;  
    //向服务端请求文章详情内容  
    mui.ajax('your-server-url' + guid, {  
        type:'GET',  
        dataType: 'json', //服务器返回json格式数据  
        timeout: 15000, //15秒超时  
        success: function(rsp) {  
            vm.content = rsp.content;  
        },  
        error: function(xhr, type, errorThrown) {  
            mui.toast('获取文章内容失败');  
            //TODO 此处可以向服务端告警  
        }  
    });  
});

详情页返回时重置页面数据

为了避免打开下一个新闻详情时,闪一下上一个新闻详情,模板在详情页返回时,会清空详情页数据;因为本模板使用了vue框架,实际上执行的就是重置vue数据。

实现较为简单,重写mui.back,代码示例如下:

//重写返回逻辑,返回时隐藏详情页webview  
mui.back = function() {  
    plus.webview.currentWebview().hide("auto", 300);  
}  
//窗口隐藏时,重置页面数据  
mui.plusReady(function () {  
    var self = plus.webview.currentWebview();  
    self.addEventListener("hide",function (e) {  
        window.scrollTo(0, 0);//重置滚动条位置  
        vm.resetData();//重置页面数据  
    },false);  
})

其中,vm.resetData()为清空vue数据的方法。

致谢,感谢 @redonion42@163.com 建议,通过hide事件同时处理back按键、侧滑返回的重置需求。

提高网络响应

核心实现就如上两点,开发者按照这种模板就可以做出同样流畅的App。如果发现响应缓慢,注意检查两点:

  • 减少网络传输量,让服务端仅返回前端需要的字段
  • 利用缓存等技术优化服务端响应,保证ajax请求可以在100毫秒之内获得响应

关联功能点

按照如上思路实现的“列表到详情最佳实践”,还牵扯到一些关联知识点:

1、集成vue
本示例的列表页、详情页均使用了vue框架实现数据绑定,涉及到vue的列表渲染、数据重置知识点,内容较为简单,源码完全开源,本文不再详述。

2、下拉刷新、上拉加载
列表页集成了下拉刷新、上拉加载,代码示例如下:

mui.init({  
    pullRefresh: {  
        container: '#list',  
        down: {  
            style: 'circle',  
            offset: '0px',  
            auto: true,  
            callback: pulldownRefresh  
        },  
        up: {  
            contentrefresh: '正在加载...',  
            callback: pullupRefresh  
        }  
    }  
});

相关教程参考:

3、透明渐变导航
详情页使用了原生版本的透明渐变导航,参考教程

在点击不同新闻详情页时,需要改变原生导航条上的标题内容,通过重新设置webview的style属性即可,示例如下:

    //更改详情页原生导航条信息  
    titleNView.titleText = title;  
    webview_detail.setStyle({  
        "titleNView": titleNView  
    });

Hello MUI中体验

最新版的Hello MUI已集成了"列表到详情最佳实践",在HBuilder 8.8.0+ 版本中即可体验,体验路径:Hello MUI首页--> 列表到详情最佳实践

继续阅读 »

Hello MUI在“模板”分类中增加了“列表到详情最佳实践”,先看效果:

列表到详情最佳实践

从如上gif图中,可看出本示例的主要特点:点击列表瞬间打开详情页,并且详情页已渲染完毕,效果堪比原生App!

本模板设计目标:演示在窗口动画期间完成页面渲染

下面简单介绍一下实现思路,开发者可以套用这个模板,修改服务端地址及对应业务参数,即可实现同样流畅平滑的窗口切换效果。

实现思路:

预加载详情页

在列表页中预加载详情页,列表页中点击某新闻时,通过自定义事件通知详情页加载对应新闻详情,这样可以避免每次打开新闻详情时重新创建webview的资源消耗。

mui.plusReady(function() {  
    //预加载详情页  
    webview_detail = mui.preload({  
        url: 'detail.html',  
        id: 'vue_demo_detail',  
        styles: {  
            "render": "always",//一直渲染  
            "popGesture": "hide",  
            "titleNView": titleNView//使用原生渐变导航  
        }  
    });  
});

复用前页数据

详情页的内容需要通过ajax从服务端动态获取,获取之后再渲染,这里需要耗费一定的时间;如果网络不好,用户就会看到白屏或空页面,体验不好;
实际上,详情页部分内容在列表页已经加载过,可以直接从列表页传递过来(自定义事件耗时<10毫秒),而无需等待网络响应(ajax耗时 > 50毫秒)。因此,在列表页点击事件中,将列表页已加载的、详情页也需要的信息通过自定义事件传递给详情页,详情页将这些数据立即渲染,然后再通过ajax动态获取其余部分的数据。

1、列表页点击事件中传递已加载数据

//触发子窗口变更新闻详情  
mui.fire(webview_detail, 'get_detail', {  
    guid: guid,  
    title:title,  
    author:author,  
    time:time,  
    cover:cover  
});

2、详情页获取前页数据后,立即渲染,再通过ajx请求其余数据

//监听自定义事件,获取新闻详情  
document.addEventListener('get_detail', function(event) {  
    var guid = event.detail.guid;  
    if(!guid) {  
        return;  
    }  
    //前页传入的数据,直接渲染,无需等待ajax请求详情后  
    vm.cover = event.detail.cover;  
    vm.title = event.detail.title;  
    vm.author = event.detail.author;  
    vm.time = event.detail.time;  
    //向服务端请求文章详情内容  
    mui.ajax('your-server-url' + guid, {  
        type:'GET',  
        dataType: 'json', //服务器返回json格式数据  
        timeout: 15000, //15秒超时  
        success: function(rsp) {  
            vm.content = rsp.content;  
        },  
        error: function(xhr, type, errorThrown) {  
            mui.toast('获取文章内容失败');  
            //TODO 此处可以向服务端告警  
        }  
    });  
});

详情页返回时重置页面数据

为了避免打开下一个新闻详情时,闪一下上一个新闻详情,模板在详情页返回时,会清空详情页数据;因为本模板使用了vue框架,实际上执行的就是重置vue数据。

实现较为简单,重写mui.back,代码示例如下:

//重写返回逻辑,返回时隐藏详情页webview  
mui.back = function() {  
    plus.webview.currentWebview().hide("auto", 300);  
}  
//窗口隐藏时,重置页面数据  
mui.plusReady(function () {  
    var self = plus.webview.currentWebview();  
    self.addEventListener("hide",function (e) {  
        window.scrollTo(0, 0);//重置滚动条位置  
        vm.resetData();//重置页面数据  
    },false);  
})

其中,vm.resetData()为清空vue数据的方法。

致谢,感谢 @redonion42@163.com 建议,通过hide事件同时处理back按键、侧滑返回的重置需求。

提高网络响应

核心实现就如上两点,开发者按照这种模板就可以做出同样流畅的App。如果发现响应缓慢,注意检查两点:

  • 减少网络传输量,让服务端仅返回前端需要的字段
  • 利用缓存等技术优化服务端响应,保证ajax请求可以在100毫秒之内获得响应

关联功能点

按照如上思路实现的“列表到详情最佳实践”,还牵扯到一些关联知识点:

1、集成vue
本示例的列表页、详情页均使用了vue框架实现数据绑定,涉及到vue的列表渲染、数据重置知识点,内容较为简单,源码完全开源,本文不再详述。

2、下拉刷新、上拉加载
列表页集成了下拉刷新、上拉加载,代码示例如下:

mui.init({  
    pullRefresh: {  
        container: '#list',  
        down: {  
            style: 'circle',  
            offset: '0px',  
            auto: true,  
            callback: pulldownRefresh  
        },  
        up: {  
            contentrefresh: '正在加载...',  
            callback: pullupRefresh  
        }  
    }  
});

相关教程参考:

3、透明渐变导航
详情页使用了原生版本的透明渐变导航,参考教程

在点击不同新闻详情页时,需要改变原生导航条上的标题内容,通过重新设置webview的style属性即可,示例如下:

    //更改详情页原生导航条信息  
    titleNView.titleText = title;  
    webview_detail.setStyle({  
        "titleNView": titleNView  
    });

Hello MUI中体验

最新版的Hello MUI已集成了"列表到详情最佳实践",在HBuilder 8.8.0+ 版本中即可体验,体验路径:Hello MUI首页--> 列表到详情最佳实践

收起阅读 »

独家系统全套mui,h5+教程,500节课程,文档,资料,20套app源码等

HTML CSS H5 JS Castapp.js,MUI,H5+,PHP mysql,React-Native,Ecmascript6,React.js mui-UI实战 mui,h5+ APP开发实战功能 app开发{仿支付宝,仿微信,仿e袋洗,仿驾考宝典,仿微店,仿教室帮,仿饿了么,仿糗事百科,仿猫眼电影,仿天猫,仿今日头条,东翌同城约,东翌课堂,全套实战开发,让大家快速学习APP开发全体课程只需要499啦 想学习的点击链接咨询 群239503027直播视频课程

继续阅读 »

HTML CSS H5 JS Castapp.js,MUI,H5+,PHP mysql,React-Native,Ecmascript6,React.js mui-UI实战 mui,h5+ APP开发实战功能 app开发{仿支付宝,仿微信,仿e袋洗,仿驾考宝典,仿微店,仿教室帮,仿饿了么,仿糗事百科,仿猫眼电影,仿天猫,仿今日头条,东翌同城约,东翌课堂,全套实战开发,让大家快速学习APP开发全体课程只需要499啦 想学习的点击链接咨询 群239503027直播视频课程

收起阅读 »

关于IMEI设备标记

IMEI

Android

Android的imei在os层面有api,在plus.device.imei里有封装。
但注意双卡手机有2个imei,会都取出来。
同时注意目前很多Android手机获取imei需要用户授权,当用户不授权时,plus api会自动给出一个随机数,类似于web中的uv的机制。

iOS

iOS没有在os层面提供获取imei的api,plus.device提供了uuid。

继续阅读 »

Android

Android的imei在os层面有api,在plus.device.imei里有封装。
但注意双卡手机有2个imei,会都取出来。
同时注意目前很多Android手机获取imei需要用户授权,当用户不授权时,plus api会自动给出一个随机数,类似于web中的uv的机制。

iOS

iOS没有在os层面提供获取imei的api,plus.device提供了uuid。

收起阅读 »

独家系统全套mui,h5+教程,500节课程,文档,资料,20套app源码等

HTML CSS H5 JS Castapp.js,MUI,H5+,PHP mysql,React-Native,Ecmascript6,React.js mui-UI实战 mui,h5+ APP开发实战功能 app开发{仿支付宝,仿微信,仿e袋洗,仿驾考宝典,仿微店,仿教室帮,仿饿了么,仿糗事百科,仿猫眼电影,仿天猫,仿今日头条,东翌同城约,东翌课堂,全套实战开发,让大家快速学习APP开发全体课程只需要499啦 想学习的点击链接咨询 群239503027上午十点直播课程

继续阅读 »

HTML CSS H5 JS Castapp.js,MUI,H5+,PHP mysql,React-Native,Ecmascript6,React.js mui-UI实战 mui,h5+ APP开发实战功能 app开发{仿支付宝,仿微信,仿e袋洗,仿驾考宝典,仿微店,仿教室帮,仿饿了么,仿糗事百科,仿猫眼电影,仿天猫,仿今日头条,东翌同城约,东翌课堂,全套实战开发,让大家快速学习APP开发全体课程只需要499啦 想学习的点击链接咨询 群239503027上午十点直播课程

收起阅读 »

关于图片分享(IOS与安卓之间的区别)

Share
   查阅  **http://www.html5plus.org/doc/zh_cn/share.html#plus.share.ShareMessage**  

发现其中

pictures: (Array[ String ] 类型 )分享消息的图片
分享消息中包含的图片路径,仅支持本地路径。 若分享平台仅支持提交一张图片,传入多张图片则仅提交第一张图片。 如果不能同时支持其它内容信息,优先级顺序为:pictures>content。
所提及的是图片路径应该是绝对路径,但经测试,在安卓上是正确的,但在IOS上却是报

分享到"微信"失败: -100 - [Share微信:-95]未知错误,http://ask.dcloud.net.cn/article/287

查阅文档是图片路径错误的问题,修改无果后便做出如下修改:

if (mui.os.android) {  
shareMsg.pictures[0] = plus.io.convertLocalFileSystemURL("_www/img1.jpg");  
}else if(mui.os.ios){  
shareMsg.pictures[0] = "_www/img1.jpg";  
}

运行测试成功。
在这里有个疑问,如果事实真是这样的,文档是否写错的,还是我这里出现什么问题?
不过有遇到这类问题的朋友,也可以照我以上写法。

继续阅读 »
   查阅  **http://www.html5plus.org/doc/zh_cn/share.html#plus.share.ShareMessage**  

发现其中

pictures: (Array[ String ] 类型 )分享消息的图片
分享消息中包含的图片路径,仅支持本地路径。 若分享平台仅支持提交一张图片,传入多张图片则仅提交第一张图片。 如果不能同时支持其它内容信息,优先级顺序为:pictures>content。
所提及的是图片路径应该是绝对路径,但经测试,在安卓上是正确的,但在IOS上却是报

分享到"微信"失败: -100 - [Share微信:-95]未知错误,http://ask.dcloud.net.cn/article/287

查阅文档是图片路径错误的问题,修改无果后便做出如下修改:

if (mui.os.android) {  
shareMsg.pictures[0] = plus.io.convertLocalFileSystemURL("_www/img1.jpg");  
}else if(mui.os.ios){  
shareMsg.pictures[0] = "_www/img1.jpg";  
}

运行测试成功。
在这里有个疑问,如果事实真是这样的,文档是否写错的,还是我这里出现什么问题?
不过有遇到这类问题的朋友,也可以照我以上写法。

收起阅读 »

ios持续定位/后台定位问题

后台定位 Geolocation

我分享一下我解决IOS和Android定位后台执行定时上传方法。

文章最下面有zip源码下载文件

文章最下面有zip源码下载文件

文章最下面有zip源码下载文件

图1是声明定位的对象 图2是开启 location.js文件中全部封装好了你自己需要的方法 对外只需要暴露的checkLocation closeLocation 2个方法

定位对象必须要是唯一的 如果不唯一就会开启多个定位方法 影响使用

android的如果全杀死是没办法,在后台的情况是没问题的.
我的做法是用watchPosition将获取的到的坐标放在一个数组中,然后调用locationHandle方法每隔多少时间上次到服务器。
这个不会出现上传一段时间之后关掉的情况。
1.在这之前你需要在manifest.json文件中配置启用后台模块"UIBackgroundModes": ["location"]
2.如果定位失败会返回一个5e-324可能是你手机的定位权限没有开启。

var Location = function () {  
  this.reportLocation = null;  
  this.watchLocation = null;  
  this.locationPool = [];  
}  

/**  
 * 判断是否开启定位  
 * @param {Object} isTask 1是开启循环上传定位0是10分钟上传一次本地定位  
 */  
Location.prototype.checkLocation = function (isTask) {  
var _this = this;  
  _this.openLocation({  
                onSuccess: function () {  
                  //开启定位成功首页回调方法  
                  var sell_main = plus.webview.getWebviewById('sell_main');  
                  mui.fire(sell_main, 'locationSuccess');  
                },  
                onFailed: function () {  
                 //开启定位失败首页回调方法  
                  var sell_main = plus.webview.getWebviewById('sell_main');  
                  mui.fire(sell_main, 'locationFailure');  
                }  
              });  
}  

/**  
 * 开启定位  
 * @param {Object} options  
 */  
Location.prototype.openLocation = function (options) {  
  options = options || {};  
  var _this = this;  
  var isTask = this.isTask;  
  var driverForOrderObject = null;  
  var driverForTaskObject = null;  
  var userInfo = DbUtils.getStorage('userInfo', 1);  

  var locationParams = {  
    enableHighAccuracy: true,  
    geocode: false,  
    coordsType: "bd09ll",  
    provider: 'baidu'  
  };  

}  

/**  
 * 默认第一次开启定位的是否先获取 之后用来过滤偏差很大的点  
 * @param {Object} options  
 */  
Location.prototype.locationReady = function (options) {  
  options = options || {};  
  var isTask = this.isTask;  
  var _this = this;  

  var locationParams = {  
    enableHighAccuracy: true,  
    geocode: false,  
    maximumAge: ApiConfig.UPLOADLOCATIONWORKTIME,  
    coordsType: "bd09ll",  
    provider: 'baidu'  
  };  
  _this.getCurrentPosition()  
}  

/**  
 * 非工作状态定位,十五分钟上传一次定位  
 * @param  options  
 */  
Location.prototype.accurateLocation = function (options) {  
  options = options || {};  
  var _this = this;  
  plus.geolocation.getCurrentPosition(function (position) {  
    _this.locationPool.push(position);  
    ApiConfig.staticIsDebug('getCurrentPosition', JSON.stringify(position));  
    _this.reportLocationHandle({  
      onSuccess: function (success) {  
        options.onSuccess && options.onSuccess(success);  
      },  
      onFailed: function (failure) {  
        options.onFailed && options.onFailed(failure);  
      }  
    });  
  }, function () {  
    options.onFailed && options.onFailed();  
  }, options.locationParams);  
}  

/**  
 * 只要定位改变就会获取并过滤错误的点和偏差很多的点   
 *坐标为 -5e32是定位权限没开启的情况  
 * @param  options  
 */  
Location.prototype.getCurrentPosition = function (options) {  
  options = options || {};  
  var _this = this;  
  var phpTimeInt = utilsJs.phpTimeInt();  
  var isWork = options.isWork;  
  var locationParams = options.locationParams;  
  //初始化Location参数  
  if (_this.reportLocation) {  
    window.clearInterval(_this.reportLocation);  
    _this.reportLocation = null;  
  }  
  if (_this.watchLocation) {  
    plus.geolocation.clearWatch(_this.watchLocation);  
    _this.reportLocation = null;  
  }  

  //是否是工作状态 工作状态用watchPosition 非工作状态用getCurrentPosition  
  if (isWork) {  
    _this.watchLocation = plus.geolocation.watchPosition(function (position) {  
        //console.log(JSON.stringify(position));  
        var difference = (position.timestamp / 1000) - phpTimeInt;  
        var coords = position.coords;  
        if (coords.latitude > 0.00000001 && coords.longitude > 0.00000001 && difference > 1) {  
          phpTimeInt = (position.timestamp / 1000);  
          _this.locationPool.push(position);  
          _this.locationHandle({  
            onSuccess: function (success) {  
              options.onSuccess && options.onSuccess(success);  
            },  
            onFailed: function (failure) {  
              options.onFailed && options.onFailed(failure);  
            }  
          });  
        }  
      },  
      function () {  
        options.onFailed && options.onFailed();  
      }, locationParams);  
  } else {  
    _this.reportLocation = window.setInterval(function () {  
      _this.accurateLocation(options);  
    }, ApiConfig.UPLOADLOCATIONTIME);  
  }  
}  
//开启定时器  
Location.prototype.locationHandle = function (options) {  
  options = options || {};  
  var _this = this;  
  if (!_this.reportLocation) {  
    _this.reportLocation = window.setInterval(function () {  
      //plus.push.createMessage('locationPool:' + _this.locationPool.length, '', '');  
      _this.reportLocationHandle({  
        onSuccess: function (success) {  
          options.onSuccess && options.onSuccess(success);  
        },  
        onFailed: function (failure) {  
          options.onFailed && options.onFailed(failure);  
        }  
      });  
    }, ApiConfig.UPLOADLOCATIONWORKTIME);  
  }  
}  

/**  
 * 关闭定位  
 *  
 */  
Location.prototype.closeLocation = function () {  
  var _this = this;  
  var isTask = this.isTask;  
  if (_this.reportLocation) {  
    window.clearInterval(_this.reportLocation);  
    _this.reportLocation = null;  

  }  
  if (_this.watchLocation) {  
    plus.geolocation.clearWatch(_this.watchLocation);  
    _this.watchLocation = null;  
  }  
  this.locationPool = [];  
  if (isTask) {  
    DbUtils.removeItem('driverStatusForTask');  
  } else {  
    DbUtils.removeItem('driverStatusObject');  
  }  
}  

/**  
 * 上传定位接口  
 * @param options  
 */  
Location.prototype.reportLocationHandle = function (options) {  

}
继续阅读 »

我分享一下我解决IOS和Android定位后台执行定时上传方法。

文章最下面有zip源码下载文件

文章最下面有zip源码下载文件

文章最下面有zip源码下载文件

图1是声明定位的对象 图2是开启 location.js文件中全部封装好了你自己需要的方法 对外只需要暴露的checkLocation closeLocation 2个方法

定位对象必须要是唯一的 如果不唯一就会开启多个定位方法 影响使用

android的如果全杀死是没办法,在后台的情况是没问题的.
我的做法是用watchPosition将获取的到的坐标放在一个数组中,然后调用locationHandle方法每隔多少时间上次到服务器。
这个不会出现上传一段时间之后关掉的情况。
1.在这之前你需要在manifest.json文件中配置启用后台模块"UIBackgroundModes": ["location"]
2.如果定位失败会返回一个5e-324可能是你手机的定位权限没有开启。

var Location = function () {  
  this.reportLocation = null;  
  this.watchLocation = null;  
  this.locationPool = [];  
}  

/**  
 * 判断是否开启定位  
 * @param {Object} isTask 1是开启循环上传定位0是10分钟上传一次本地定位  
 */  
Location.prototype.checkLocation = function (isTask) {  
var _this = this;  
  _this.openLocation({  
                onSuccess: function () {  
                  //开启定位成功首页回调方法  
                  var sell_main = plus.webview.getWebviewById('sell_main');  
                  mui.fire(sell_main, 'locationSuccess');  
                },  
                onFailed: function () {  
                 //开启定位失败首页回调方法  
                  var sell_main = plus.webview.getWebviewById('sell_main');  
                  mui.fire(sell_main, 'locationFailure');  
                }  
              });  
}  

/**  
 * 开启定位  
 * @param {Object} options  
 */  
Location.prototype.openLocation = function (options) {  
  options = options || {};  
  var _this = this;  
  var isTask = this.isTask;  
  var driverForOrderObject = null;  
  var driverForTaskObject = null;  
  var userInfo = DbUtils.getStorage('userInfo', 1);  

  var locationParams = {  
    enableHighAccuracy: true,  
    geocode: false,  
    coordsType: "bd09ll",  
    provider: 'baidu'  
  };  

}  

/**  
 * 默认第一次开启定位的是否先获取 之后用来过滤偏差很大的点  
 * @param {Object} options  
 */  
Location.prototype.locationReady = function (options) {  
  options = options || {};  
  var isTask = this.isTask;  
  var _this = this;  

  var locationParams = {  
    enableHighAccuracy: true,  
    geocode: false,  
    maximumAge: ApiConfig.UPLOADLOCATIONWORKTIME,  
    coordsType: "bd09ll",  
    provider: 'baidu'  
  };  
  _this.getCurrentPosition()  
}  

/**  
 * 非工作状态定位,十五分钟上传一次定位  
 * @param  options  
 */  
Location.prototype.accurateLocation = function (options) {  
  options = options || {};  
  var _this = this;  
  plus.geolocation.getCurrentPosition(function (position) {  
    _this.locationPool.push(position);  
    ApiConfig.staticIsDebug('getCurrentPosition', JSON.stringify(position));  
    _this.reportLocationHandle({  
      onSuccess: function (success) {  
        options.onSuccess && options.onSuccess(success);  
      },  
      onFailed: function (failure) {  
        options.onFailed && options.onFailed(failure);  
      }  
    });  
  }, function () {  
    options.onFailed && options.onFailed();  
  }, options.locationParams);  
}  

/**  
 * 只要定位改变就会获取并过滤错误的点和偏差很多的点   
 *坐标为 -5e32是定位权限没开启的情况  
 * @param  options  
 */  
Location.prototype.getCurrentPosition = function (options) {  
  options = options || {};  
  var _this = this;  
  var phpTimeInt = utilsJs.phpTimeInt();  
  var isWork = options.isWork;  
  var locationParams = options.locationParams;  
  //初始化Location参数  
  if (_this.reportLocation) {  
    window.clearInterval(_this.reportLocation);  
    _this.reportLocation = null;  
  }  
  if (_this.watchLocation) {  
    plus.geolocation.clearWatch(_this.watchLocation);  
    _this.reportLocation = null;  
  }  

  //是否是工作状态 工作状态用watchPosition 非工作状态用getCurrentPosition  
  if (isWork) {  
    _this.watchLocation = plus.geolocation.watchPosition(function (position) {  
        //console.log(JSON.stringify(position));  
        var difference = (position.timestamp / 1000) - phpTimeInt;  
        var coords = position.coords;  
        if (coords.latitude > 0.00000001 && coords.longitude > 0.00000001 && difference > 1) {  
          phpTimeInt = (position.timestamp / 1000);  
          _this.locationPool.push(position);  
          _this.locationHandle({  
            onSuccess: function (success) {  
              options.onSuccess && options.onSuccess(success);  
            },  
            onFailed: function (failure) {  
              options.onFailed && options.onFailed(failure);  
            }  
          });  
        }  
      },  
      function () {  
        options.onFailed && options.onFailed();  
      }, locationParams);  
  } else {  
    _this.reportLocation = window.setInterval(function () {  
      _this.accurateLocation(options);  
    }, ApiConfig.UPLOADLOCATIONTIME);  
  }  
}  
//开启定时器  
Location.prototype.locationHandle = function (options) {  
  options = options || {};  
  var _this = this;  
  if (!_this.reportLocation) {  
    _this.reportLocation = window.setInterval(function () {  
      //plus.push.createMessage('locationPool:' + _this.locationPool.length, '', '');  
      _this.reportLocationHandle({  
        onSuccess: function (success) {  
          options.onSuccess && options.onSuccess(success);  
        },  
        onFailed: function (failure) {  
          options.onFailed && options.onFailed(failure);  
        }  
      });  
    }, ApiConfig.UPLOADLOCATIONWORKTIME);  
  }  
}  

/**  
 * 关闭定位  
 *  
 */  
Location.prototype.closeLocation = function () {  
  var _this = this;  
  var isTask = this.isTask;  
  if (_this.reportLocation) {  
    window.clearInterval(_this.reportLocation);  
    _this.reportLocation = null;  

  }  
  if (_this.watchLocation) {  
    plus.geolocation.clearWatch(_this.watchLocation);  
    _this.watchLocation = null;  
  }  
  this.locationPool = [];  
  if (isTask) {  
    DbUtils.removeItem('driverStatusForTask');  
  } else {  
    DbUtils.removeItem('driverStatusObject');  
  }  
}  

/**  
 * 上传定位接口  
 * @param options  
 */  
Location.prototype.reportLocationHandle = function (options) {  

}
收起阅读 »

承接App开发,Vue + Dcloud 目前架构最成熟的跨平台解决方案。

外包

默客 (http://www.mokekeji.com) 原横行科技,专业跨平台App开发。

我们从大约四年前开始混合式App(hybrid app) 的相关开发,从早期的 cordova (原phonegap) 到后来的国内的DcloudApiCloud ,再到现在的 React Native 以及 Weex,我们切实的看到了混合式App从一开始的饱受诟病到后来的遍地流行,甚至现在我们几乎可以断言混合式App将会成为主流App开发方式,这里不仅是一篇广告,同时会说明我们最终选择Vue + Dcloud的原因。

cordovaDcloud , Apicloud 三者都是基于webview 进行封装的,具体的框架对比有很多文章说明,比如这里比较流行的一篇文章http://blog.csdn.net/guzhenping/article/details/50496883

但是所谓文章一旦开始分析优缺点,往往都是各有优劣,其实只有真正开发过,使用过,吃过亏才知道哪个是不能用的。

Apicloud 是不能用的。
必须承认apicloud的营销和用户后台做得都不错,也正是因为这些表面功夫,让我们以花费了接近半年时间,并重构了一个项目的成本,得出了这个结论。
apicloud的开发环境和运行环境有很大不同,这给开发带来了巨大的阻碍,debug也非常艰难。
apicloud的模块数量不少,但质量十分低下,即使最基础的ajax模块都有一堆问题。
apicloud许多模块都有原生的UI,这部分UI质量的定制和使用很难达到商业水准。

总而言之,apicloud并不适合开发人员使用,也不适合商业产品的开发。

开发上来说,cordova 与 Dcloud 各有千秋。
cordova 有成熟的社区,海量的扩展插件,以及许多的成熟解决方案,Dcloud有更好的性能,更好的开发工具,更高的投入产出比。
但我们选择 Dcloud,与我们没有选择React Native的原因一样,一个成熟的商业公司在选择技术框架时,更低的开发门槛实在过于重要了,目前国内的平均前端水准仍然偏低,看懂cordova的开发文档就已经很困难了,插件市场也很难用上。

我们将Dcloud的html5 Plus api 以及 微信js sdk都进行了封装,有一定基础的开发人员可以在很短的时间内掌握,加上Dcloud对于常规需求都有比较接地气的解决方案,开发体验就要好的多。

Mvvm框架是大型应用的必选项
Mvvm框架代表:Vue,react
目前大多数人仍是使用原始的Html页面进行应用开发,包括Dcloud的展示案例也是如此。
这种开发方式在开发大型应用时越来越捉襟见肘,比如如何跨页面管理全局状态就是个不小的问题。
原始的静态页面开发虽然降低了开发成本,但其实大幅增加了维护成本,当前的app对与快速迭代有越来越高的要求,静态页面开发动辄上百个页面,改一个UI颜色,都可能需要半天的时间。
Mvvm框架可以大幅提高代码质量,所有ui可以封装为组件,数据驱动视图,对于复杂的交互来说,结构也更为清晰。

Weex和React Native终成主流
与Dcloud这类框架不同,这两个框架在原生平台上运行时,会将页面编译为原生控件,可以说,这从根本上解决了混合式app的性能问题,我们目前在重点关注Weex,这个框架目前仍未达到商业使用的要求,我们预计在明年我司内部会逐渐用其替代Dcloud作为主开发框架。React Native的问题仍然在开发门槛上,我们只会在少数项目上使用。

我们致力于开发高质量的跨平台应用,业务联系请参考官网。
http://www.mokekeji.com

继续阅读 »

默客 (http://www.mokekeji.com) 原横行科技,专业跨平台App开发。

我们从大约四年前开始混合式App(hybrid app) 的相关开发,从早期的 cordova (原phonegap) 到后来的国内的DcloudApiCloud ,再到现在的 React Native 以及 Weex,我们切实的看到了混合式App从一开始的饱受诟病到后来的遍地流行,甚至现在我们几乎可以断言混合式App将会成为主流App开发方式,这里不仅是一篇广告,同时会说明我们最终选择Vue + Dcloud的原因。

cordovaDcloud , Apicloud 三者都是基于webview 进行封装的,具体的框架对比有很多文章说明,比如这里比较流行的一篇文章http://blog.csdn.net/guzhenping/article/details/50496883

但是所谓文章一旦开始分析优缺点,往往都是各有优劣,其实只有真正开发过,使用过,吃过亏才知道哪个是不能用的。

Apicloud 是不能用的。
必须承认apicloud的营销和用户后台做得都不错,也正是因为这些表面功夫,让我们以花费了接近半年时间,并重构了一个项目的成本,得出了这个结论。
apicloud的开发环境和运行环境有很大不同,这给开发带来了巨大的阻碍,debug也非常艰难。
apicloud的模块数量不少,但质量十分低下,即使最基础的ajax模块都有一堆问题。
apicloud许多模块都有原生的UI,这部分UI质量的定制和使用很难达到商业水准。

总而言之,apicloud并不适合开发人员使用,也不适合商业产品的开发。

开发上来说,cordova 与 Dcloud 各有千秋。
cordova 有成熟的社区,海量的扩展插件,以及许多的成熟解决方案,Dcloud有更好的性能,更好的开发工具,更高的投入产出比。
但我们选择 Dcloud,与我们没有选择React Native的原因一样,一个成熟的商业公司在选择技术框架时,更低的开发门槛实在过于重要了,目前国内的平均前端水准仍然偏低,看懂cordova的开发文档就已经很困难了,插件市场也很难用上。

我们将Dcloud的html5 Plus api 以及 微信js sdk都进行了封装,有一定基础的开发人员可以在很短的时间内掌握,加上Dcloud对于常规需求都有比较接地气的解决方案,开发体验就要好的多。

Mvvm框架是大型应用的必选项
Mvvm框架代表:Vue,react
目前大多数人仍是使用原始的Html页面进行应用开发,包括Dcloud的展示案例也是如此。
这种开发方式在开发大型应用时越来越捉襟见肘,比如如何跨页面管理全局状态就是个不小的问题。
原始的静态页面开发虽然降低了开发成本,但其实大幅增加了维护成本,当前的app对与快速迭代有越来越高的要求,静态页面开发动辄上百个页面,改一个UI颜色,都可能需要半天的时间。
Mvvm框架可以大幅提高代码质量,所有ui可以封装为组件,数据驱动视图,对于复杂的交互来说,结构也更为清晰。

Weex和React Native终成主流
与Dcloud这类框架不同,这两个框架在原生平台上运行时,会将页面编译为原生控件,可以说,这从根本上解决了混合式app的性能问题,我们目前在重点关注Weex,这个框架目前仍未达到商业使用的要求,我们预计在明年我司内部会逐渐用其替代Dcloud作为主开发框架。React Native的问题仍然在开发门槛上,我们只会在少数项目上使用。

我们致力于开发高质量的跨平台应用,业务联系请参考官网。
http://www.mokekeji.com

收起阅读 »

关于Appstore版Hello H5+支付示例只有iap的说明

Payment

Hello H5+的支付示例是捐赠,按照Appstore的规定属于非实物交易,必须且只能使用Apple的应用内支付iap,并且必须给Apple分成30%。
应Apple要求,新版Hello H5+的iOS版支付示例去掉了微信支付和支付宝支付。但相关api仍然是可以使用的,只能你是实物交易,就可以使用微信、支付宝。当然如果你不打算上Appstore,那想怎么样都行。

如果开发者在Appstore中发行,使用实物交易,比如电商、外卖、电影票。。。不受此影响。如果是非实物交易,比如销售App、游戏道具、打赏捐赠、电子书、音视频会员、知识付费,都必须使用iap。

如果开发者在iOS流应用中发行,没有此限制。即使是非实物交易,也可以使用支付宝支付,对于微信支付,可以使用微信H5支付。

继续阅读 »

Hello H5+的支付示例是捐赠,按照Appstore的规定属于非实物交易,必须且只能使用Apple的应用内支付iap,并且必须给Apple分成30%。
应Apple要求,新版Hello H5+的iOS版支付示例去掉了微信支付和支付宝支付。但相关api仍然是可以使用的,只能你是实物交易,就可以使用微信、支付宝。当然如果你不打算上Appstore,那想怎么样都行。

如果开发者在Appstore中发行,使用实物交易,比如电商、外卖、电影票。。。不受此影响。如果是非实物交易,比如销售App、游戏道具、打赏捐赠、电子书、音视频会员、知识付费,都必须使用iap。

如果开发者在iOS流应用中发行,没有此限制。即使是非实物交易,也可以使用支付宝支付,对于微信支付,可以使用微信H5支付。

收起阅读 »