HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

UniAPP车牌实时离线扫描识别

插件说明

UniAPP车牌实时离线扫描识别(Android平台)

标签:车牌实时识别 车牌离线识别 车牌实时扫描 车牌离线扫描 车牌实时离线识别 车牌实时离线扫描

特点:

  • 1、使用方便,引入即可;
  • 2、响应快速,原生体验;
  • 3、完全离线,无需联网;
  • 4、插件包体积小,不占用云打包资源(参考后边压缩体积教程);
  • 5、完全独立,不依赖任何第三方SDK(目前发现很多依赖百度等第三方SDK,需要单独进行购买第三方服务或者授权,此插件承诺终身使用);
  • 6、返回结果内容丰富,支持:车牌号车牌颜色车牌抓拍图片
  • 7、支持车牌类型齐全;
  • 8、支持离线打包;
  • 9、可进行定制;

效果:

车牌实时识别
车牌实时识别-结果

支持车牌:

序号 车牌类型 是否支持
1 单行蓝牌
2 单行黄牌
3 新能源车牌
4 白色警用车牌
5 教练车牌
6 武警车牌
7 双层黄牌
8 双层武警
9 使馆车牌
10 港澳牌车
11 双层农用车牌
12 民航车牌
13 摩托车牌
14 危险品车牌

平台兼容性

平台 是否支持 支持版本 支持CPU类型
Android 5.0 - 13.0 + armeabi-v7a、arm64-v8a、x86
iOS ×

原生插件通用使用流程:

  • 1、购买插件,选择该插件绑定的项目;
  • 2、在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块,如需要填写参数则参考插件作者的文档添加;
  • 3、根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能;
  • 4、打包自定义基座,选择插件,得到自定义基座,然后运行时选择自定义基座,进行log输出测试;
  • 5、开发完毕后正式云打包;

目前插件市场所有付费原生插件均不支持离线打包,此插件支持离线打包!!!

  • Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/android
  • iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/ios

使用HBuilderX2.7.14以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提示包名绑定不一致时,需要在HBuilderX项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件重新选择;

使用说明

参考官网原生插件使用:
https://nativesupport.dcloud.net.cn/NativePlugin/use/use.html

使用步骤

  • 1、解压插件:

    解压插件zip包到uniapp项目目录nativePlugins中;

  • 2、引用插件:

    1) 点击manifest.json 进行配置;
    2) 选择指定的本地插件(自动识别):

  • 3、使用插件:

// 一行代码引用  
var plateModule = uni.requireNativePlugin("PlateModule")  

// 调用识别程序  
plateModule.startPlate(  
    {  
        'accuracy': 0.80, // 识别准确率(取值范围:0.0-1.0。准确率大于该值才返回结果,值越大识别越准确但也会越慢,需要测试出来最适合自己的准确率)  
        'quality': 80, // 图像压缩率(取值范围:0-100。 0:压缩100%,100:不压缩)  
        'showText': true // 是否显示提示文字  
    },  
    (ret) => {  
        console.log("showLPR result : ", ret);  
        modal.toast({  
            message: ret,  
            duration: 1.5  
        });  
        //解析  
        this.success = true;  
        if (ret.number) {  
            this.number = ret.number;  
        }  
        if (ret.color) {  
            this.color = ret.color;  
        }  
        if (ret.image) {  
            this.image = ret.image;  
            this.imagePath = "file:///" + ret.image;  
        }  

    }  
);  
  • 3、压缩体积教程:

将插件目录中文件lib-lpr-release.aar使用压缩工具打开,根据自己使用的Android平台进行保留jni目录下.so文件,即删除掉多余的平台目录;

目录结构:

├─ package.json  
├─ android  
│  ├── res  
│  │── libs  
│  │── assets  
│  │── uniplugin_lpr-release.aar  
│  └── lib-lpr-release.aar  
└─ ios

lib-lpr-release.aar文件压缩包中目录结构:

├─ AndroidManifest.xml  
├─ classes.jar  
├─ res  
├─ assets  
├─ jni  
│  │── armeabi-v7a  
│  │── arm64-v8a  
│  └── x86  
└─ios

举例:如果当前平台为armeabi-v7a,则只需要保留armeabi-v7a目录即可,其他同级目录arm64-v8ax86均可删除;

完整代码示例

<template>  
    <view class="button-sp-area">  
        <button type="primary" plain="true" @click="showLPR()">点击识别车牌</button>  
        <view style="margin-top: 20px; padding: 20px;" v-show="this.success == true">  
            <view style="text-align: center;color: lightslategray;">  
                <text>车牌号:{{number}}</text>  
            </view>  
            <view style="text-align: center;color: lightslategray;">  
                <text>车牌颜色:{{color}}</text>  
            </view>  
            <view style="text-align: center;color: lightslategray;">  
                <text>图片地址:{{image}}</text>  
            </view>  
            <view style="text-align: center;color: lightslategray;">  
                <image :src="imagePath"></image>  
            </view>  
        </view>  
    </view>  
</template>  

<script>  
    const modal = uni.requireNativePlugin('modal');  
    // 获取 module  
    var plateModule = uni.requireNativePlugin("PlateModule")  
    export default {  
        data() {  
            return {  
                success: false,  
                number: "",  
                color: "",  
                image: "",  
                imagePath: ""  
            }  
        },  
        methods: {  
            showLPR() {  
                console.log('showLPR...')  

                //带参数  
                plateModule.startPlate(  
                    {  
                        'accuracy': 0.80, // 识别准确率(取值范围:0.0-1.0。准确率大于该值才返回结果,值越大识别越准确但也会越慢,需要测试出来最适合自己的准确率)  
                        'quality': 80, // 图像压缩率(取值范围:0-100。 0:压缩100%,100:不压缩)  
                        'showText': true // 是否显示提示文字  
                    },  
                    (ret) => {  
                        console.log("showLPR result : ", ret);  
                        modal.toast({  
                            message: ret,  
                            duration: 1.5  
                        });  
                        //解析  
                        this.success = true;  
                        if (ret.number) {  
                            this.number = ret.number;  
                        }  
                        if (ret.color) {  
                            this.color = ret.color;  
                        }  
                        if (ret.image) {  
                            this.image = ret.image;  
                            this.imagePath = "file:///" + ret.image;  
                        }  

                    }  
                );  
            }  
        }  
    }  
