HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

针对plus.runtime.install在安卓9.0+上无法执行的解决方案

install 安卓9.0

先确保你的IDE使用的是HBuilderX, 老HBuilder用户请升级HBuilderX

云打包配置

云打包时配置manifest.json将targetSdkVersion改为26或更高 最高建议28。
5+应用:
http://ask.dcloud.net.cn/article/94


uniapp:
https://uniapp.dcloud.io/collocation/manifest

如果提交云端打包后调用plus.runtime.install无法安装apk文件,请添加以下权限

<uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/>  
<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>

如何添加权限?可参考

TIPS

云打包配置修改完毕后。请重新提交云端打包。生成你的APK,该APK才有调用plus.runtime.install安装APK的能力。

离线打包配置

  1. 将build.gradle中的targetSdkVersion调到26或者更高。

  2. 在Androidmanifest.xml添加provider节点,将里面的io.dcloud.HBuilder改成自己应用的包名。

        <provider  
            android:name="io.dcloud.common.util.DCloud_FileProvider"  
            android:authorities="XXXX.XXX.XX(当前的应用包名).dc.fileprovider"  
            android:exported="false"  
            android:grantUriPermissions="true">  
            <meta-data  
                android:name="android.support.FILE_PROVIDER_PATHS"  
                android:resource="@xml/dcloud_file_provider" />  
        </provider>  
  3. 在Androidmanifest.xml中添加权限。
    注:最新版SDK已经将权限加入基础库里面使用时请下载最新版SDK

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>  

配置完权限请重新编译生成APK。该APK才有调用plus.runtime.install安装APK的能力。

继续阅读 »

先确保你的IDE使用的是HBuilderX, 老HBuilder用户请升级HBuilderX

云打包配置

云打包时配置manifest.json将targetSdkVersion改为26或更高 最高建议28。
5+应用:
http://ask.dcloud.net.cn/article/94


uniapp:
https://uniapp.dcloud.io/collocation/manifest

如果提交云端打包后调用plus.runtime.install无法安装apk文件,请添加以下权限

<uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/>  
<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>

如何添加权限?可参考

TIPS

云打包配置修改完毕后。请重新提交云端打包。生成你的APK,该APK才有调用plus.runtime.install安装APK的能力。

离线打包配置

  1. 将build.gradle中的targetSdkVersion调到26或者更高。

  2. 在Androidmanifest.xml添加provider节点,将里面的io.dcloud.HBuilder改成自己应用的包名。

        <provider  
            android:name="io.dcloud.common.util.DCloud_FileProvider"  
            android:authorities="XXXX.XXX.XX(当前的应用包名).dc.fileprovider"  
            android:exported="false"  
            android:grantUriPermissions="true">  
            <meta-data  
                android:name="android.support.FILE_PROVIDER_PATHS"  
                android:resource="@xml/dcloud_file_provider" />  
        </provider>  
  3. 在Androidmanifest.xml中添加权限。
    注:最新版SDK已经将权限加入基础库里面使用时请下载最新版SDK

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>  

配置完权限请重新编译生成APK。该APK才有调用plus.runtime.install安装APK的能力。

收起阅读 »

uniapp视频教程

视频教程

uniapp视频教程
http://fainbory.com/E7v

uniapp视频教程
http://fainbory.com/E7v

uni-app/mpvue 插件开发大赛启动,iPhone Xs Max等奖品等你来拿!

插件市场 uni_app

更新:大赛评奖结果揭晓,详见:https://ask.dcloud.net.cn/article/35939

基于vue,开发H5、小程序及App等多端应用,已经成为前端技术界的热门话题。

但vue周边生态很多组件都因为操作dom、window而无法跨多端。

为进一步活跃vue多端开发生态,为开发者提供更多方便的轮子,作为vue开发多端框架的2大主力,uni-app与mpvue团队,联合举办插件开发大赛。

这些插件中涉及小程序的均可用于uni-app和mpvue的开发者。涉及H5和App多端使用的,仅限于uni-app(mpvue不支持h5和App)

大赛活动时间及评奖方式

  • 即日起至2019年4月30日,参赛插件提交发布。超过4月30日的插件可以提交但不再评奖。
  • 2019年5月15日起,评委开始根据插件的下载量、插件市场评分、github star(如有)、评委主观评价等综合权重打分,评选获奖者。
  • 2019年5月20日,公布获奖名单并发放奖品

奖品设置

一等奖:
iphone Xs Max 3名

二等奖:
Samsung 32寸4k显示器 8名

三等奖:
Kindle Paperwhite 16名

贡献奖:
未获得以上奖项,仍有机会评选贡献奖,奖品为uni-app纪念T恤,50名。

其他:
获奖作者将进入DCloud的vip开发者群,享受优先的技术支持和bug受理。
获奖作者将得到宣传报道,有助于为简历或接外包资质添彩。

参赛方式

  1. 登陆插件市场,https://ext.dcloud.net.cn/
  2. 点击发布插件,插件开发指南参考:https://ask.dcloud.net.cn/article/35408
  3. 填写插件描述信息并提交发布
  4. 插件有多种类型,包括组件、js sdk、项目/页面模板、原生插件,均可参赛。但不接受只能用于h5端的插件。

其他注意事项

  1. 越早提交插件,下载量越大,有利于被评选获奖
  2. 插件市场可以同时提交npm地址,但必须有zip包。由于npm下载量可以刷,无法作为评选依据,请理解
  3. 插件市场的下载和评分都有反作弊系统,欢迎向朋友正常推广你的插件,但不要刷数据,违规者取消参赛资格
  4. 插件市场提供了赞赏,并即将上线付费插件购买,插件作者可以有更多收益
  5. 一位作者提交多个插件,每个插件都独立参与评奖。允许一位作者领取多个奖品

如果你想了解广大开发者都需要什么插件,可以点击插件市场右上角的已发布需求

本活动解释权归DCloud uni-app团队mpvue团队

更新:感谢尤雨溪对大赛的宣传支持

继续阅读 »

更新:大赛评奖结果揭晓,详见:https://ask.dcloud.net.cn/article/35939

基于vue,开发H5、小程序及App等多端应用,已经成为前端技术界的热门话题。

但vue周边生态很多组件都因为操作dom、window而无法跨多端。

为进一步活跃vue多端开发生态,为开发者提供更多方便的轮子,作为vue开发多端框架的2大主力,uni-app与mpvue团队,联合举办插件开发大赛。

这些插件中涉及小程序的均可用于uni-app和mpvue的开发者。涉及H5和App多端使用的,仅限于uni-app(mpvue不支持h5和App)

大赛活动时间及评奖方式

  • 即日起至2019年4月30日,参赛插件提交发布。超过4月30日的插件可以提交但不再评奖。
  • 2019年5月15日起,评委开始根据插件的下载量、插件市场评分、github star(如有)、评委主观评价等综合权重打分,评选获奖者。
  • 2019年5月20日,公布获奖名单并发放奖品

奖品设置

一等奖:
iphone Xs Max 3名

二等奖:
Samsung 32寸4k显示器 8名

三等奖:
Kindle Paperwhite 16名

贡献奖:
未获得以上奖项,仍有机会评选贡献奖,奖品为uni-app纪念T恤,50名。

