HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

低功耗蓝牙-安卓版插件

已经使用过一段时间Dcloud公司提供的这套跨平台框架,总体上还是比较喜欢的。  
在这里也是感谢Dcloud公司的奉献。今天也是准备尽一点绵薄之力,贡献出这段时间自己开发的一个蓝牙通信的安卓版插件。写的不好请勿喷,欢迎交流。刚好今天是我的生日,Happy Birthday to myself !哈哈  

进入正题,低功耗蓝牙的通信大致分为三个过程。搜索--》连接--》进行通信。因为也是刚接触蓝牙这个方面,如有理解片面或者不对的地方,还请指正。此处以我方设备的连接过程为例进行讲解。在搜索到蓝牙设备后,需要进行连接(mBluetoothDevice.connectGatt),连接成功后,需要进行一个口令认证,认证成功后,方可继续进行和设备的交互。在连接上蓝牙设备后一定时间内未认证通过,蓝牙设备将自动断开。  

上代码:
JavaScript部分:
我是结合了vue的一些写法,方法体写在了vue的methods中,主要有onStartSearch、onBluetoothConnect、onBluetoothAuth等。
与原始交互方面主要用到了
plus.pluginBLE.PluginInitBle,
plus.pluginBLE.PluginStartSearchBle,
plus.pluginBLE.PluginStopSearchBle,
plus.pluginBLE.PluginConnectBle,
plus.pluginBLE.PluginBleAuth等方法。
这些的方法可见demo工程中PluginBLE.js以及对应BLEPlugin.java文件。