</script>  

<style>  

</style>  
继续阅读 »

插件说明

UniAPP车牌实时离线扫描识别(Android平台)

标签:车牌实时识别 车牌离线识别 车牌实时扫描 车牌离线扫描 车牌实时离线识别 车牌实时离线扫描

特点:

  • 1、使用方便,引入即可;
  • 2、响应快速,原生体验;
  • 3、完全离线,无需联网;
  • 4、插件包体积小,不占用云打包资源(参考后边压缩体积教程);
  • 5、完全独立,不依赖任何第三方SDK(目前发现很多依赖百度等第三方SDK,需要单独进行购买第三方服务或者授权,此插件承诺终身使用);
  • 6、返回结果内容丰富,支持:车牌号车牌颜色车牌抓拍图片
  • 7、支持车牌类型齐全;
  • 8、支持离线打包;
  • 9、可进行定制;

效果:

车牌实时识别
车牌实时识别-结果

支持车牌:

序号 车牌类型 是否支持
1 单行蓝牌
2 单行黄牌
3 新能源车牌
4 白色警用车牌
5 教练车牌
6 武警车牌
7 双层黄牌
8 双层武警
9 使馆车牌
10 港澳牌车
11 双层农用车牌
12 民航车牌
13 摩托车牌
14 危险品车牌

平台兼容性

平台 是否支持 支持版本 支持CPU类型
Android 5.0 - 13.0 + armeabi-v7a、arm64-v8a、x86
iOS ×

原生插件通用使用流程:

  • 1、购买插件,选择该插件绑定的项目;
  • 2、在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块,如需要填写参数则参考插件作者的文档添加;
  • 3、根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能;
  • 4、打包自定义基座,选择插件,得到自定义基座,然后运行时选择自定义基座,进行log输出测试;
  • 5、开发完毕后正式云打包;

目前插件市场所有付费原生插件均不支持离线打包,此插件支持离线打包!!!

  • Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/android
  • iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/ios

使用HBuilderX2.7.14以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提示包名绑定不一致时,需要在HBuilderX项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件重新选择;

使用说明

参考官网原生插件使用:
https://nativesupport.dcloud.net.cn/NativePlugin/use/use.html

使用步骤

  • 1、解压插件:

    解压插件zip包到uniapp项目目录nativePlugins中;

  • 2、引用插件:

    1) 点击manifest.json 进行配置;
    2) 选择指定的本地插件(自动识别):

  • 3、使用插件:

// 一行代码引用  
var plateModule = uni.requireNativePlugin("PlateModule")  

// 调用识别程序  
plateModule.startPlate(  
    {  
        'accuracy': 0.80, // 识别准确率(取值范围:0.0-1.0。准确率大于该值才返回结果,值越大识别越准确但也会越慢,需要测试出来最适合自己的准确率)  
        'quality': 80, // 图像压缩率(取值范围:0-100。 0:压缩100%,100:不压缩)  
        'showText': true // 是否显示提示文字  
    },  
    (ret) => {  
        console.log("showLPR result : ", ret);  
        modal.toast({  
            message: ret,  
            duration: 1.5  
        });  
        //解析  
        this.success = true;  
        if (ret.number) {  
            this.number = ret.number;  
        }  
        if (ret.color) {  
            this.color = ret.color;  
        }  
        if (ret.image) {  
            this.image = ret.image;  
            this.imagePath = "file:///" + ret.image;  
        }  

    }  
);  
  • 3、压缩体积教程:

将插件目录中文件lib-lpr-release.aar使用压缩工具打开,根据自己使用的Android平台进行保留jni目录下.so文件,即删除掉多余的平台目录;

目录结构:

├─ package.json  
├─ android  
│  ├── res  
│  │── libs  
│  │── assets  
│  │── uniplugin_lpr-release.aar  
│  └── lib-lpr-release.aar  
└─ ios

lib-lpr-release.aar文件压缩包中目录结构:

├─ AndroidManifest.xml  
├─ classes.jar  
├─ res  
├─ assets  
├─ jni  
│  │── armeabi-v7a  
│  │── arm64-v8a  
│  └── x86  
└─ios

举例:如果当前平台为armeabi-v7a,则只需要保留armeabi-v7a目录即可,其他同级目录arm64-v8ax86均可删除;

完整代码示例

<template>  
    <view class="button-sp-area">  
        <button type="primary" plain="true" @click="showLPR()">点击识别车牌</button>  
        <view style="margin-top: 20px; padding: 20px;" v-show="this.success == true">  
            <view style="text-align: center;color: lightslategray;">  
                <text>车牌号:{{number}}</text>  
            </view>  
            <view style="text-align: center;color: lightslategray;">  
                <text>车牌颜色:{{color}}</text>  
            </view>  
            <view style="text-align: center;color: lightslategray;">  
                <text>图片地址:{{image}}</text>  
            </view>  
            <view style="text-align: center;color: lightslategray;">  
                <image :src="imagePath"></image>  
            </view>  
        </view>  
    </view>  
</template>  

<script>  
    const modal = uni.requireNativePlugin('modal');  
    // 获取 module  
    var plateModule = uni.requireNativePlugin("PlateModule")  
    export default {  
        data() {  
            return {  
                success: false,  
                number: "",  
                color: "",  
                image: "",  
                imagePath: ""  
            }  
        },  
        methods: {  
            showLPR() {  
                console.log('showLPR...')  

                //带参数  
                plateModule.startPlate(  
                    {  
                        'accuracy': 0.80, // 识别准确率(取值范围:0.0-1.0。准确率大于该值才返回结果,值越大识别越准确但也会越慢,需要测试出来最适合自己的准确率)  
                        'quality': 80, // 图像压缩率(取值范围:0-100。 0:压缩100%,100:不压缩)  
                        'showText': true // 是否显示提示文字  
                    },  
                    (ret) => {  
                        console.log("showLPR result : ", ret);  
                        modal.toast({  
                            message: ret,  
                            duration: 1.5  
                        });  
                        //解析  
                        this.success = true;  
                        if (ret.number) {  
                            this.number = ret.number;  
                        }  
                        if (ret.color) {  
                            this.color = ret.color;  
                        }  
                        if (ret.image) {  
                            this.image = ret.image;  
                            this.imagePath = "file:///" + ret.image;  
                        }  

                    }  
                );  
            }  
        }  
    }  