其他:
获奖作者将进入DCloud的vip开发者群,享受优先的技术支持和bug受理。
获奖作者将得到宣传报道,有助于为简历或接外包资质添彩。

参赛方式

  1. 登陆插件市场,https://ext.dcloud.net.cn/
  2. 点击发布插件,插件开发指南参考:https://ask.dcloud.net.cn/article/35408
  3. 填写插件描述信息并提交发布
  4. 插件有多种类型,包括组件、js sdk、项目/页面模板、原生插件,均可参赛。但不接受只能用于h5端的插件。

其他注意事项

  1. 越早提交插件,下载量越大,有利于被评选获奖
  2. 插件市场可以同时提交npm地址,但必须有zip包。由于npm下载量可以刷,无法作为评选依据,请理解
  3. 插件市场的下载和评分都有反作弊系统,欢迎向朋友正常推广你的插件,但不要刷数据,违规者取消参赛资格
  4. 插件市场提供了赞赏,并即将上线付费插件购买,插件作者可以有更多收益
  5. 一位作者提交多个插件,每个插件都独立参与评奖。允许一位作者领取多个奖品

如果你想了解广大开发者都需要什么插件,可以点击插件市场右上角的已发布需求

本活动解释权归DCloud uni-app团队mpvue团队

更新:感谢尤雨溪对大赛的宣传支持

收起阅读 »

uni-app 1.8发布,微信端性能翻倍,并增加若干 Vue 语法支持

微信小程序 性能 filter

背景

uni-app在初期借鉴了mpvue,实现了微信小程序端的快速兼容,感谢美团点评团队对于开源社区的贡献!

但不少开发者抱怨mpvue支持的vue语法少,某些场景性能有问题。

为了让uni-app的开发者更满意,uni-app团队经过数月研发,全新重写框架,大幅提升了微信端运行性能、支持了更多vue语法

新版特性1:性能翻倍

基于mpvue的老框架和新框架是两种编译模式,主要区别在于组件化开发的实现机制不同;

  • mpvue将用户编写的Vue组件,编译为WXML中的模板(template),变相实现组件化开发;我们称这种编译模式为template模板模式
  • uni-app新框架则将用户编写的Vue组件,编译为微信小程序自定义组件,实现了更高的性能;我们称这种编译模式为自定义组件模式

基于自定义组件的新框架完成后,我们构造了如下测试模型:

  • 构造一个列表界面,每个列表项为一个自定义组件
  • 上拉加载触发数据更新,每次从本地读取静态数据,屏蔽网络差异

然后分别使用template模板模式自定义组件模式,在同一台手机(vivo nex)上进行多次测试,然后求其平均值,获取如下结果:

组件数量 老框架(mpvue) 新框架
200 204ms 129ms
400 280ms 139ms
800 341ms 180ms
1000 653ms 196ms

上表时间毫秒是指,从给变量赋值,到界面更新渲染完毕之间的耗时。

从测试数据来看,自定义组件模式(新框架)在复杂页面下,性能有翻倍提升!特别是数据越多、组件越复杂的页面,性能提升越大!

新版特性2:更多Vue语法支持

新版支持了更多 Vue 语法,详细如下:

  • 支持过滤器 filter
  • 支持比较复杂的 JavaScript 渲染表达式
  • 支持在 template 内使用 methods 中的函数
  • 支持 v-html (同 rich-text 的解析)
  • 支持 v-slot 新语法
  • 支持解构插槽 Prop 设置默认值
  • 支持 slot 后备内容
  • 组件支持原生事件绑定,如:@tap.native

新版不支持的 vue 语法

  • class不支持绑定Obejct变量(使用字符串的形式绑定)
  • 不支持事件修饰符:prevent、passive(在App与小程序平台,使用stop修饰符,既可以阻止冒泡也能阻止默认行为)
  • 不支持render、inline-template、X-Templates、keep-alive、transition
  • 不支持使用 Vue.use 的方式注册全局组件(在main.js使用Vue.component的方式引入)

新旧版本兼容策略

为兼容历史项目,uni-app 现阶段同时支持老的template模板模式、和新的自定义组件模式两种模式,默认策略如下:

  • HBuilderX 1.8.0+ 新创建的项目,在微信端默认会启用新的框架;
  • 历史项目默认使用老框架。如需启动新框架请按下面配置开启。
  • 但注意1.7.3群测版默认使用了新框架,升级到1.8后,也需要手动配置开启新框架

开发者可在manifest.json的源码视图里配置, manifest.json -> mp-weixin -> usingComponents切换编译模式,如下:

// manifest.json  
{  
    // ...  
    /* 小程序特有相关 */  
    "mp-weixin": {  
        "usingComponents":true //是否启用`自定义组件模式`,为true表示新的`自定义组件模式`,否则启用老的`template模板模式`  
    }  
}  

Tips:

  • 为保证自定义组件兼容性,运行到微信开发者工具时,建议将微信基础库设置为最新版本。
  • 如果你使用了新增的vue语法,请注意只有h5和微信支持这些新语法,编译到其他平台时,要用条件编译处理。

新版开发注意事项

新框架基于微信小程序自定义组件实现,在进行自定义组件开发(页面开发不影响)时,需注意部分约束,详见:https://ask.dcloud.net.cn/article/35851

性能优化建议

  1. 模板中不建议直接使用 object
<!-- 低性能写法 -->  
<uni-title title="标题文字" note="描述信息" show-extra-icon="true" :extra-icon="{color: '#4cd964',size: '22',type: 'spinner'}"></uni-title>  
<!-- 高性能写法 -->  
<template>  
    <view>  
        <uni-title title="标题文字" note="描述信息" show-extra-icon="true" :extra-icon="extraIcon"></uni-title>  
    </view>  
</template>  
<script>  
export default {  
    data() {  
        return {  
            extraIcon:{color: '#4cd964',size: '22',type: 'spinner'}  
        }  
    }  
}  
</script>  
  1. 在模板中未使用的数据不建议定义在data 中,未使用的数据一律移除到 vm 外边定义
<!-- 低性能写法 -->  
<template>  
    <view>  
        {{name}}  
    </view>  
</template>  
<script>  
export default {  
    data() {  
        return {  
            name:'',  
            types:true  
        }  
    },  
    onLoad(){  
        if(this.types){  
            this.name = '张三';  
        } else {  
            this.name = '李四';  
        }  
    }  
}  
</script>
<!-- 高性能写法 -->  
<template>  
    <view>  
        {{name}}  
    </view>  
</template>  
<script>  
let types = true ;  
export default {  
    data() {  
        return {  
            name:''  
        }  
    },  
    onLoad(){  
        if(types){  
            this.name = '张三';  
        } else {  
            this.name = '李四';  
        }  
    }  
}  
</script>
  1. 为提升开发体验,新版本增加了部分 Vue 语法,其实这些语法在微信小程序中本身是不支持的;为支持这些语法,uni-app 会在编译、运行时分别做一些额外的工作,若开发者希望追求性能极致,则建议尽量少用或者不用新增语法。

后续

新框架会陆续把新编译器迁移到其他小程序端上。

升级注意