methods: {  
            onStopSearch: function () {  
                var that = this;  
                console.log('onstop');  
                plus.pluginBLE.PluginStopSearchBle(function (aData) {  
                  //停止搜索,命令调用成功后,执行以下逻辑  
                });  
            },  
            onStartSearch: function () {  
                var that = this;  
                console.log('startDiscovery');  
                plus.pluginBLE.PluginInitBle(function (aData) {  
                //初始化一些变量,初始化成功后执行以下逻辑  
                    if (aData.Result == 200) {  
                        that.searching = true;  
                        mui.toast('蓝牙搜索初始化成功,开始搜索');  
                        plus.pluginBLE.PluginStartSearchBle(function (bData) {  
                           //搜索到的设备在这里  
                        }, function (eData) {  
                                mui.toast(eData.Description);  
                        });  
                    }  
                }, function (eData) {  
                        mui.toast(eData.Description);  
                });  
            },  
            onBluetoothConnect: function (item) {  
                var that = this;  
                that.onStopSearch();  
                plus.nativeUI.showWaiting("蓝牙连接中...");  
                plus.pluginBLE.PluginConnectBle(item.bleAddress, function (aData) {  
                    //连接成功  
                    plus.nativeUI.closeWaiting();  
                        that.onBluetoothAuth();  
                }, function (eData) {  
                    //连接失败  
                    plus.nativeUI.closeWaiting();  
                    mui.toast(eData.Description);  

                });  
            },  
            onBluetoothReconnect: function () {  
                this.onBluetoothConnect(this.bluetoothDevice);  
            },  
            onBluetoothAuth: function () {  
                var that = this;  
                plus.nativeUI.showWaiting("连接成功,身份信息验证中...");  
                plus.pluginBLE.PluginBleAuth(function (aData) {  
                    plus.nativeUI.closeWaiting();  
                    mui.toast('认证成功,开始交互');  

                },function (eData) {  
                    plus.nativeUI.closeWaiting();  
                    mui.toast("认证失败,请重试");  
                });  
            },  

            onDisconnectBluetoothTap:function(){  
                var that=this;  
                plus.pluginBLE.PluginDisconnectBle(function (aData) {  

                    // mui.toast('设备已断开');  
                });  
            },  
            onCompleteTap: function () {  
                var that=this;  

            },  
            onRetryTap: function () {  
                that.retryFlag = false;  

            },

以上是Html5展示界面的逻辑。看的可能会比较生硬晦涩。来几张图看看效果。

再来一张硬件照,露个脸O(∩_∩)O哈哈~

java插件层,和jsbridge层直接交互的代码在BLEPlugin.java 中,方法名称也是一一对应起来的。便于大家查看。
低功耗蓝牙交互的过程,需要使用到每个特征值的UUID,这个在开发过程中可以找硬件工程师提供。或者通过一款叫做nRF Connect 的软件进行查看。java层的代码也是在github上找到的,站在巨人的肩膀上^^,懂安卓原生开发的朋友,可以直接借鉴这部分的代码。地址奉上:https://github.com/0xsunsama/Android_ble

没怎么写个,感觉写得好烂。不过话又说回来。烂葱不烂味,哈哈,希望能对有需要的朋友有所帮助。
最后,毕竟项目涉及到一些公司机密,所以对项目有删减。这个就存粹的作为一个demo了。

继续阅读 »
已经使用过一段时间Dcloud公司提供的这套跨平台框架,总体上还是比较喜欢的。  
在这里也是感谢Dcloud公司的奉献。今天也是准备尽一点绵薄之力,贡献出这段时间自己开发的一个蓝牙通信的安卓版插件。写的不好请勿喷,欢迎交流。刚好今天是我的生日,Happy Birthday to myself !哈哈  

进入正题,低功耗蓝牙的通信大致分为三个过程。搜索--》连接--》进行通信。因为也是刚接触蓝牙这个方面,如有理解片面或者不对的地方,还请指正。此处以我方设备的连接过程为例进行讲解。在搜索到蓝牙设备后,需要进行连接(mBluetoothDevice.connectGatt),连接成功后,需要进行一个口令认证,认证成功后,方可继续进行和设备的交互。在连接上蓝牙设备后一定时间内未认证通过,蓝牙设备将自动断开。  

上代码:
JavaScript部分:
我是结合了vue的一些写法,方法体写在了vue的methods中,主要有onStartSearch、onBluetoothConnect、onBluetoothAuth等。
与原始交互方面主要用到了
plus.pluginBLE.PluginInitBle,
plus.pluginBLE.PluginStartSearchBle,
plus.pluginBLE.PluginStopSearchBle,
plus.pluginBLE.PluginConnectBle,
plus.pluginBLE.PluginBleAuth等方法。
这些的方法可见demo工程中PluginBLE.js以及对应BLEPlugin.java文件。

methods: {  
            onStopSearch: function () {  
                var that = this;  
                console.log('onstop');  
                plus.pluginBLE.PluginStopSearchBle(function (aData) {  
                  //停止搜索,命令调用成功后,执行以下逻辑  
                });  
            },  
            onStartSearch: function () {  
                var that = this;  
                console.log('startDiscovery');  
                plus.pluginBLE.PluginInitBle(function (aData) {  
                //初始化一些变量,初始化成功后执行以下逻辑  
                    if (aData.Result == 200) {  
                        that.searching = true;  
                        mui.toast('蓝牙搜索初始化成功,开始搜索');  
                        plus.pluginBLE.PluginStartSearchBle(function (bData) {  
                           //搜索到的设备在这里  
                        }, function (eData) {  
                                mui.toast(eData.Description);  
                        });  
                    }  
                }, function (eData) {  
                        mui.toast(eData.Description);  
                });  
            },  
            onBluetoothConnect: function (item) {  
                var that = this;  
                that.onStopSearch();  
                plus.nativeUI.showWaiting("蓝牙连接中...");  
                plus.pluginBLE.PluginConnectBle(item.bleAddress, function (aData) {  
                    //连接成功  
                    plus.nativeUI.closeWaiting();  
                        that.onBluetoothAuth();  
                }, function (eData) {  
                    //连接失败  
                    plus.nativeUI.closeWaiting();  
                    mui.toast(eData.Description);  

                });  
            },  
            onBluetoothReconnect: function () {  
                this.onBluetoothConnect(this.bluetoothDevice);  
            },  
            onBluetoothAuth: function () {  
                var that = this;  
                plus.nativeUI.showWaiting("连接成功,身份信息验证中...");  
                plus.pluginBLE.PluginBleAuth(function (aData) {  
                    plus.nativeUI.closeWaiting();  
                    mui.toast('认证成功,开始交互');  

                },function (eData) {  
                    plus.nativeUI.closeWaiting();  
                    mui.toast("认证失败,请重试");  
                });  
            },  

            onDisconnectBluetoothTap:function(){  
                var that=this;  
                plus.pluginBLE.PluginDisconnectBle(function (aData) {  

                    // mui.toast('设备已断开');  
                });  
            },  
            onCompleteTap: function () {  
                var that=this;  

            },  
            onRetryTap: function () {  
                that.retryFlag = false;  

            },

以上是Html5展示界面的逻辑。看的可能会比较生硬晦涩。来几张图看看效果。

再来一张硬件照,露个脸O(∩_∩)O哈哈~

java插件层,和jsbridge层直接交互的代码在BLEPlugin.java 中,方法名称也是一一对应起来的。便于大家查看。
低功耗蓝牙交互的过程,需要使用到每个特征值的UUID,这个在开发过程中可以找硬件工程师提供。或者通过一款叫做nRF Connect 的软件进行查看。java层的代码也是在github上找到的,站在巨人的肩膀上^^,懂安卓原生开发的朋友,可以直接借鉴这部分的代码。地址奉上:https://github.com/0xsunsama/Android_ble

没怎么写个,感觉写得好烂。不过话又说回来。烂葱不烂味,哈哈,希望能对有需要的朋友有所帮助。
最后,毕竟项目涉及到一些公司机密,所以对项目有删减。这个就存粹的作为一个demo了。

收起阅读 »

版本更新后编译失败【已解决,需要删除unpackage目录的编译缓存】

更新

更新前运行还好好的,更新完就成这样了,求解决方法啊??

更新前运行还好好的,更新完就成这样了,求解决方法啊??

关于uni-app原生tabbar的字体问题

tabbar uniapp

为什么app端的原生tabbar字体大小比小程序和H5端都要大两号呢?已经提过很多次这个字号大小的问题了,官方就是视而不见,是APP端改不了还是就是故意弄这么大字体呢?一个端一个样,觉得这样子无所谓么?真是无语了。

继续阅读 »

为什么app端的原生tabbar字体大小比小程序和H5端都要大两号呢?已经提过很多次这个字号大小的问题了,官方就是视而不见,是APP端改不了还是就是故意弄这么大字体呢?一个端一个样,觉得这样子无所谓么?真是无语了。

收起阅读 »

HBuilderX1.2.0的app中manifest的延迟关闭splash设置时间报错的临时方法

HBuilderX升级

此文已过期,请遇到问题的用户升级HBuilderX 1.2.1解决。

============以下为过期内容===============
需要在manifest源码视图里,将splashscreen节点下的delay,后面设为"1000"(或你需要的数字),注意需要加引号,然后保存。

后续会提供升级补丁。
后续升级后需要恢复为正常数字。

抱歉给大家带来麻烦。

继续阅读 »

此文已过期,请遇到问题的用户升级HBuilderX 1.2.1解决。

============以下为过期内容===============
需要在manifest源码视图里,将splashscreen节点下的delay,后面设为"1000"(或你需要的数字),注意需要加引号,然后保存。

后续会提供升级补丁。
后续升级后需要恢复为正常数字。

抱歉给大家带来麻烦。

收起阅读 »

HBuilderX升级时无限重启的临时解决方法

HBuilderX升级

原因是升级包下载后无法覆盖到HBuilderX所在的目录,一般是权限问题或目录文件占用问题。

  1. 需要以管理员身份启动HBuilderX。
  2. 需要关掉HBuilderX,在任务管理器里杀掉node.js、adb相关进程。或者重启电脑。杀掉这些进程后启动HBuilderX不要运行应用,直接升级。

后续版本会解决这个问题。

继续阅读 »

原因是升级包下载后无法覆盖到HBuilderX所在的目录,一般是权限问题或目录文件占用问题。

  1. 需要以管理员身份启动HBuilderX。
  2. 需要关掉HBuilderX,在任务管理器里杀掉node.js、adb相关进程。或者重启电脑。杀掉这些进程后启动HBuilderX不要运行应用,直接升级。

后续版本会解决这个问题。

收起阅读 »

【解决方案】关于iPhone XR/XS/XS Max无法手机真机运行的临时解决方法

真机运行 iPhone XS iphonex HBuilderX

部分同学在iPhone XS/iPhone XS Max等手机上真机运行不了的问题,解决方法如下:

最新版hx已解决,请升级。
HBuilder不支持,请升级到hx。

需注意保持itunes为最新

另此问题只影响真机运行,不影响打包的app在这些手机上安装和运行。

继续阅读 »

部分同学在iPhone XS/iPhone XS Max等手机上真机运行不了的问题,解决方法如下:

最新版hx已解决,请升级。
HBuilder不支持,请升级到hx。

需注意保持itunes为最新

另此问题只影响真机运行,不影响打包的app在这些手机上安装和运行。

收起阅读 »

关于HBuilderX运行或其它操作,要求管理员权限的问题

权限 HBuilderX权限

办法1:不要把HBuilderX安装包放置在C盘程序目录下

方法2:

  1. 激活windows administrator用户,使用administrator用户
  2. “我的电脑”,右键菜单,点击“管理”,即可进入“计算机管理”窗口

继续阅读 »

办法1:不要把HBuilderX安装包放置在C盘程序目录下

方法2:

  1. 激活windows administrator用户,使用administrator用户
  2. “我的电脑”,右键菜单,点击“管理”,即可进入“计算机管理”窗口

收起阅读 »

【解决方案】关于HBuilder中iOS真机运行基座包证书过期导致无法安装的问题

真机运行 iOS真机运行失败 HBuilder

请重启HBuilder,根据升级提示升级到最新版本。

请重启HBuilder,根据升级提示升级到最新版本。

uniapp input组件

uniapp

uniapp input组件type类型为number的设置maxlength没用,app没有效果,小程序正常

uniapp input组件type类型为number的设置maxlength没用,app没有效果,小程序正常

关于nuiapp检测升级app并自动安装的代码分享

思路如下,供新手参考

检测升级部分代码

    upapp: function(isup) {  
        //#ifdef APP-PLUS  
        /* 5+环境锁定屏幕方向 */  
        plus.screen.lockOrientation('portrait-primary'); //锁定  
        /* 5+环境升级提示 */  
        var server = ""; //检查更新地址  

        var req = { //升级检测数据  
            "appid": plus.runtime.appid,  
            "version": plus.runtime.version,  
            "imei": plus.device.imei  
        };  

        uni.request({  
            url: server,  
            data: req,  
            success: (res) => {  
                if (res.statusCode == 200 && res.data.state == "yes") {  
                    let openUrl = plus.os.name === 'iOS' ? res.data.iOS : res.data.Android;  
                    var url = res.data.urlapp;  
                    var content = res.data.content;  
                    uni.showModal({ //提醒用户更新  
                        title: '更新提示',  
                        cancelText:'确定',  
                        confirmText:'取消',  
                        content: res.data.content ? res.data.content : '有新版本,是否确定更新?',  
                        success: (res) => {  
                            if (!res.confirm) {  
                                                                //跳转到升级进度页面  
                                uni.navigateTo({  
                                    url: "/pages/upapp/index?url=" + url + "&content=" + content  
                                })  
                            } else {  
                                //取消  
                            }  
                        }  
                    })  
                } else if (res.statusCode == 200) {  
                    uni.setStorageSync("upapp", time);  
                    uni.showToast({  
                        "title": res.data.content ? res.data.content : "已是最新版本",  
                    });  

                } else {  
                    //  
                }  
            }  
        })  
        //#endif  
    }

下载升级进度页面:/pages/upapp/index

<template>  
    <view>  
        <view class="page-body">  
            {{title}} {{content}}  
            <view class="page-section page-section-gap">  
                <view class="progress-box">  
                    <progress :percent="percent" show-info stroke-width="30" />  
                </view>  
            </view>  
        </view>  
    </view>  
</template>  
<script>  
    export default {  
        data() {  
            return {  
                title: '正在下载中,请稍候!',  
                content: "",  
                percent: 0  
            }  
        },  
        onLoad: function (option) {  
            if (option.url) {  
                this.content = option.content;  
                this.up_app(option.url);  
            } else {  
                uni.navigateBack({  
                    delta: 1,  
                });  
                return;  
            }  

        },  
        onHide: function () {  

        },  
        onShow: function () {  

        },  
        methods: {  
            up_app: function (url) {  
                plus.screen.lockOrientation('portrait-primary'); //锁定  
                this.download(url)  
            },  
            download: function (url) {  
                console.log(url)  
                var that = this;  
                const downloadTask = uni.downloadFile({  
                    url: url,   
                    success: function (res) {  
                        if (res.statusCode === 200) {  
                            console.log(JSON.stringify(res))  
                            console.log('下载成功');  
                            var tempFilePaths = res.tempFilePath;  
                            that.install(tempFilePaths);  
                            return;  
                        }  
                    }  
                });  

                downloadTask.onProgressUpdate(function (res) {  
                    that.percent = res.progress;  
                    //console.log('下载进度' + res.progress);  
                    //console.log('已经下载的数据长度' + res.totalBytesWritten);  
                    //console.log('预期需要下载的数据总长度' + res.totalBytesExpectedToWrite);  
                });  
            },  
            install: function (path) {//安装  
                console.log(path)  
                plus.runtime.install(path, {  
                    force: true  
                }, function () {  
                    //uni.hideNavigationBarLoading();  
                    console.log("加载完成!");  
                    uni.navigateBack({  
                        delta: 1,  
                    });  
                }, function (e) {  

                    console.log(JSON.stringify(e));  

                });  
            }  

        }  
    }  
</script>  

<style>  
    progress {  
        width: 100%;  
    }  

    .progress-box {  
        display: flex;  
        height: 50px;  
        margin-bottom: 60px;  
    }  

    .progress-cancel {  
        margin-left: 40px;  
    }  
</style>

后端代码(php):

$version="";//是接收到的版本号
$now_v="1.0.1";//要升级最新版本号
$data_json=["state"=>"not","content"=>"已是最新版本!",];
if ($version !== $now_v) { //这里是示例代码,真实业务上,最新版本号及relase no
$data_json =array(
"state"=>"yes",
"content"=>"增加一些新功能。",
"mark"=>$now_v,
"urlapp"=>"",//下载app地址
);
}

继续阅读 »

思路如下,供新手参考

检测升级部分代码

    upapp: function(isup) {  
        //#ifdef APP-PLUS  
        /* 5+环境锁定屏幕方向 */  
        plus.screen.lockOrientation('portrait-primary'); //锁定  
        /* 5+环境升级提示 */  
        var server = ""; //检查更新地址  

        var req = { //升级检测数据  
            "appid": plus.runtime.appid,  
            "version": plus.runtime.version,  
            "imei": plus.device.imei  
        };  

        uni.request({  
            url: server,  
            data: req,  
            success: (res) => {  
                if (res.statusCode == 200 && res.data.state == "yes") {  
                    let openUrl = plus.os.name === 'iOS' ? res.data.iOS : res.data.Android;  
                    var url = res.data.urlapp;  
                    var content = res.data.content;  
                    uni.showModal({ //提醒用户更新  
                        title: '更新提示',  
                        cancelText:'确定',  
                        confirmText:'取消',  
                        content: res.data.content ? res.data.content : '有新版本,是否确定更新?',  
                        success: (res) => {  
                            if (!res.confirm) {  
                                                                //跳转到升级进度页面  
                                uni.navigateTo({  
                                    url: "/pages/upapp/index?url=" + url + "&content=" + content  
                                })  
                            } else {  
                                //取消  
                            }  
                        }  
                    })  
                } else if (res.statusCode == 200) {  
                    uni.setStorageSync("upapp", time);  
                    uni.showToast({  
                        "title": res.data.content ? res.data.content : "已是最新版本",  
                    });  

                } else {  
                    //  
                }  
            }  
        })  
        //#endif  
    }

下载升级进度页面:/pages/upapp/index

<template>  
    <view>  
        <view class="page-body">  
            {{title}} {{content}}  
            <view class="page-section page-section-gap">  
                <view class="progress-box">  
                    <progress :percent="percent" show-info stroke-width="30" />  
                </view>  
            </view>  
        </view>  
    </view>  
</template>  
<script>  
    export default {  
        data() {  
            return {  
                title: '正在下载中,请稍候!',  
                content: "",  
                percent: 0  
            }  
        },  
        onLoad: function (option) {  
            if (option.url) {  
                this.content = option.content;  
                this.up_app(option.url);  
            } else {  
                uni.navigateBack({  
                    delta: 1,  
                });  
                return;  
            }  

        },  
        onHide: function () {  

        },  
        onShow: function () {  

        },  
        methods: {  
            up_app: function (url) {  
                plus.screen.lockOrientation('portrait-primary'); //锁定  
                this.download(url)  
            },  
            download: function (url) {  
                console.log(url)  
                var that = this;  
                const downloadTask = uni.downloadFile({  
                    url: url,   
                    success: function (res) {  
                        if (res.statusCode === 200) {  
                            console.log(JSON.stringify(res))  
                            console.log('下载成功');  
                            var tempFilePaths = res.tempFilePath;  
                            that.install(tempFilePaths);  
                            return;  
                        }  
                    }  
                });  

                downloadTask.onProgressUpdate(function (res) {  
                    that.percent = res.progress;  
                    //console.log('下载进度' + res.progress);  
                    //console.log('已经下载的数据长度' + res.totalBytesWritten);  
                    //console.log('预期需要下载的数据总长度' + res.totalBytesExpectedToWrite);  
                });  
            },  
            install: function (path) {//安装  
                console.log(path)  
                plus.runtime.install(path, {  
                    force: true  
                }, function () {  
                    //uni.hideNavigationBarLoading();  
                    console.log("加载完成!");  
                    uni.navigateBack({  
                        delta: 1,  
                    });  
                }, function (e) {  

                    console.log(JSON.stringify(e));  

                });  
            }  

        }  
    }  
</script>  

<style>  
    progress {  
        width: 100%;  
    }  

    .progress-box {  
        display: flex;  
        height: 50px;  
        margin-bottom: 60px;  
    }  

    .progress-cancel {  
        margin-left: 40px;  
    }  
</style>

后端代码(php):

$version="";//是接收到的版本号
$now_v="1.0.1";//要升级最新版本号
$data_json=["state"=>"not","content"=>"已是最新版本!",];
if ($version !== $now_v) { //这里是示例代码,真实业务上,最新版本号及relase no
$data_json =array(
"state"=>"yes",
"content"=>"增加一些新功能。",
"mark"=>$now_v,
"urlapp"=>"",//下载app地址
);
}

收起阅读 »

uni-app简易富文本编辑器(不是基于markdown)

uniapp插件 uniapp

git地址

(此编辑器仅适用移动端,chrome请按F12模拟手机设备进行浏览)
demo

说明:打包为h5需要进入项目根目录执行
npm init
npm install
安装颜色选择器插件,如无需打包为H5可忽略

上传视频及文件需要传入上传地址给组件,详情见DEMO(注意H5版本的跨域问题)。

具体用法见代码,本插件仅提供了一下思路,可根据自己的需求再进行修改。
截图:

1

2

继续阅读 »

git地址

(此编辑器仅适用移动端,chrome请按F12模拟手机设备进行浏览)
demo

说明:打包为h5需要进入项目根目录执行
npm init
npm install
安装颜色选择器插件,如无需打包为H5可忽略

上传视频及文件需要传入上传地址给组件,详情见DEMO(注意H5版本的跨域问题)。

具体用法见代码,本插件仅提供了一下思路,可根据自己的需求再进行修改。
截图:

1

2

收起阅读 »

MUI框架制作的汽车4S店网站模板分享

mui


一款基于MUI框架制作的蓝色美观的汽车4S店网站模板,可以用来做汽车美容维修微网站模板等

下载地址:http://www.sucaihuo.com/templates/2081.html
需要积分的朋友,签到评论可以免费获取积分下载

继续阅读 »


一款基于MUI框架制作的蓝色美观的汽车4S店网站模板,可以用来做汽车美容维修微网站模板等

下载地址:http://www.sucaihuo.com/templates/2081.html
需要积分的朋友,签到评论可以免费获取积分下载

收起阅读 »