</script>  

<style>  

</style>  
收起阅读 »

uni-upgrade-center升级中心性价比评测

uni_upgrade_center 升级中心 uniCloud

近期,uniCloud阿里云版开始正式商用,部分开发者对基于uniCloud的uni-upgrade-center等云端一体业务,开始纠结,不清楚这些业务预计会花费多少钱,不清楚相比传统服务器而言,何种方案性价比更好。

本文尝试算细账、算总账,以阿里云按量计费为例,详细预测uni-upgrade-center在不同用户规模下的资源消耗及对应费用,帮助大家明智选择,无忧开发。

本文主要分为三个部分:

  • uni-upgrade-center消耗的资源费用测算
  • uni-upgrade-center给你带来的收益
  • 综合考虑,你该如何选择

uni-upgrade-center 消耗的资源费用测算

uni-upgrade-center升级中心涉及费用的部分主要分为:

  • 云函数:uni-upgrade-center云函数,将客户端版本和服务端最新版本进行对比,返回是否需升级的逻辑
  • 云数据库:opendb-app-versions表,存储版本信息
  • 云存储:放置近期的升级包资源(apk/ipa/wgt)
  • 前端网站托管:部署uni-admin,管理员发布新版本

接下来,我们对不同资源,分别进行费用评估。

云函数

启用uni-upgrade-center升级中心后,你的App每次启动,会请求一次uni-upgrade-center云函数。

我们按照uniCloud官网列出的按量计费规则,计算一下云函数的资源消耗。

我们可以简单得出如下公式:

云函数费用 = 资源使用量 * 0.000110592 + 调用次数 * 0.0133 / 10000 + 出网流量 * 0.8

其中:

  • 资源使用量 = 云函数内存(单位为G) 云函数平均单次执行时长(单位为秒) 调用次数
  • 调用次数 = App日活 * 每日活用户平均每天启动App次数,因为App每次启动,均会执行检查更新逻辑

我们假设如下数据模型:

  • 云函数内存:256M,即0.25G;注意云函数内存默认为512M,uni-upgrade-center云函数建议设置为256M
  • 云函数平均单次执行时长:100毫秒,即0.1秒
  • 每日活用户平均每天启动App次数:2次
  • 出网流量:0,升级中心无需链接外网

按照如上公式,你的App若有100个日活用户,其升级中心云函数每天的费用为:

云函数费用(天) = 资源使用量 * 0.000110592  + 调用次数 * 0.0133 / 10000 + 出网流量 * 0.8  
              = 云函数内存(单位为G) * 云函数平均单次执行时长(单位为秒) * 调用次数 + 调用次数 * 0.0133 / 10000 + 出网流量 * 0.8  
              = 0.25G * 0.1S * 100 * 2 * 0.000110592 + 100 * 2 * 0.0133/10000 + 0   
              = 0.00081896(元)

即:你的App日活为100,使用uni-upgrade-center商业版后,对应云函数每天大概消耗0.00081896元。

据此,可计算其每月的费用为:0.00081896 * 30 = 0.0245688,即每月只需2分钱;

同理,我们可推导出日活为1000、10000、10万的App,其升级中心云函数每月费用如下表:

日活 资源使用量计费 调用次数计费 出网流量计费 合计
100 0.0165888 0.00798 0 0.0245688
1000 0.165888 0.0798 0 0.245688
10000 1.65888 0.798 0 2.45688
100000 16.5888 7.98 0 24.5688

日活1000的App,月度消耗才2毛钱,真是毛毛雨了。

云数据库

按照uniCloud官网介绍,云数据库费用 = 容量费用 + 读操作次数费用 + 写操作次数费用,其中:

  • 容量费用:数据库存储容量(单位为G) * 0.07
  • 读操作次数费用:读操作次数(万次) * 0.015
  • 写操作次数:写操作次数(万次) * 0.015;

容量费用

我们以hello uni-app为例,opendb-app-versions数据表中共存储30条升级记录,容量大小为8K。
据此可计算出opendb-app-versions表的日存储费用为:8/1024/1024 * 0.07 = 0.000000534

容量计费单位是G,故需先将8K折算成M,再折算成G,故上述公式中连续除了两个1024

1月按30天算,则月存储费用为0.000000534 * 30 = 0.000016,还不到1分钱,可忽略。

注意:数据库容量仅跟发布版本多少有关系,跟日活用户无关。

读操作次数

在uni升级中心业务中,云函数uni-upgrade-center每次执行,仅调用一次数据库读取(读取一次opendb-app-versions表),故数据库的读操作次数等同于云函数的调用次数,前文有过公式,云函数调用次数 = App日活 * 每日活用户平均每天启动App次数,每日活用户平均每天启动App次数我们假设为2次。

我们即可推算,如果一个App的日活为100,则uni升级中心每日云数据库读操作次数费用计算如下:

读操作次数费用 = 读操作次数(万次) * 0.015  
            = 云函数调用次数(万次) * 0.015  
            = App日活 * 每日活用户平均每天启动App次数 / 10000 * 0.015  
            = 100 * 2 / 10000 * 0.015  
            = 0.0003

1月按30天算,则每月云数据库读操作次数费用为0.0003 * 30 = 0.009,还不到1分钱。

同理,我们可推导出日活为1000、10000的App,其uni升级中心每月云数据库读操作次数费用为9分钱、9毛钱。

写操作次数

uni-upgrade-center升级中心,写数据库操作很少;管理员仅在每次发布新版时,通过uni-adminopendb-app-versions表插入一条新版本信息;用户端App每次启动检查升级,无需数据表的写入操作,故写操作次数可忽略为0;

小结

因为容量费和写操作次数费用均可忽略为0,根据公式:

云数据库费用 = 容量费(忽略为0) + 读操作费用 + 写操作费用(忽略为0)   
           = 读操作费用

可推导,uni升级中心的云数据库计费主要是读操作次数计费,因此我们进一步得出如下预测:

日活 容量费 读操作次数费用 写操作次数费用 合计
100 0 0.009 0 0.009
1000 0 0.09 0 0.09
10000 0 0.9 0 0.9
100000 0 9 0 9

云存储

按照uniCloud官网介绍,云存储费用 = 容量费 + 下载操作次数计费点 + 上传操作次数计费点 + CDN流量费

如果您的应用每次均上架到apple store或安卓各应用商店,升级时从应用商店下载安装,则云存储费用为0,因为使用的是应用商店的存储和CDN下载流量,本计费点测评章节可直接跳过。

uni-upgrade-center 支持设置应用新版安装包下载地址为应用商店地址,这样就可以使用应用商店的存储和CDN,不消耗uniCloud的云存储资源。

现阶段,iOS平台均需上架apple store,我们可以忽略iOS平台的云存储消耗。

如果您的安卓apk安装包及wgt差量升级包全部托管在uniCloud云存储中,我们也可以算算这笔账。

容量费

容量费主要是存储费用,我们可以定期将过期版本删除,从而节省容量费。

假设我们在云存储中保留最近5个版本的文件,apk/wgt全部保留,大小假设分别为:40M、10M。

如前所言,ipa需上架apple store,不使用云存储,测评可忽略。

则每天容量费用为:5 * (40+10)/1024 * 0.0043 = 0.0010498

据此,可计算其每月30天的容量费用为:0.0010498 * 30 = 0.031494,即只需3分钱;

注意:云存储容量仅跟保留的历史升级包多少有关系,跟日活用户无关。

下载操作次数计费点

下载操作次数计费点:仅触发文件下载时会触发,若无新版本下载,则不会触发。

假设你的App日活为100、月活为1500,每月发一次版本;月活用户中,50%会选择升级到新版本,我们可计算下载次数为:1500*50% = 750次

而云存储的下载操作次数计费规则为:每万次0.01元,即每万次下载1分钱,750次下载远还不到1分钱,故下载操作计费点可直接忽略。

上传操作次数计费点

每次App发版,仅需管理员上传一次新的资源包,用户App端检查升级时,不涉及上传操作,故上传操作次数计费点亦可忽略。

CDN流量费

CDN流量费:我们假设50%概率启用wgt资源包升级(升级包为10M),50%概率为整包升级;而整包升级中,20%为苹果用户(使用apple store流量),80%为安卓用户(升级包为40M)。

则按照如上数据模型,日活为100的App,假期其月活为1500,而月活用户中,50%会选择升级到新版本,即750人选择升级,不同升级包消耗CDN流量如下:

  • wgt资源包CDN流量:750 50% 10 / 1024 = 3.662G
  • 苹果整包升级CDN流量:使用apple store流量,uniCloud云存储流量为0
  • 安卓整包升级CDN流量:750 50% 80% * 40 /1024 = 11.719G

即:日活为100的App,月度CDN流量为:3.662 + 0 + 11.719 = 15.381G,对应费用则为:15.381 * 0.18 = 2.76858 (元)

同理,我们可推导出日活为1000的App,其升级中心云存储每月的CDN费用为27.6858元。

和传统 OSS + CDN 对比

如果你不用uni-upgrade-center,选择如阿里云的传统OSS + CDN 方案,同样按量计费的情况下,1PB流量以内,传统CDN都没有价格优势;传统CDN每GB的起步价为0.24元,而uniCloud云存储CDN每GB的费用为0.18元。

详见:阿里云官网CDN定价详情

1PB流量是什么概念?我们以每个安卓安装包为40M为例,需要 1 * 1024 * 1024 * 1024 / 40 = 26843546,即需要2600万人次安装包下载才能达到1PB流量,你可以评估一下你的App何时可以达到这个量级。

具体解释一下:1PB = 1024TB,1TB = 1024G,1G = 1024M,故上面公式连乘3个1024

也有人说了,购买阿里云CDN资源包可以更便宜。确实,购买大额资源包会更便宜,但这个方案有两个缺点:

  • 这个资源包仅仅是CDN流量包,你还需要购买OSS回源流量包,而uniCloud直接将回源流量费用包在CDN费用之内了,无需额外购买回源流量。
  • 预付费,在业务发展不明朗的情况下,一次性投入太多钱;一旦业务失败,CDN资源包未消耗完毕,也不能退款,浪费资金;而按量计费则没有这个问题,真实用多少资源,就花多少钱;

综合来看,uniCloud云存储相比传统云厂商的OSS + CDN 方案:

  • 都选择按量计费,uniCloud版CDN默认0.18元更具价格优势;
  • 预付费方式,选购云厂商CDN资源包,需额外购买回源流量包,对普通开发者,特别是中小开发者,并不友好,此时依然是uniCloud按量计费的云存储更具性价比。

前端网页托管

uni-upgrade-center需要和uni-admin配合使用,uni-admin需要部署在前端网页托管中。uni-admin主要是管理员使用,使用频次较少,流量也较低。

按照uniCloud官网介绍,前端网页托管费用 = 容量费 + 流量费

容量费

uni-admin编译后为4.7M,按照官网每GB每天0.0043元的规则,uni-admin的月度容量费为:4.7 / 1024 * 0.0043 * 30 = 0.00059,不到1分钱,可忽略。

流量费

管理员登录uni-admin,到升级中心管理页面浏览并发布新版,所需流量不超过3M,即使每月发布2次更新,流量费预估为:3 / 1024 * 0.18 * 2 = 0.00105,也不到1分钱,也可忽略。

合并总结

细项对比完了,我们来合并看看,使用uniCloud升级中心,到底需要花多少钱,相比传统自己研发升级逻辑、搭建升级中心,哪些地方都需要花钱,差异点在哪里?

不管是开发者自研的升级方案,还是uni-upgrade-center,存储+CDN的费用都是必需的,前文也将传统OSS+CDN和uniCloud云存储的性价比进行了对比,均按量计费的模式下,uniCloud更具性价比;以资源包方式购买传统CDN模式下,各有优劣。

既然两个方案,都绕不开云存储,那我们暂时抛开云存储对比(更建议走应用商店下载,这样完全没有CDN流量费),将其他各项按照日活用户规模罗列一下,看看uni-upgrade-center在其他维度所需费用。