如果你的项目是cli创建的,记得编译器在你的项目下,不会随着HBuilderX升级而升级,你需要npm update手动升级编译器。

继续阅读 »

背景

uni-app在初期借鉴了mpvue,实现了微信小程序端的快速兼容,感谢美团点评团队对于开源社区的贡献!

但不少开发者抱怨mpvue支持的vue语法少,某些场景性能有问题。

为了让uni-app的开发者更满意,uni-app团队经过数月研发,全新重写框架,大幅提升了微信端运行性能、支持了更多vue语法

新版特性1:性能翻倍

基于mpvue的老框架和新框架是两种编译模式,主要区别在于组件化开发的实现机制不同;

  • mpvue将用户编写的Vue组件,编译为WXML中的模板(template),变相实现组件化开发;我们称这种编译模式为template模板模式
  • uni-app新框架则将用户编写的Vue组件,编译为微信小程序自定义组件,实现了更高的性能;我们称这种编译模式为自定义组件模式

基于自定义组件的新框架完成后,我们构造了如下测试模型:

  • 构造一个列表界面,每个列表项为一个自定义组件
  • 上拉加载触发数据更新,每次从本地读取静态数据,屏蔽网络差异

然后分别使用template模板模式自定义组件模式,在同一台手机(vivo nex)上进行多次测试,然后求其平均值,获取如下结果:

组件数量 老框架(mpvue) 新框架
200 204ms 129ms
400 280ms 139ms
800 341ms 180ms
1000 653ms 196ms

上表时间毫秒是指,从给变量赋值,到界面更新渲染完毕之间的耗时。

从测试数据来看,自定义组件模式(新框架)在复杂页面下,性能有翻倍提升!特别是数据越多、组件越复杂的页面,性能提升越大!

新版特性2:更多Vue语法支持

新版支持了更多 Vue 语法,详细如下:

  • 支持过滤器 filter
  • 支持比较复杂的 JavaScript 渲染表达式
  • 支持在 template 内使用 methods 中的函数
  • 支持 v-html (同 rich-text 的解析)
  • 支持 v-slot 新语法
  • 支持解构插槽 Prop 设置默认值
  • 支持 slot 后备内容
  • 组件支持原生事件绑定,如:@tap.native

新版不支持的 vue 语法

  • class不支持绑定Obejct变量(使用字符串的形式绑定)
  • 不支持事件修饰符:prevent、passive(在App与小程序平台,使用stop修饰符,既可以阻止冒泡也能阻止默认行为)
  • 不支持render、inline-template、X-Templates、keep-alive、transition
  • 不支持使用 Vue.use 的方式注册全局组件(在main.js使用Vue.component的方式引入)

新旧版本兼容策略

为兼容历史项目,uni-app 现阶段同时支持老的template模板模式、和新的自定义组件模式两种模式,默认策略如下:

  • HBuilderX 1.8.0+ 新创建的项目,在微信端默认会启用新的框架;
  • 历史项目默认使用老框架。如需启动新框架请按下面配置开启。
  • 但注意1.7.3群测版默认使用了新框架,升级到1.8后,也需要手动配置开启新框架

开发者可在manifest.json的源码视图里配置, manifest.json -> mp-weixin -> usingComponents切换编译模式,如下:

// manifest.json  
{  
    // ...  
    /* 小程序特有相关 */  
    "mp-weixin": {  
        "usingComponents":true //是否启用`自定义组件模式`,为true表示新的`自定义组件模式`,否则启用老的`template模板模式`  
    }  
}  

Tips:

  • 为保证自定义组件兼容性,运行到微信开发者工具时,建议将微信基础库设置为最新版本。
  • 如果你使用了新增的vue语法,请注意只有h5和微信支持这些新语法,编译到其他平台时,要用条件编译处理。

新版开发注意事项

新框架基于微信小程序自定义组件实现,在进行自定义组件开发(页面开发不影响)时,需注意部分约束,详见:https://ask.dcloud.net.cn/article/35851

性能优化建议

  1. 模板中不建议直接使用 object
<!-- 低性能写法 -->  
<uni-title title="标题文字" note="描述信息" show-extra-icon="true" :extra-icon="{color: '#4cd964',size: '22',type: 'spinner'}"></uni-title>  
<!-- 高性能写法 -->  
<template>  
    <view>  
        <uni-title title="标题文字" note="描述信息" show-extra-icon="true" :extra-icon="extraIcon"></uni-title>  
    </view>  
</template>  
<script>  
export default {  
    data() {  
        return {  
            extraIcon:{color: '#4cd964',size: '22',type: 'spinner'}  
        }  
    }  
}  
</script>  
  1. 在模板中未使用的数据不建议定义在data 中,未使用的数据一律移除到 vm 外边定义
<!-- 低性能写法 -->  
<template>  
    <view>  
        {{name}}  
    </view>  
</template>  
<script>  
export default {  
    data() {  
        return {  
            name:'',  
            types:true  
        }  
    },  
    onLoad(){  
        if(this.types){  
            this.name = '张三';  
        } else {  
            this.name = '李四';  
        }  
    }  
}  
</script>
<!-- 高性能写法 -->  
<template>  
    <view>  
        {{name}}  
    </view>  
</template>  
<script>  
let types = true ;  
export default {  
    data() {  
        return {  
            name:''  
        }  
    },  
    onLoad(){  
        if(types){  
            this.name = '张三';  
        } else {  
            this.name = '李四';  
        }  
    }  
}  
</script>
  1. 为提升开发体验,新版本增加了部分 Vue 语法,其实这些语法在微信小程序中本身是不支持的;为支持这些语法,uni-app 会在编译、运行时分别做一些额外的工作,若开发者希望追求性能极致,则建议尽量少用或者不用新增语法。

后续

新框架会陆续把新编译器迁移到其他小程序端上。

升级注意

如果你的项目是cli创建的,记得编译器在你的项目下,不会随着HBuilderX升级而升级,你需要npm update手动升级编译器。

收起阅读 »

uni-app 解决 app中调用微信支付一直返回 -1 的错误

官方文档和示例并没有写清楚。导致app中调用微信支付一直返回 -1 的错误,最终通过百度找到一位大佬成功接通iOS版微信支付、支付宝的案例,结合文档iOS和安卓版orderInfo字段数据格式不一致的情况,稍加修改后调用微信支付成功。以下为安卓版微信支付的调用代码。苹果版请参考点击此处查看iOS版完整案例

                // 安卓调用微信支付  
                uni.requestPayment({  
                    provider: "wxpay",  
                    timeStamp: JSON.stringify(result2.timestamp),  
                    nonceStr: result2.noncestr,  
                    package: result2.package,  
                    signType:"MD5",  
                    paySign: result2.sign,  
                    orderInfo: JSON.stringify({  
                        appid: result2.appid,  
                        noncestr: result2.noncestr,  
                        package: result2.package,  
                        partnerid: result2.partnerid,  
                        prepayid: result2.prepayid,  
                        timestamp: result2.timestamp,  
                        sign: result2.sign,  
                    }),  
                    success:function(res){  
                        uni.showToast({  
                            title:"支付成功",  
                            icon:"success",  
                            duration:2000,  
                            complete:function(){  

                            }  
                        });  
                    },  
                    fail:function(res){  
                        // console.log(JSON.stringify(res));  
                        uni.showModal({  
                             content: "支付失败,原因为: "   res.errMsg,  
                             showCancel: false  
                         })  
                        console.log('fail:'   JSON.stringify(res));  
                    }  
                });
继续阅读 »

官方文档和示例并没有写清楚。导致app中调用微信支付一直返回 -1 的错误,最终通过百度找到一位大佬成功接通iOS版微信支付、支付宝的案例,结合文档iOS和安卓版orderInfo字段数据格式不一致的情况,稍加修改后调用微信支付成功。以下为安卓版微信支付的调用代码。苹果版请参考点击此处查看iOS版完整案例

                // 安卓调用微信支付  
                uni.requestPayment({  
                    provider: "wxpay",  
                    timeStamp: JSON.stringify(result2.timestamp),  
                    nonceStr: result2.noncestr,  
                    package: result2.package,  
                    signType:"MD5",  
                    paySign: result2.sign,  
                    orderInfo: JSON.stringify({  
                        appid: result2.appid,  
                        noncestr: result2.noncestr,  
                        package: result2.package,  
                        partnerid: result2.partnerid,  
                        prepayid: result2.prepayid,  
                        timestamp: result2.timestamp,  
                        sign: result2.sign,  
                    }),  
                    success:function(res){  
                        uni.showToast({  
                            title:"支付成功",  
                            icon:"success",  
                            duration:2000,  
                            complete:function(){  

                            }  
                        });  
                    },  
                    fail:function(res){  
                        // console.log(JSON.stringify(res));  
                        uni.showModal({  
                             content: "支付失败,原因为: "   res.errMsg,  
                             showCancel: false  
                         })  
                        console.log('fail:'   JSON.stringify(res));  
                    }  
                });
收起阅读 »

【经验分享】pickers 省市区多级联动设置默认值

picker

【介绍】
当我们使用 mui.PopPicker 创建省、市、区三级联动,并且想要选中默认值的时候,
会出现只能选中第一级,无法选择第二级、第三级。

【原因】
这是因为 pickers 在设置默认值的时候是异步执行,并且有动画效果,我们就不能直接通过以下代码设置:

picker.pickers[0].setSelectedValue(100);  
picker.pickers[1].setSelectedValue(120);  
picker.pickers[2].setSelectedValue(123);

【解决】
如何解决?使用递归的方式调用即可
// 初始化选择器默认值
function initAddressSelector(index) {
if (index < picker.pickers.length && defaultData[index]) {
picker.pickers[index].setSelectedValue(defaultData[index], 0, initAddressSelector(index+1));
}
}

说明:调用的时候默认 index 传 0 ,这样代码会从第一个 picker 开始选择,setSelectedValue 的 第二参数为动画时长,这里设置 0 (单位:毫秒)即可,
setSelectedValue 的第三个参数为设置默认值成功之后回调,这里我们回调自己,并且下标 +1,这样就可以以此把 1、2、3 级全部设置上。
要设置的默认值可以放入一个数组里面,这样在递归的时候可以通过 index 下标获取到每一级的默认值。

继续阅读 »

【介绍】
当我们使用 mui.PopPicker 创建省、市、区三级联动,并且想要选中默认值的时候,
会出现只能选中第一级,无法选择第二级、第三级。

【原因】
这是因为 pickers 在设置默认值的时候是异步执行,并且有动画效果,我们就不能直接通过以下代码设置:

picker.pickers[0].setSelectedValue(100);  
picker.pickers[1].setSelectedValue(120);  
picker.pickers[2].setSelectedValue(123);

【解决】
如何解决?使用递归的方式调用即可
// 初始化选择器默认值
function initAddressSelector(index) {
if (index < picker.pickers.length && defaultData[index]) {
picker.pickers[index].setSelectedValue(defaultData[index], 0, initAddressSelector(index+1));
}
}

说明:调用的时候默认 index 传 0 ,这样代码会从第一个 picker 开始选择,setSelectedValue 的 第二参数为动画时长,这里设置 0 (单位:毫秒)即可,
setSelectedValue 的第三个参数为设置默认值成功之后回调,这里我们回调自己,并且下标 +1,这样就可以以此把 1、2、3 级全部设置上。
要设置的默认值可以放入一个数组里面,这样在递归的时候可以通过 index 下标获取到每一级的默认值。

收起阅读 »

【解决办法】打开文件服务失败,请尝试拔掉数据线后重新连接手机

真机调试 真机运行

当使用 HBuilder 真机运行编写好的 app 时,若遇到以下提示,重启手机即可解决:
正在建立手机连接...
正在同步手机端程序文件...
打开文件服务失败,请尝试拔掉数据线后重新连接手机

使用 iPhone6s 连接电脑,正常真机运行,当直接拔掉数据线之后重新连接电脑会出现此问题,
遇到此问题时只需要重启手机重新运行即可,或者尽量避免直接拔数据线,而是采用停止运行之后再拔。

继续阅读 »

当使用 HBuilder 真机运行编写好的 app 时,若遇到以下提示,重启手机即可解决:
正在建立手机连接...
正在同步手机端程序文件...
打开文件服务失败,请尝试拔掉数据线后重新连接手机

使用 iPhone6s 连接电脑,正常真机运行,当直接拔掉数据线之后重新连接电脑会出现此问题,
遇到此问题时只需要重启手机重新运行即可,或者尽量避免直接拔数据线,而是采用停止运行之后再拔。

收起阅读 »

android 多渠道打包白屏问题的解决

白屏 uni_app

多渠道打包,当applicationId ,与包名不一致时,Uni-app会出现白屏问题
原因,PdrR 不能引用到 包资源文件
解决方案:
1、在工程 新建包io.dcloud ,创建PdrR.java
2、复制源码到创建的java文件里面,修改 init()方法

public static void init(Context var0) {
if (var0 != null) {
a = " ";//你的包名,Androidmanifest里的包名
}
}

3、Rebuild project 一下,会报错,因为同时存在两个PdrR.java文件(忽略报的警告)
4、去app/build/intermediates/javac/ 你的app包名/ 目录下找到 编译生成的PdrR.class文件
5、用压缩器打开5plus.aar 包,打开里面的classes.jar,把自己生成的PdrR.class 进行替换
直接用解压文件打开,然后找到原先的PdrR.class删除,然后复制进去jar包里面即可
6、重新导入修改的aar包

继续阅读 »

多渠道打包,当applicationId ,与包名不一致时,Uni-app会出现白屏问题
原因,PdrR 不能引用到 包资源文件
解决方案:
1、在工程 新建包io.dcloud ,创建PdrR.java
2、复制源码到创建的java文件里面,修改 init()方法

public static void init(Context var0) {
if (var0 != null) {
a = " ";//你的包名,Androidmanifest里的包名
}
}

3、Rebuild project 一下,会报错,因为同时存在两个PdrR.java文件(忽略报的警告)
4、去app/build/intermediates/javac/ 你的app包名/ 目录下找到 编译生成的PdrR.class文件
5、用压缩器打开5plus.aar 包,打开里面的classes.jar,把自己生成的PdrR.class 进行替换
直接用解压文件打开,然后找到原先的PdrR.class删除,然后复制进去jar包里面即可
6、重新导入修改的aar包