日活 云函数 云数据库 云存储 前端网页托管 合计
100 0.0245688 0.009 忽略 0 0.0335688
1000 0.245688 0.09 忽略 0 0.335688
10000 2.45688 0.9 忽略 0 3.35688
100000 24.5688 9 忽略 0 33.5688

uni-upgrade-center 给你带来的收益

使用uni-upgrade-center,免费获取、一键安装,你将获得:

  • 经受大量App验证的、完备的检查升级逻辑,同时支持整包/资源包升级,支持静默升级,支持强制升级;
  • 完备的管理功能,分平台发布新版、下线老版,关联应用商店,分渠道发布等。
  • 代码开源,随意定制

如上功能,如果你使用传统模式自研,需要前后端配合开发,后端使用php/java做接口,前端发起Ajax请求,处理服务端的各种响应和错误码,处理升级弹窗提醒,这些功能做完善至少需要4个工作日。

假设工程师月薪18K,社保等综合管理成本是薪资的1.4倍,则4个工作日的综合成本为:18*1000*1.4/22 * 4 = 4582元

总结

再次说回uni-upgrade-center,相比传统方式自研升级中心,存储+CDN的钱都是要花的,我们忽略它。

其它云函数、云数据库等,虽然看起来是额外增加的费用,但实际上你使用传统php/java自研升级逻辑,除了自研人力费用,后期也是需要消耗CPU、内存、带宽资源的,只是这些费用合并到虚拟机的整体租用成本中,你无法拆出来计算罢了。

再看回刚才的计算表,以1000日活用户来说,云函数、云数据库每月才多了0.34元,每年才多了4块钱(不考虑云存储CDN的情况下),一年多花4块钱,可以省掉自研的4500多元人工费用,可以让工程师将更多精力投入核心业务中。这5块钱的买卖,不划算吗?它不香吗?

日活 云函数 云数据库 云存储 前端网页托管 合计
100 0.0245688 0.009 忽略 0 0.0335688
1000 0.245688 0.09 忽略 0 0.335688
10000 2.45688 0.9 忽略 0 3.35688
100000 24.5688 9 忽略 0 33.5688

不重复制造轮子,聚焦业务,快速验证模式,实现商业增长,才应该是聪明工程师的追求。

本篇评测共大家参考。

继续阅读 »

近期,uniCloud阿里云版开始正式商用,部分开发者对基于uniCloud的uni-upgrade-center等云端一体业务,开始纠结,不清楚这些业务预计会花费多少钱,不清楚相比传统服务器而言,何种方案性价比更好。

本文尝试算细账、算总账,以阿里云按量计费为例,详细预测uni-upgrade-center在不同用户规模下的资源消耗及对应费用,帮助大家明智选择,无忧开发。

本文主要分为三个部分:

  • uni-upgrade-center消耗的资源费用测算
  • uni-upgrade-center给你带来的收益
  • 综合考虑,你该如何选择

uni-upgrade-center 消耗的资源费用测算

uni-upgrade-center升级中心涉及费用的部分主要分为:

  • 云函数:uni-upgrade-center云函数,将客户端版本和服务端最新版本进行对比,返回是否需升级的逻辑
  • 云数据库:opendb-app-versions表,存储版本信息
  • 云存储:放置近期的升级包资源(apk/ipa/wgt)
  • 前端网站托管:部署uni-admin,管理员发布新版本

接下来,我们对不同资源,分别进行费用评估。

云函数

启用uni-upgrade-center升级中心后,你的App每次启动,会请求一次uni-upgrade-center云函数。

我们按照uniCloud官网列出的按量计费规则,计算一下云函数的资源消耗。

我们可以简单得出如下公式:

云函数费用 = 资源使用量 * 0.000110592 + 调用次数 * 0.0133 / 10000 + 出网流量 * 0.8

其中:

  • 资源使用量 = 云函数内存(单位为G) 云函数平均单次执行时长(单位为秒) 调用次数
  • 调用次数 = App日活 * 每日活用户平均每天启动App次数,因为App每次启动,均会执行检查更新逻辑

我们假设如下数据模型:

  • 云函数内存:256M,即0.25G;注意云函数内存默认为512M,uni-upgrade-center云函数建议设置为256M
  • 云函数平均单次执行时长:100毫秒,即0.1秒
  • 每日活用户平均每天启动App次数:2次
  • 出网流量:0,升级中心无需链接外网

按照如上公式,你的App若有100个日活用户,其升级中心云函数每天的费用为:

云函数费用(天) = 资源使用量 * 0.000110592  + 调用次数 * 0.0133 / 10000 + 出网流量 * 0.8  
              = 云函数内存(单位为G) * 云函数平均单次执行时长(单位为秒) * 调用次数 + 调用次数 * 0.0133 / 10000 + 出网流量 * 0.8  
              = 0.25G * 0.1S * 100 * 2 * 0.000110592 + 100 * 2 * 0.0133/10000 + 0   
              = 0.00081896(元)

即:你的App日活为100,使用uni-upgrade-center商业版后,对应云函数每天大概消耗0.00081896元。

据此,可计算其每月的费用为:0.00081896 * 30 = 0.0245688,即每月只需2分钱;

同理,我们可推导出日活为1000、10000、10万的App,其升级中心云函数每月费用如下表:

日活 资源使用量计费 调用次数计费 出网流量计费 合计
100 0.0165888 0.00798 0 0.0245688
1000 0.165888 0.0798 0 0.245688
10000 1.65888 0.798 0 2.45688
100000 16.5888 7.98 0 24.5688

日活1000的App,月度消耗才2毛钱,真是毛毛雨了。

云数据库

按照uniCloud官网介绍,云数据库费用 = 容量费用 + 读操作次数费用 + 写操作次数费用,其中:

  • 容量费用:数据库存储容量(单位为G) * 0.07
  • 读操作次数费用:读操作次数(万次) * 0.015
  • 写操作次数:写操作次数(万次) * 0.015;

容量费用

我们以hello uni-app为例,opendb-app-versions数据表中共存储30条升级记录,容量大小为8K。
据此可计算出opendb-app-versions表的日存储费用为:8/1024/1024 * 0.07 = 0.000000534