收起阅读 »

力谱云社区团购解决方案:开发制作社区团购APP

5+App开发

新年新气象,新市场鼓动新风口。随着2018年末社区团购一夕爆红的乐观市场走势,以及对应社区团购APP的可观盈利,在新的一年中,市场春风拂过,大量传统企业家们,对社区团购APP已不再是简单的观望不前,而是摩拳擦掌,想要快速进入社区团购这一新零售赛道。那么在社区团购APP制作前应该先做哪些准备工作?今天就先带您了解一下社区团购APP的最新动态,以及如何通过制作APP的渠道从电商平台模式转化为社区团购模式?

社区团购资本大批入场,企业争相跑马圈地新零售

据了解,目前社区团购APP,仅在今年年初就斩获了近50亿的资本投入,在头部社区团购企业兴盛优选、松鼠拼拼、食享会之后,专家推测,还将有更多传统企业、甚至草根创业者将跻身社区团购。目前,社区团购企业所打造的APP平台模式,在技术方面并无颇多创新,因此,是否拥有线下门店经营,成为了社区团购企业在运营方面的分水岭。
无门店运营模式:以食享会、你我您等为例,他们的平台直接略过线下门店,通过节省店面、人力成本,快速的城市拓展,进行市场方面的跑马圈地。
有门店运营模式:以拥有线下门店的兴盛优选为例,拥有良好的线下用户体验,供应链优势明显,平台口碑正面效应能持续性扩散。
如上所知,社区团购的运营模式易于复制推广,因而诸多坐拥生鲜、日用品供应链,以及本身做生鲜水果类的商家企业,也开始纷纷谋求进行社区团购的商业模式探索。

力谱云SaaS+PaaS云计算技术创新河,高效、低成本、功能齐备受瞩目

其实,之所以力谱云的研发技术,能突破高成本的应用开发瓶颈,为企业提供低于传统App开发成本90%的效能,关键在于“SaaS+PaaS”云计算模式的创新引入。APP制作这项技术层面的创新之举,不仅大幅降低了技术开发门槛,更能提升研发效率,这也成为了诸多中小企业进行移动互联网产业升级的福音。目前,力谱云推出了社区分销、社交团购、服务预订和入住、以及订货和供应链,这四大维度的核心解决方案,支持B2C、B2B、O2O、OMO、B2B2C等多种复杂商业平台模式,提供从研发到运营的全程技术护航,支持苹果App+安卓App+微信小程序+微商城+移动网站的平台打造,让企业线上运营渠道全面贯通,并可通过丰富前沿的营销工具,打出平台销售佳绩。

力谱云的一站式社区团购解决方案

对此,力谱云所提出的一站式社区团购APP制作解决方案,力图在渠道方面,助力企业一站式开发iOS App/安卓App、微商城、小程序、移动网站,让社区团长灵活营销使用。在营销方面,为企业配置数余种营销工具如拼团App、秒杀App、分销App等,助力企业刺激销量增长。在管理方面,企业方不仅可以通过PC端管理后台,进行订单、会员数据的统筹管理,还可通过配送端、移动管理端等多种移动运营App,辅助企业日常运营、跟进物流、进行核销等工作,让社区团购模式,真正通过高新技术,进行快捷、高效、低成本地落地开展。

如果你的企业正身处三四五线城市,有供应链,有人脉圈,只要有社区就有企业可发挥的目标人群。通过力谱云,即刻加入到目前最前沿的营销风口——社区团购吧!

继续阅读 »

新年新气象,新市场鼓动新风口。随着2018年末社区团购一夕爆红的乐观市场走势,以及对应社区团购APP的可观盈利,在新的一年中,市场春风拂过,大量传统企业家们,对社区团购APP已不再是简单的观望不前,而是摩拳擦掌,想要快速进入社区团购这一新零售赛道。那么在社区团购APP制作前应该先做哪些准备工作?今天就先带您了解一下社区团购APP的最新动态,以及如何通过制作APP的渠道从电商平台模式转化为社区团购模式?

社区团购资本大批入场,企业争相跑马圈地新零售

据了解,目前社区团购APP,仅在今年年初就斩获了近50亿的资本投入,在头部社区团购企业兴盛优选、松鼠拼拼、食享会之后,专家推测,还将有更多传统企业、甚至草根创业者将跻身社区团购。目前,社区团购企业所打造的APP平台模式,在技术方面并无颇多创新,因此,是否拥有线下门店经营,成为了社区团购企业在运营方面的分水岭。
无门店运营模式:以食享会、你我您等为例,他们的平台直接略过线下门店,通过节省店面、人力成本,快速的城市拓展,进行市场方面的跑马圈地。
有门店运营模式:以拥有线下门店的兴盛优选为例,拥有良好的线下用户体验,供应链优势明显,平台口碑正面效应能持续性扩散。
如上所知,社区团购的运营模式易于复制推广,因而诸多坐拥生鲜、日用品供应链,以及本身做生鲜水果类的商家企业,也开始纷纷谋求进行社区团购的商业模式探索。

力谱云SaaS+PaaS云计算技术创新河,高效、低成本、功能齐备受瞩目

其实,之所以力谱云的研发技术,能突破高成本的应用开发瓶颈,为企业提供低于传统App开发成本90%的效能,关键在于“SaaS+PaaS”云计算模式的创新引入。APP制作这项技术层面的创新之举,不仅大幅降低了技术开发门槛,更能提升研发效率,这也成为了诸多中小企业进行移动互联网产业升级的福音。目前,力谱云推出了社区分销、社交团购、服务预订和入住、以及订货和供应链,这四大维度的核心解决方案,支持B2C、B2B、O2O、OMO、B2B2C等多种复杂商业平台模式,提供从研发到运营的全程技术护航,支持苹果App+安卓App+微信小程序+微商城+移动网站的平台打造,让企业线上运营渠道全面贯通,并可通过丰富前沿的营销工具,打出平台销售佳绩。

力谱云的一站式社区团购解决方案

对此,力谱云所提出的一站式社区团购APP制作解决方案,力图在渠道方面,助力企业一站式开发iOS App/安卓App、微商城、小程序、移动网站,让社区团长灵活营销使用。在营销方面,为企业配置数余种营销工具如拼团App、秒杀App、分销App等,助力企业刺激销量增长。在管理方面,企业方不仅可以通过PC端管理后台,进行订单、会员数据的统筹管理,还可通过配送端、移动管理端等多种移动运营App,辅助企业日常运营、跟进物流、进行核销等工作,让社区团购模式,真正通过高新技术,进行快捷、高效、低成本地落地开展。

如果你的企业正身处三四五线城市,有供应链,有人脉圈,只要有社区就有企业可发挥的目标人群。通过力谱云,即刻加入到目前最前沿的营销风口——社区团购吧!

收起阅读 »

自定义组件嵌套的折磨

组件 uniapp

昨天一天时间浪费在了组件上,本想着代码复用一下的,自己封装了list和list-item的组件,谁知道通过组件slot嵌套进去的组件没法传数据,我就蒙了,我以为自己哪里写错了;但是再无数次的摧残之后,我将list-item组件单独提出来试了一下,数据传进去了,神奇了,太神奇了,当时我有种一万头XXX飞奔而过的感觉......
代码大概是这样的

<template>  
     <view>  
          // 这样子,title和value死活传不进去  
          <list>  
               <list-item title="姓名" value="张三" />  
               <list-item title="姓名" value="张三" />  
          </list>  

          // 这样子,它就传进去了,莫名其妙  
          <list-item title="姓名" value="张三" />  
          <list-item title="姓名" value="张三" />  
     </view>  
</template>

心如死灰呀,,我还是老老实实的复制粘贴吧............

继续阅读 »

昨天一天时间浪费在了组件上,本想着代码复用一下的,自己封装了list和list-item的组件,谁知道通过组件slot嵌套进去的组件没法传数据,我就蒙了,我以为自己哪里写错了;但是再无数次的摧残之后,我将list-item组件单独提出来试了一下,数据传进去了,神奇了,太神奇了,当时我有种一万头XXX飞奔而过的感觉......
代码大概是这样的

<template>  
     <view>  
          // 这样子,title和value死活传不进去  
          <list>  
               <list-item title="姓名" value="张三" />  
               <list-item title="姓名" value="张三" />  
          </list>  

          // 这样子,它就传进去了,莫名其妙  
          <list-item title="姓名" value="张三" />  
          <list-item title="姓名" value="张三" />  
     </view>  
</template>

心如死灰呀,,我还是老老实实的复制粘贴吧............

收起阅读 »

uniapp 实现 NFC标签读取 和 写入

NFC uniapp

参考文章链接:
NFC读取卡片ID
磊子文章

uniapp 开发,找了很久没找到相关的NFC读写的代码;解决相关问题也用了些时间,希望文章有用;

最开始没有找到uniapp中的,NFC贴上手机后对应的响应事件;
有发帖提问怎么解决;
链接:uniapp怎么监听h5+的event事件http://ask.dcloud.net.cn/question/66505
在uniapp中:封装在 onShow 和onHide

代码基本同之前磊子提供的一样,全部放在methods 里面;
listenNFCStatus()
在onLoad的时候调用;
读写是在onShow的时候调用;

下面这段

nfcAdapter.disableForegroundDispatch(main);

打算放在onHide但是出现三方脚本错误的报错;
没法解决;就没放 = =;

但是单独的读没有任何影响,这是我写了读出数据会有个消息弹框,响应NFC并读取数据的方法是在onShow里面的;

手机息屏重新打开,扔会出发onShow,自动又调用了一次读取数据,所以遇到bug就是NFC的响应事件和手机息屏事件冲突;

暂时加了个计数器 count ,第一次进入的时候不调用读取;并且在hide和show加了时间戳,通过onHide 和 onShow响应的时间差,来判断是否触发读取事件;

如果有小伙伴知道怎么弄求分享

uniapp支持 plus.globalEvent.addEventListener('newintent', e =>{}); 后,之前因为懒没有改,后来出现bug了,就抽空改了下,突然想起来修改这个;

我是加载onReady内的;

var that = this ;  
    plus.globalEvent.addEventListener('newintent', e =>{  
              console.log("newIntent");  

                  that.readData();  
            });

将之前在onShow 和onHide 全部删掉。当时设置的onShow 和 onHide 的时间差是400,这样搞会出问题,当数据或者长时间放置等其他时候,会造成无法调起nfc这个。还是需要用安卓的newIntent。

需要放在 应用层级,app.vue 下。后期写个完整的贴

附上整体js代码,部分自己的function已删除;

    var NfcAdapter;  
    var NdefRecord;  
    var NdefMessage;  
    var waiting  
    var readyRead = false;  
    var nfcAdapter,main , pendingIntent,intentFiltersArray,techListsArray, IntentFilter  

    export default {  
        data() {  
            return {  
                currentNFCInfo: [], //NFC 读取消息;  
                bannerShow: false,  
                remark:"",  
                message: "",  
                count:0,  
                timestampHide:"",  
                timestampShow:""  
            };  
        },  
        methods: {  
            listenNFCStatus() {  
                try {  
                    console.log('Init NFC...');  
                    main = plus.android.runtimeMainActivity();  
                    var Intent = plus.android.importClass('android.content.Intent');  
                    var Activity = plus.android.importClass('android.app.Activity');  
                    var PendingIntent = plus.android.importClass('android.app.PendingIntent');  
                    IntentFilter = plus.android.importClass('android.content.IntentFilter');  
                    NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');  
                    nfcAdapter = NfcAdapter.getDefaultAdapter(main);  
                    var intent = new Intent(main, main.getClass());  
                    intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  
                    pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);  
                    var ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");  
                    ndef.addDataType("*/*");  
                    intentFiltersArray = [ndef];  
                    techListsArray = [  
                        ["android.nfc.tech.IsoDep"],  
                        ["android.nfc.tech.NfcA"],  
                        ["android.nfc.tech.NfcB"],  
                        ["android.nfc.tech.NfcF"],  
                        ["android.nfc.tech.Ndef"],  
                        ["android.nfc.tech.NfcV"],  
                        ["android.nfc.tech.NdefFormatable"],  
                        ["android.nfc.tech.MifareClassic"],  
                        ["android.nfc.tech.MifareUltralight"]  
                    ];  

                } catch (e) {  
                    console.error(e);  
                }  
            },  
            handle_nfc_data() {  

                NdefRecord = plus.android.importClass("android.nfc.NdefRecord");  
                NdefMessage = plus.android.importClass("android.nfc.NdefMessage");  
                // main = plus.android.runtimeMainActivity();  
                var intent = main.getIntent();  

                console.log("action type:" + intent.getAction());  
                if ("android.nfc.action.TECH_DISCOVERED" == intent.getAction()) {  
                    if (readyRead) {  
                        this.__read(intent);  
                        readyRead = false;  
                    }  
                } else {  
                    // waiting.close();  
                    console.log("nfc读取失败")  
                }  
            },  
            __read(intent) {  
                try {  
                    var content = "";  
                    waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");  
                    waiting.setTitle('请勿移开标签\n正在读取数据...');  
                    var tag = plus.android.importClass("android.nfc.Tag");  
                    waiting.close();  
                    var Parcelable = plus.android.importClass("android.os.Parcelable");  
                    // var rawmsgs = intent.getParcelableArrayExtra("android.nfc.extra.NDEF_MESSAGES");  
                    var rawmsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);  

                    if (rawmsgs != null && rawmsgs.length > 0) {  
                        waiting.close();  
                        // console.log(JSON.stringify(rawmsgs[0]));  
                        var records = rawmsgs[0].getRecords();  
                        var result = records[0].getPayload();  
                        // console.log(result)  
                        if (result != null) {  
                            var s = plus.android.newObject("java.lang.String", result);  
                            console.log(s);  
                            this.currentNFCInfo = s;  
                        } else {  
                            this.currentNFCInfo = "";  
                        }  
                    } else {  
                        console.log("NFC获取失败");  
                        uni.showToast({  
                            title: "NFC获取失败.",  
                            icon: "none"  
                        });  
                    }  

                } catch (e) {  
                    console.log(e);  
                    console.log("NFC获取失败,丢出异常");  
                    waiting.close();  
                    uni.showToast({  
                        title: "NFC获取失败,丢出异常.",  
                        icon: "none"  
                    });  
                    //TODO handle the exception  
                }  
            },  
            readData() {  
                readyRead = true;  
            //  waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");  
                setTimeout(this.handle_nfc_data, 1000);  
            }  
        },  
        onLoad: function(option) {  
            this.listenNFCStatus()  
        },  
        onShow: function(){  
            console.log('page Show');  
            this.timestampShow = (new Date()).getTime();  
            console.log(this.timestampShow)  
            var TimeScale =  this.timestampShow - this.timestampHide;  
            console.log(TimeScale);  
                        nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);  
            if(this.count++ == 0){  
                // this.listenNFCStatus()  
                return false;  
            }else if(TimeScale > 400){  
                return false;  
            }else{  
                this.readData();  
            }  
        },  
        onHide:function(){  
            console.log("onHide");  
            this.timestampHide = (new Date()).getTime();  
            console.log(this.timestampHide);  
        }  
    }