容量计费单位是G,故需先将8K折算成M,再折算成G,故上述公式中连续除了两个1024

1月按30天算,则月存储费用为0.000000534 * 30 = 0.000016,还不到1分钱,可忽略。

注意:数据库容量仅跟发布版本多少有关系,跟日活用户无关。

读操作次数

在uni升级中心业务中,云函数uni-upgrade-center每次执行,仅调用一次数据库读取(读取一次opendb-app-versions表),故数据库的读操作次数等同于云函数的调用次数,前文有过公式,云函数调用次数 = App日活 * 每日活用户平均每天启动App次数,每日活用户平均每天启动App次数我们假设为2次。

我们即可推算,如果一个App的日活为100,则uni升级中心每日云数据库读操作次数费用计算如下:

读操作次数费用 = 读操作次数(万次) * 0.015  
            = 云函数调用次数(万次) * 0.015  
            = App日活 * 每日活用户平均每天启动App次数 / 10000 * 0.015  
            = 100 * 2 / 10000 * 0.015  
            = 0.0003

1月按30天算,则每月云数据库读操作次数费用为0.0003 * 30 = 0.009,还不到1分钱。

同理,我们可推导出日活为1000、10000的App,其uni升级中心每月云数据库读操作次数费用为9分钱、9毛钱。

写操作次数

uni-upgrade-center升级中心,写数据库操作很少;管理员仅在每次发布新版时,通过uni-adminopendb-app-versions表插入一条新版本信息;用户端App每次启动检查升级,无需数据表的写入操作,故写操作次数可忽略为0;

小结

因为容量费和写操作次数费用均可忽略为0,根据公式:

云数据库费用 = 容量费(忽略为0) + 读操作费用 + 写操作费用(忽略为0)   
           = 读操作费用

可推导,uni升级中心的云数据库计费主要是读操作次数计费,因此我们进一步得出如下预测:

日活 容量费 读操作次数费用 写操作次数费用 合计
100 0 0.009 0 0.009
1000 0 0.09 0 0.09
10000 0 0.9 0 0.9
100000 0 9 0 9

云存储

按照uniCloud官网介绍,云存储费用 = 容量费 + 下载操作次数计费点 + 上传操作次数计费点 + CDN流量费

如果您的应用每次均上架到apple store或安卓各应用商店,升级时从应用商店下载安装,则云存储费用为0,因为使用的是应用商店的存储和CDN下载流量,本计费点测评章节可直接跳过。

uni-upgrade-center 支持设置应用新版安装包下载地址为应用商店地址,这样就可以使用应用商店的存储和CDN,不消耗uniCloud的云存储资源。

现阶段,iOS平台均需上架apple store,我们可以忽略iOS平台的云存储消耗。

如果您的安卓apk安装包及wgt差量升级包全部托管在uniCloud云存储中,我们也可以算算这笔账。

容量费

容量费主要是存储费用,我们可以定期将过期版本删除,从而节省容量费。

假设我们在云存储中保留最近5个版本的文件,apk/wgt全部保留,大小假设分别为:40M、10M。

如前所言,ipa需上架apple store,不使用云存储,测评可忽略。

则每天容量费用为:5 * (40+10)/1024 * 0.0043 = 0.0010498

据此,可计算其每月30天的容量费用为:0.0010498 * 30 = 0.031494,即只需3分钱;

注意:云存储容量仅跟保留的历史升级包多少有关系,跟日活用户无关。

下载操作次数计费点

下载操作次数计费点:仅触发文件下载时会触发,若无新版本下载,则不会触发。

假设你的App日活为100、月活为1500,每月发一次版本;月活用户中,50%会选择升级到新版本,我们可计算下载次数为:1500*50% = 750次

而云存储的下载操作次数计费规则为:每万次0.01元,即每万次下载1分钱,750次下载远还不到1分钱,故下载操作计费点可直接忽略。

上传操作次数计费点

每次App发版,仅需管理员上传一次新的资源包,用户App端检查升级时,不涉及上传操作,故上传操作次数计费点亦可忽略。

CDN流量费

CDN流量费:我们假设50%概率启用wgt资源包升级(升级包为10M),50%概率为整包升级;而整包升级中,20%为苹果用户(使用apple store流量),80%为安卓用户(升级包为40M)。

则按照如上数据模型,日活为100的App,假期其月活为1500,而月活用户中,50%会选择升级到新版本,即750人选择升级,不同升级包消耗CDN流量如下:

  • wgt资源包CDN流量:750 50% 10 / 1024 = 3.662G
  • 苹果整包升级CDN流量:使用apple store流量,uniCloud云存储流量为0
  • 安卓整包升级CDN流量:750 50% 80% * 40 /1024 = 11.719G

即:日活为100的App,月度CDN流量为:3.662 + 0 + 11.719 = 15.381G,对应费用则为:15.381 * 0.18 = 2.76858 (元)

同理,我们可推导出日活为1000的App,其升级中心云存储每月的CDN费用为27.6858元。

和传统 OSS + CDN 对比

如果你不用uni-upgrade-center,选择如阿里云的传统OSS + CDN 方案,同样按量计费的情况下,1PB流量以内,传统CDN都没有价格优势;传统CDN每GB的起步价为0.24元,而uniCloud云存储CDN每GB的费用为0.18元。

详见:阿里云官网CDN定价详情

1PB流量是什么概念?我们以每个安卓安装包为40M为例,需要 1 * 1024 * 1024 * 1024 / 40 = 26843546,即需要2600万人次安装包下载才能达到1PB流量,你可以评估一下你的App何时可以达到这个量级。

具体解释一下:1PB = 1024TB,1TB = 1024G,1G = 1024M,故上面公式连乘3个1024

也有人说了,购买阿里云CDN资源包可以更便宜。确实,购买大额资源包会更便宜,但这个方案有两个缺点:

  • 这个资源包仅仅是CDN流量包,你还需要购买OSS回源流量包,而uniCloud直接将回源流量费用包在CDN费用之内了,无需额外购买回源流量。
  • 预付费,在业务发展不明朗的情况下,一次性投入太多钱;一旦业务失败,CDN资源包未消耗完毕,也不能退款,浪费资金;而按量计费则没有这个问题,真实用多少资源,就花多少钱;