写入分开写了,也是一样的写法

            __write(intent) {  
                try {  
                    waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");  
                    waiting.setTitle('请勿移开标签\n正在写入...');  
                    // var text = document.getElementById('text').value;  
                    console.log("text=" + this.writeCode);  
                    var textBytes = plus.android.invoke(this.writeCode, "getBytes");  
                    var textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,  
                        plus.android.invoke("text/plain", "getBytes"), plus.android.invoke("", "getBytes"), textBytes);  
                    var message = new NdefMessage([textRecord]);  
                    var Ndef = plus.android.importClass('android.nfc.tech.Ndef');  
                    var NdefFormatable = plus.android.importClass('android.nfc.tech.NdefFormatable');  
                    var tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  
                    var ndef = Ndef.get(tag);  
                    if (ndef != null) {  
                        var size = message.toByteArray().length;  
                        console.log("size=" + size);  
                        ndef.connect();  
                        if (!ndef.isWritable()) {  
                            console.log("tag不允许写入");  
                            waiting.close();  
                            uni.showToast({  
                                title: "tag不允许写入.",  
                                icon: "none"  
                            });  
                            return;  
                        }  
                        if (ndef.getMaxSize() < size) {  
                            console.log("文件大小超出容量");  
                            waiting.close();  
                            uni.showToast({  
                                title: "文件大小超出容量.",  
                                icon: "none"  
                            });  
                            return;  
                        }  
                        // console.log('写入数据:' + JSON.stringify(message) + ' __TYPE__: ' + JSON.stringify(message.__TYPE__));  
                        console.log("message:" + message)  
                        ndef.writeNdefMessage(message);  

                        waiting.close();  
                        console.log("写入数据成功.");  
                        uni.showToast({  
                            title: "写入数据成功.",  
                            icon: "none"  
                        });  
                        this.writeCode = "XJD:" + this.detailObj.code;  
                        this.updateCode(); //数据写入成功后,数据关联成功;  
                        return;  
                    } else {  
                        var format = NdefFormatable.get(tag);  
                        if (format != null) {  
                            try {  
                                format.connect();  
                                format.format(message);  
                                console.log("格式化tag并且写入message")  
                                waiting.close();  
                                return;  
                            } catch (e) {  
                                console.log("格式化tag失败.");  
                                waiting.close();  
                                uni.showToast({  
                                    title: "格式化tag失败.",  
                                    icon: "none"  
                                });  
                                return;  
                            }  
                        } else {  
                            console.log("Tag不支持NDEF");  
                            uni.showToast({  
                                title: "Tag不支持NDEF",  
                                icon: "none"  
                            });  
                            waiting.close();  
                            return;  
                        }  
                    }  
                } catch (e) {  
                    console.log("error=" + e);  
                    waiting.close();  
                    console.log('写入失败');  
                }  
            },  
            writeData() {  
                readyWriteData = true;  
                // waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");  
                setTimeout(this.handle_nfc_data, 1000);  
            },

最近新增了,可读写nfcv格式的标签
http://ask.dcloud.net.cn/article/36108

有其他小伙伴解决了或者有更好的方式可以多多交流

继续阅读 »

参考文章链接:
NFC读取卡片ID
磊子文章

uniapp 开发,找了很久没找到相关的NFC读写的代码;解决相关问题也用了些时间,希望文章有用;

最开始没有找到uniapp中的,NFC贴上手机后对应的响应事件;
有发帖提问怎么解决;
链接:uniapp怎么监听h5+的event事件http://ask.dcloud.net.cn/question/66505
在uniapp中:封装在 onShow 和onHide

代码基本同之前磊子提供的一样,全部放在methods 里面;
listenNFCStatus()
在onLoad的时候调用;
读写是在onShow的时候调用;

下面这段

nfcAdapter.disableForegroundDispatch(main);

打算放在onHide但是出现三方脚本错误的报错;
没法解决;就没放 = =;

但是单独的读没有任何影响,这是我写了读出数据会有个消息弹框,响应NFC并读取数据的方法是在onShow里面的;

手机息屏重新打开,扔会出发onShow,自动又调用了一次读取数据,所以遇到bug就是NFC的响应事件和手机息屏事件冲突;

暂时加了个计数器 count ,第一次进入的时候不调用读取;并且在hide和show加了时间戳,通过onHide 和 onShow响应的时间差,来判断是否触发读取事件;

如果有小伙伴知道怎么弄求分享

uniapp支持 plus.globalEvent.addEventListener('newintent', e =>{}); 后,之前因为懒没有改,后来出现bug了,就抽空改了下,突然想起来修改这个;

我是加载onReady内的;

var that = this ;  
    plus.globalEvent.addEventListener('newintent', e =>{  
              console.log("newIntent");  

                  that.readData();  
            });

将之前在onShow 和onHide 全部删掉。当时设置的onShow 和 onHide 的时间差是400,这样搞会出问题,当数据或者长时间放置等其他时候,会造成无法调起nfc这个。还是需要用安卓的newIntent。

需要放在 应用层级,app.vue 下。后期写个完整的贴

附上整体js代码,部分自己的function已删除;

    var NfcAdapter;  
    var NdefRecord;  
    var NdefMessage;  
    var waiting  
    var readyRead = false;  
    var nfcAdapter,main , pendingIntent,intentFiltersArray,techListsArray, IntentFilter  

    export default {  
        data() {  
            return {  
                currentNFCInfo: [], //NFC 读取消息;  
                bannerShow: false,  
                remark:"",  
                message: "",  
                count:0,  
                timestampHide:"",  
                timestampShow:""  
            };  
        },  
        methods: {  
            listenNFCStatus() {  
                try {  
                    console.log('Init NFC...');  
                    main = plus.android.runtimeMainActivity();  
                    var Intent = plus.android.importClass('android.content.Intent');  
                    var Activity = plus.android.importClass('android.app.Activity');  
                    var PendingIntent = plus.android.importClass('android.app.PendingIntent');  
                    IntentFilter = plus.android.importClass('android.content.IntentFilter');  
                    NfcAdapter = plus.android.importClass('android.nfc.NfcAdapter');  
                    nfcAdapter = NfcAdapter.getDefaultAdapter(main);  
                    var intent = new Intent(main, main.getClass());  
                    intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);  
                    pendingIntent = PendingIntent.getActivity(main, 0, intent, 0);  
                    var ndef = new IntentFilter("android.nfc.action.TECH_DISCOVERED");  
                    ndef.addDataType("*/*");  
                    intentFiltersArray = [ndef];  
                    techListsArray = [  
                        ["android.nfc.tech.IsoDep"],  
                        ["android.nfc.tech.NfcA"],  
                        ["android.nfc.tech.NfcB"],  
                        ["android.nfc.tech.NfcF"],  
                        ["android.nfc.tech.Ndef"],  
                        ["android.nfc.tech.NfcV"],  
                        ["android.nfc.tech.NdefFormatable"],  
                        ["android.nfc.tech.MifareClassic"],  
                        ["android.nfc.tech.MifareUltralight"]  
                    ];  

                } catch (e) {  
                    console.error(e);  
                }  
            },  
            handle_nfc_data() {  

                NdefRecord = plus.android.importClass("android.nfc.NdefRecord");  
                NdefMessage = plus.android.importClass("android.nfc.NdefMessage");  
                // main = plus.android.runtimeMainActivity();  
                var intent = main.getIntent();  

                console.log("action type:" + intent.getAction());  
                if ("android.nfc.action.TECH_DISCOVERED" == intent.getAction()) {  
                    if (readyRead) {  
                        this.__read(intent);  
                        readyRead = false;  
                    }  
                } else {  
                    // waiting.close();  
                    console.log("nfc读取失败")  
                }  
            },  
            __read(intent) {  
                try {  
                    var content = "";  
                    waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");  
                    waiting.setTitle('请勿移开标签\n正在读取数据...');  
                    var tag = plus.android.importClass("android.nfc.Tag");  
                    waiting.close();  
                    var Parcelable = plus.android.importClass("android.os.Parcelable");  
                    // var rawmsgs = intent.getParcelableArrayExtra("android.nfc.extra.NDEF_MESSAGES");  
                    var rawmsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);  

                    if (rawmsgs != null && rawmsgs.length > 0) {  
                        waiting.close();  
                        // console.log(JSON.stringify(rawmsgs[0]));  
                        var records = rawmsgs[0].getRecords();  
                        var result = records[0].getPayload();  
                        // console.log(result)  
                        if (result != null) {  
                            var s = plus.android.newObject("java.lang.String", result);  
                            console.log(s);  
                            this.currentNFCInfo = s;  
                        } else {  
                            this.currentNFCInfo = "";  
                        }  
                    } else {  
                        console.log("NFC获取失败");  
                        uni.showToast({  
                            title: "NFC获取失败.",  
                            icon: "none"  
                        });  
                    }  

                } catch (e) {  
                    console.log(e);  
                    console.log("NFC获取失败,丢出异常");  
                    waiting.close();  
                    uni.showToast({  
                        title: "NFC获取失败,丢出异常.",  
                        icon: "none"  
                    });  
                    //TODO handle the exception  
                }  
            },  
            readData() {  
                readyRead = true;  
            //  waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");  
                setTimeout(this.handle_nfc_data, 1000);  
            }  
        },  
        onLoad: function(option) {  
            this.listenNFCStatus()  
        },  
        onShow: function(){  
            console.log('page Show');  
            this.timestampShow = (new Date()).getTime();  
            console.log(this.timestampShow)  
            var TimeScale =  this.timestampShow - this.timestampHide;  
            console.log(TimeScale);  
                        nfcAdapter.enableForegroundDispatch(main, pendingIntent, intentFiltersArray, techListsArray);  
            if(this.count++ == 0){  
                // this.listenNFCStatus()  
                return false;  
            }else if(TimeScale > 400){  
                return false;  
            }else{  
                this.readData();  
            }  
        },  
        onHide:function(){  
            console.log("onHide");  
            this.timestampHide = (new Date()).getTime();  
            console.log(this.timestampHide);  
        }  
    }

写入分开写了,也是一样的写法

            __write(intent) {  
                try {  
                    waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");  
                    waiting.setTitle('请勿移开标签\n正在写入...');  
                    // var text = document.getElementById('text').value;  
                    console.log("text=" + this.writeCode);  
                    var textBytes = plus.android.invoke(this.writeCode, "getBytes");  
                    var textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,  
                        plus.android.invoke("text/plain", "getBytes"), plus.android.invoke("", "getBytes"), textBytes);  
                    var message = new NdefMessage([textRecord]);  
                    var Ndef = plus.android.importClass('android.nfc.tech.Ndef');  
                    var NdefFormatable = plus.android.importClass('android.nfc.tech.NdefFormatable');  
                    var tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  
                    var ndef = Ndef.get(tag);  
                    if (ndef != null) {  
                        var size = message.toByteArray().length;  
                        console.log("size=" + size);  
                        ndef.connect();  
                        if (!ndef.isWritable()) {  
                            console.log("tag不允许写入");  
                            waiting.close();  
                            uni.showToast({  
                                title: "tag不允许写入.",  
                                icon: "none"  
                            });  
                            return;  
                        }  
                        if (ndef.getMaxSize() < size) {  
                            console.log("文件大小超出容量");  
                            waiting.close();  
                            uni.showToast({  
                                title: "文件大小超出容量.",  
                                icon: "none"  
                            });  
                            return;  
                        }  
                        // console.log('写入数据:' + JSON.stringify(message) + ' __TYPE__: ' + JSON.stringify(message.__TYPE__));  
                        console.log("message:" + message)  
                        ndef.writeNdefMessage(message);  

                        waiting.close();  
                        console.log("写入数据成功.");  
                        uni.showToast({  
                            title: "写入数据成功.",  
                            icon: "none"  
                        });  
                        this.writeCode = "XJD:" + this.detailObj.code;  
                        this.updateCode(); //数据写入成功后,数据关联成功;  
                        return;  
                    } else {  
                        var format = NdefFormatable.get(tag);  
                        if (format != null) {  
                            try {  
                                format.connect();  
                                format.format(message);  
                                console.log("格式化tag并且写入message")  
                                waiting.close();  
                                return;  
                            } catch (e) {  
                                console.log("格式化tag失败.");  
                                waiting.close();  
                                uni.showToast({  
                                    title: "格式化tag失败.",  
                                    icon: "none"  
                                });  
                                return;  
                            }  
                        } else {  
                            console.log("Tag不支持NDEF");  
                            uni.showToast({  
                                title: "Tag不支持NDEF",  
                                icon: "none"  
                            });  
                            waiting.close();  
                            return;  
                        }  
                    }  
                } catch (e) {  
                    console.log("error=" + e);  
                    waiting.close();  
                    console.log('写入失败');  
                }  
            },  
            writeData() {  
                readyWriteData = true;  
                // waiting = plus.nativeUI.showWaiting("请将NFC标签靠近!");  
                setTimeout(this.handle_nfc_data, 1000);  
            },

最近新增了,可读写nfcv格式的标签
http://ask.dcloud.net.cn/article/36108

有其他小伙伴解决了或者有更好的方式可以多多交流

收起阅读 »