综合来看,uniCloud云存储相比传统云厂商的OSS + CDN 方案:

  • 都选择按量计费,uniCloud版CDN默认0.18元更具价格优势;
  • 预付费方式,选购云厂商CDN资源包,需额外购买回源流量包,对普通开发者,特别是中小开发者,并不友好,此时依然是uniCloud按量计费的云存储更具性价比。

前端网页托管

uni-upgrade-center需要和uni-admin配合使用,uni-admin需要部署在前端网页托管中。uni-admin主要是管理员使用,使用频次较少,流量也较低。

按照uniCloud官网介绍,前端网页托管费用 = 容量费 + 流量费

容量费

uni-admin编译后为4.7M,按照官网每GB每天0.0043元的规则,uni-admin的月度容量费为:4.7 / 1024 * 0.0043 * 30 = 0.00059,不到1分钱,可忽略。

流量费

管理员登录uni-admin,到升级中心管理页面浏览并发布新版,所需流量不超过3M,即使每月发布2次更新,流量费预估为:3 / 1024 * 0.18 * 2 = 0.00105,也不到1分钱,也可忽略。

合并总结

细项对比完了,我们来合并看看,使用uniCloud升级中心,到底需要花多少钱,相比传统自己研发升级逻辑、搭建升级中心,哪些地方都需要花钱,差异点在哪里?

不管是开发者自研的升级方案,还是uni-upgrade-center,存储+CDN的费用都是必需的,前文也将传统OSS+CDN和uniCloud云存储的性价比进行了对比,均按量计费的模式下,uniCloud更具性价比;以资源包方式购买传统CDN模式下,各有优劣。

既然两个方案,都绕不开云存储,那我们暂时抛开云存储对比(更建议走应用商店下载,这样完全没有CDN流量费),将其他各项按照日活用户规模罗列一下,看看uni-upgrade-center在其他维度所需费用。

日活 云函数 云数据库 云存储 前端网页托管 合计
100 0.0245688 0.009 忽略 0 0.0335688
1000 0.245688 0.09 忽略 0 0.335688
10000 2.45688 0.9 忽略 0 3.35688
100000 24.5688 9 忽略 0 33.5688

uni-upgrade-center 给你带来的收益

使用uni-upgrade-center,免费获取、一键安装,你将获得:

  • 经受大量App验证的、完备的检查升级逻辑,同时支持整包/资源包升级,支持静默升级,支持强制升级;
  • 完备的管理功能,分平台发布新版、下线老版,关联应用商店,分渠道发布等。
  • 代码开源,随意定制

如上功能,如果你使用传统模式自研,需要前后端配合开发,后端使用php/java做接口,前端发起Ajax请求,处理服务端的各种响应和错误码,处理升级弹窗提醒,这些功能做完善至少需要4个工作日。

假设工程师月薪18K,社保等综合管理成本是薪资的1.4倍,则4个工作日的综合成本为:18*1000*1.4/22 * 4 = 4582元

总结

再次说回uni-upgrade-center,相比传统方式自研升级中心,存储+CDN的钱都是要花的,我们忽略它。

其它云函数、云数据库等,虽然看起来是额外增加的费用,但实际上你使用传统php/java自研升级逻辑,除了自研人力费用,后期也是需要消耗CPU、内存、带宽资源的,只是这些费用合并到虚拟机的整体租用成本中,你无法拆出来计算罢了。

再看回刚才的计算表,以1000日活用户来说,云函数、云数据库每月才多了0.34元,每年才多了4块钱(不考虑云存储CDN的情况下),一年多花4块钱,可以省掉自研的4500多元人工费用,可以让工程师将更多精力投入核心业务中。这5块钱的买卖,不划算吗?它不香吗?

日活 云函数 云数据库 云存储 前端网页托管 合计
100 0.0245688 0.009 忽略 0 0.0335688
1000 0.245688 0.09 忽略 0 0.335688
10000 2.45688 0.9 忽略 0 3.35688
100000 24.5688 9 忽略 0 33.5688

不重复制造轮子,聚焦业务,快速验证模式,实现商业增长,才应该是聪明工程师的追求。

本篇评测共大家参考。

收起阅读 »

可以添加一个sumup支付嘛?

现在 在使用sumup支付。可以添加一个sumup支付嘛? 不然好不方便

现在 在使用sumup支付。可以添加一个sumup支付嘛? 不然好不方便

uni-app运行微信小程序无法启动? Enable IDE Service (y/N) 

uni小程序

手动开启微信小程序开发工具 -> 设置 -> 安全 -> 打开服务端口

手动开启微信小程序开发工具 -> 设置 -> 安全 -> 打开服务端口

请问使用5+app中的plus.android.importClass('android.media.AudioRecord');引入对象后,调用对象的 read 方法一直返回null是怎么回事呢?

5+App开发 Native.JS html5plus

请问使用5+app中的plus.android.importClass('android.media.AudioRecord');引入对象后,调用对象的 read() 方法一直返回null是怎么回事呢?
在调用对象的 read() 方法之前已经实例化AudioRecord,并调用了 startRecording() 方法,请各位大佬赐教

继续阅读 »

请问使用5+app中的plus.android.importClass('android.media.AudioRecord');引入对象后,调用对象的 read() 方法一直返回null是怎么回事呢?
在调用对象的 read() 方法之前已经实例化AudioRecord,并调用了 startRecording() 方法,请各位大佬赐教

收起阅读 »

有人可以帮我点点小程序吗,还没破1000

微信小程序

兄弟们有人点点不

兄弟们有人点点不

uniapp 打包离线android

vue_cli

记录一下初入手uniapp,已经踩过的坑。
使用vue-cli 作为新建项目以及打包,方便自动构建。

使用官方教程模板,dcloudio/uni-preset-vue。很快项目就新建好了。然后问题就来了。

模板中的依赖是有问题的:

"@vue/cli-plugin-babel": "^5.0.8",  
"@vue/cli-service": "^5.0.8",  

解决方式:
手动锁定版本,本人用的是VUE2,需要把: “^2.0.2-3061520221228001”改为“2.0.2-3061520221228001”。
修改:
"@vue/shared": "~3.0.0",
"@vue/cli-plugin-babel": "~4.5.19",
"@vue/cli-service": "~4.5.19",
建议把所有版本锁定为小版本更新,UNIAPP的依赖直接锁定版本。因为UNIAPP经常有更新,更新后导致项目跑不起。只能干着急的在网上求助。

最后建议,转向其他框架它不香吗?Taro, RN, ionic, 起码不会让你写个构建脚本花个半天找问题。而且人家才是真正的开源,不需要在什么平台绑定什么KEY,说不定什么时候KEY就要收费了,cli 也只能用IDE 里的。尽早离坑,都是VUE,运行速度更快,插件更多下载量也大,不安心吗?

继续阅读 »

记录一下初入手uniapp,已经踩过的坑。
使用vue-cli 作为新建项目以及打包,方便自动构建。

使用官方教程模板,dcloudio/uni-preset-vue。很快项目就新建好了。然后问题就来了。

模板中的依赖是有问题的:

"@vue/cli-plugin-babel": "^5.0.8",  
"@vue/cli-service": "^5.0.8",  

解决方式:
手动锁定版本,本人用的是VUE2,需要把: “^2.0.2-3061520221228001”改为“2.0.2-3061520221228001”。
修改:
"@vue/shared": "~3.0.0",
"@vue/cli-plugin-babel": "~4.5.19",
"@vue/cli-service": "~4.5.19",
建议把所有版本锁定为小版本更新,UNIAPP的依赖直接锁定版本。因为UNIAPP经常有更新,更新后导致项目跑不起。只能干着急的在网上求助。

最后建议,转向其他框架它不香吗?Taro, RN, ionic, 起码不会让你写个构建脚本花个半天找问题。而且人家才是真正的开源,不需要在什么平台绑定什么KEY,说不定什么时候KEY就要收费了,cli 也只能用IDE 里的。尽早离坑,都是VUE,运行速度更快,插件更多下载量也大,不安心吗?

收起阅读 »

个推支持小程序消息推送,助力开发者实现用户高触达、高转化

消息推送 微信小程序

随着小程序技术和应用场景的不断完善,越来越多的开发者搭建了小程序平台,为用户带来更“轻量”的服务。在小程序用户迅猛增长的同时,开发者对于小程序用户精细化触达的需求也愈加强烈。近日,个推消息推送上线了小程序推送功能,帮助开发者高效地连接小程序用户群体,提升用户活跃、留存和转化。

个推小程序推送提供功能完善、集成简单、使用方便的SDK解决方案,满足小程序开发者多渠道、多互动场景下的用户连接需求。通过个推小程序推送的在线+离线组合推送策略,开发者既可以在小程序在线时下发消息,实现消息毫秒级送达,也可以通过“离线模板消息”的形式对用户进行触达,最大化提升运营效果。在提高用户触达“量”的同时,个推小程序推送也支持开发者结合实际业务场景自助创建用户标签,实现精细化人群洞察、圈选、触达,提升用户触达的“质”。

此外,个推小程序推送还提供“模板管理”能力,帮助开发者高效管理小程序模板消息,优化消息转化内容与路径,让用户一站式完成内容的获取和消费,形成转化闭环。

除了小程序外,个推消息推送还高效整合了APP、Web、H5、短信等多推送渠道,并提供消息多渠道并发、分发、补发策略以及多维度的数据统计报表,帮助开发者实现多渠道灵活组合推送,提升整体运营能力。

作为国内移动推送领域的早期进入者,个推十余年来持续专注推送技术的创新与实践,帮助开发者挖掘更广阔的增长空间。比如,个推在与华为、小米、OPPO、vivo、魅族等厂商合作的基础上,今年又与荣耀达成合作,进一步加强个推消息推送的厂商推送能力,提升消息到达率。同时,为了帮助开发者高效开拓海外市场,个推推出了海外消息推送解决方案,高效整合海外消息通道,促进APP海外业务快速增长。

在新技术、新玩法、新场景不断涌现的当下,个推还将持续深耕行业应用实践、优化产品技术能力,帮助更多开发者实现与用户多平台、场景化的互动沟通,共同推动移动互联网领域创新发展。

继续阅读 »

随着小程序技术和应用场景的不断完善,越来越多的开发者搭建了小程序平台,为用户带来更“轻量”的服务。在小程序用户迅猛增长的同时,开发者对于小程序用户精细化触达的需求也愈加强烈。近日,个推消息推送上线了小程序推送功能,帮助开发者高效地连接小程序用户群体,提升用户活跃、留存和转化。

个推小程序推送提供功能完善、集成简单、使用方便的SDK解决方案,满足小程序开发者多渠道、多互动场景下的用户连接需求。通过个推小程序推送的在线+离线组合推送策略,开发者既可以在小程序在线时下发消息,实现消息毫秒级送达,也可以通过“离线模板消息”的形式对用户进行触达,最大化提升运营效果。在提高用户触达“量”的同时,个推小程序推送也支持开发者结合实际业务场景自助创建用户标签,实现精细化人群洞察、圈选、触达,提升用户触达的“质”。

此外,个推小程序推送还提供“模板管理”能力,帮助开发者高效管理小程序模板消息,优化消息转化内容与路径,让用户一站式完成内容的获取和消费,形成转化闭环。

除了小程序外,个推消息推送还高效整合了APP、Web、H5、短信等多推送渠道,并提供消息多渠道并发、分发、补发策略以及多维度的数据统计报表,帮助开发者实现多渠道灵活组合推送,提升整体运营能力。

作为国内移动推送领域的早期进入者,个推十余年来持续专注推送技术的创新与实践,帮助开发者挖掘更广阔的增长空间。比如,个推在与华为、小米、OPPO、vivo、魅族等厂商合作的基础上,今年又与荣耀达成合作,进一步加强个推消息推送的厂商推送能力,提升消息到达率。同时,为了帮助开发者高效开拓海外市场,个推推出了海外消息推送解决方案,高效整合海外消息通道,促进APP海外业务快速增长。

在新技术、新玩法、新场景不断涌现的当下,个推还将持续深耕行业应用实践、优化产品技术能力,帮助更多开发者实现与用户多平台、场景化的互动沟通,共同推动移动互联网领域创新发展。

收起阅读 »