HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

TRONexMax智能合约系统定制开发

App

TRONexMax波场合约系统定制开发【199-2463*6653】

TRONexMax波场合约系统定制开发【199-2463*6653】

uniapp 隐私与政策提示框配置方法

app-plus下面配置

"privacy" : {
"prompt" : "template",
"template" : {
//prompt取值为template时有效,用于配置模板提示框上显示的内容
"title" : "温馨提示",
"message" : "  欢迎使用布尔App,布尔非常牛逼带你装逼带你飞。在使用App服务前,请认真阅读<a href='http或者https链接'>《用户服务协议》</a>及<a href='http或者https链接'>《隐私政策》</a>,全部条款。你同意并接受全部条款后开始使用我们的服务<br/>",
"buttonAccept" : "同意并继续", //继续下一步,进入首页
"buttonRefuse" : "不同意" //退出下载
}
},

继续阅读 »

app-plus下面配置

"privacy" : {
"prompt" : "template",
"template" : {
//prompt取值为template时有效,用于配置模板提示框上显示的内容
"title" : "温馨提示",
"message" : "  欢迎使用布尔App,布尔非常牛逼带你装逼带你飞。在使用App服务前,请认真阅读<a href='http或者https链接'>《用户服务协议》</a>及<a href='http或者https链接'>《隐私政策》</a>,全部条款。你同意并接受全部条款后开始使用我们的服务<br/>",
"buttonAccept" : "同意并继续", //继续下一步,进入首页
"buttonRefuse" : "不同意" //退出下载
}
},

收起阅读 »

H5跨域秒解决的方法

uniCloud

一、在uniCloud前端网页托管===>参数配置中,复制你的网站网址(默认域名)。
二、在跨域配置===>新增域名内,粘贴确定即可。
三、所有端都可以通过网址(默认域名)访问你的网站了。

继续阅读 »

一、在uniCloud前端网页托管===>参数配置中,复制你的网站网址(默认域名)。
二、在跨域配置===>新增域名内,粘贴确定即可。
三、所有端都可以通过网址(默认域名)访问你的网站了。

收起阅读 »

微信支付商户号H5支付产品权限开通详解

微信h5 微信app

一、微信商户H5支付产品简介

H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付。

主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外部浏览器唤起微信支付

二、H5支付开通流程详解

登录商户平台-->产品中心-->我的产品-->支付产品-->H5支付

需要如实完善以下信息后再进行申请提交

◆ 需要搭建一个H5商城系统,要有完整的购买支付流程展示。

◆ 如有同主体备案域名,可以直接提交提交进行申请。

◆ 如无同主体域名,需要用到《ICP备案授权函》,模板可在“网创商盟”中下载。记得在授权函中填写所需的完整信息,并且签字盖章

◆ 如实填写售卖产品信息

如果上述操作,有问题或者想要进一步信息了解,可以前往“网创商盟”这个公众号获取更多帮助支持。同时祝愿大家早日开通H5支付来运营使用。

继续阅读 »

一、微信商户H5支付产品简介

H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付。

主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外部浏览器唤起微信支付

二、H5支付开通流程详解

登录商户平台-->产品中心-->我的产品-->支付产品-->H5支付

需要如实完善以下信息后再进行申请提交

◆ 需要搭建一个H5商城系统,要有完整的购买支付流程展示。

◆ 如有同主体备案域名,可以直接提交提交进行申请。

◆ 如无同主体域名,需要用到《ICP备案授权函》,模板可在“网创商盟”中下载。记得在授权函中填写所需的完整信息,并且签字盖章

◆ 如实填写售卖产品信息

如果上述操作,有问题或者想要进一步信息了解,可以前往“网创商盟”这个公众号获取更多帮助支持。同时祝愿大家早日开通H5支付来运营使用。

收起阅读 »

无需苹果电脑上传ipa到AppStore构造版本,liunx下上传ipa到App Store,windows上传ipa

内测 上架

前言:

> 虽然Mac系统使用xcode自带的上传ipa工具很方便,也很简单,但众多跨平台开发者,如:uni-app,apicloud,Flutter等混合开发者,用不到mac系统来开发,几乎没有必要用到,如果只是一个上传ipa功能,来买个Mac,那太不划算了(土豪随意),我们开发出了无需Mac,自助上传ipa文件到Appstore构造版本,无需Mac系统,无需苹果电脑,无需安装任何程序,只需要一个浏览器即可搞定,兼容多种环境,服务器千兆宽带上传,直连苹果端,上传IP随机更换,提升App Store上架成功率,4.3被拒几率也会大大降低。我们将会当您的iPA上传成功后,立刻删除您的账号密码,确保数据安全,始终坚持用最好的服务,为客户带来最大的价值,欢迎您的使用!

续:

> 古人云:读书破万卷,下笔如有神...........咳咳,废话不多说

>
> 1.上传ipa
> 2.输入开发者账号,和专用密码
> 3.提交任务

后记:

> 1.我们解决了混合开发者彻底摆脱Mac系统

> 2.解决了在Mac系统下上传IPA卡住的问题(正在通过App Store进行认证或正在验证 App一直没动静)

> 3.千兆宽带支持,上传速度更快,代替mac的application loader, 上传构建文件到开发者中心

> 4.专用密码详解:专用密码不是开发者的账号密码,需要在开发者中心右上角账号名里点"Email Settings"->再点"My Apple ID",登录apple Id的安全管理页面里获取专用密码,这里的专用密码,仅适用于上传ipa构造版本,无法登陆其他网站或者第三方应用!

> 简单三步搞定;地址:https://www.chuxueyun.com/ipaup/index.html

继续阅读 »

前言:

> 虽然Mac系统使用xcode自带的上传ipa工具很方便,也很简单,但众多跨平台开发者,如:uni-app,apicloud,Flutter等混合开发者,用不到mac系统来开发,几乎没有必要用到,如果只是一个上传ipa功能,来买个Mac,那太不划算了(土豪随意),我们开发出了无需Mac,自助上传ipa文件到Appstore构造版本,无需Mac系统,无需苹果电脑,无需安装任何程序,只需要一个浏览器即可搞定,兼容多种环境,服务器千兆宽带上传,直连苹果端,上传IP随机更换,提升App Store上架成功率,4.3被拒几率也会大大降低。我们将会当您的iPA上传成功后,立刻删除您的账号密码,确保数据安全,始终坚持用最好的服务,为客户带来最大的价值,欢迎您的使用!

续:

> 古人云:读书破万卷,下笔如有神...........咳咳,废话不多说

>
> 1.上传ipa
> 2.输入开发者账号,和专用密码
> 3.提交任务

后记:

> 1.我们解决了混合开发者彻底摆脱Mac系统

> 2.解决了在Mac系统下上传IPA卡住的问题(正在通过App Store进行认证或正在验证 App一直没动静)

> 3.千兆宽带支持,上传速度更快,代替mac的application loader, 上传构建文件到开发者中心

> 4.专用密码详解:专用密码不是开发者的账号密码,需要在开发者中心右上角账号名里点"Email Settings"->再点"My Apple ID",登录apple Id的安全管理页面里获取专用密码,这里的专用密码,仅适用于上传ipa构造版本,无法登陆其他网站或者第三方应用!

> 简单三步搞定;地址:https://www.chuxueyun.com/ipaup/index.html

收起阅读 »

原生编辑视频传给前端本地地址,上传oss


//v  = 原生本地视频路径  
fileInfo(v){  
           var file = typeof(v) === 'object' ? v : JSON.parse(v)  
           var reader = new plus.io.FileReader();  
           reader.onloadstart = function(e) {  
               // console.log('resolveLocalFileSystemURL onloadstart reader.result' + reader.result);  
               console.log("resolveLocalFileSystemURL onloadstart:" + JSON.stringify(e).substring(0,180));  
           }  
           reader.onload = function(e) {  
               // console.log('resolveLocalFileSystemURL onload reader.result' + reader.result);  
               console.log("resolveLocalFileSystemURL onload:" + JSON.stringify(e).substring(0,180));  
           }  
           reader.onabort = function(e) {  
               // console.log('resolveLocalFileSystemURL onabort reader.result' + reader.result);  
               console.log("resolveLocalFileSystemURL onabort:" + JSON.stringify(e).substring(0,180));  
           }  
           reader.onerror = function(e) {  
               // console.log('resolveLocalFileSystemURL onerror reader.result' + reader.result);  
               console.log("resolveLocalFileSystemURL onerror:" + JSON.stringify(e).substring(0,180));  
           }  
           reader.onloadend = function ( e ) {    
               console.log("resolveLocalFileSystemURL onloadend  e.target.result:" + e.target.result.substring(0,180));  
               // var blob = base64toBlob(reader.result, "UTF-8");  
               // console.log('resolveLocalFileSystemURL   blob :' , vueSelf.$center.dataURItoBlob(e.target.result))  
               try{  
                   var blob = dataURLtoBlob(e.target.result)  
                   console.log("resolveLocalFileSystemURL onloadend  blob :" + blob.substring(0,180));  
                   //BLOB对象转换为FILE对象     
                   var newfile = new File([blob],file.name);    
                   console.log("resolveLocalFileSystemURL  start" );    
                   console.log(newfile.size+'---'+newfile.name);    
                   console.log(entry.toLocalURL());    
                   console.log("resolveLocalFileSystemURL  end" );    
               }catch(e){  
                   //TODO handle the exception  
                   console.log('resolveLocalFileSystemURL cash' ,e)  
               }  
               // vueSelf.$center.fileUpload('mp4',blob)  
           }  
            reader.readAsDataURL(file, 'utf-8');    
           // reader.readAsText(file, 'utf-8');  
           //Base64转二进制  
           function  dataURLtoBlob(dataurl) {    
               var arr = dataurl.split(','),    
                   mime = arr[0].match(/:(.*?);/)[1],    
                   bstr = atob(arr[1]),    
                   n = bstr.length,    
                   u8arr = new Uint8Array(n);//8位无符号整数,长度1个字节    
               console.log(mime)    
               while (n--) {    
                   u8arr[n] = bstr.charCodeAt(n);    
               }    
               // console.log(JSON.stringify(u8arr));    
               return new Blob([u8arr], {    
                   type: mime    
               });    
           }  
        },
继续阅读 »

//v  = 原生本地视频路径  
fileInfo(v){  
           var file = typeof(v) === 'object' ? v : JSON.parse(v)  
           var reader = new plus.io.FileReader();  
           reader.onloadstart = function(e) {  
               // console.log('resolveLocalFileSystemURL onloadstart reader.result' + reader.result);  
               console.log("resolveLocalFileSystemURL onloadstart:" + JSON.stringify(e).substring(0,180));  
           }  
           reader.onload = function(e) {  
               // console.log('resolveLocalFileSystemURL onload reader.result' + reader.result);  
               console.log("resolveLocalFileSystemURL onload:" + JSON.stringify(e).substring(0,180));  
           }  
           reader.onabort = function(e) {  
               // console.log('resolveLocalFileSystemURL onabort reader.result' + reader.result);  
               console.log("resolveLocalFileSystemURL onabort:" + JSON.stringify(e).substring(0,180));  
           }  
           reader.onerror = function(e) {  
               // console.log('resolveLocalFileSystemURL onerror reader.result' + reader.result);  
               console.log("resolveLocalFileSystemURL onerror:" + JSON.stringify(e).substring(0,180));  
           }  
           reader.onloadend = function ( e ) {    
               console.log("resolveLocalFileSystemURL onloadend  e.target.result:" + e.target.result.substring(0,180));  
               // var blob = base64toBlob(reader.result, "UTF-8");  
               // console.log('resolveLocalFileSystemURL   blob :' , vueSelf.$center.dataURItoBlob(e.target.result))  
               try{  
                   var blob = dataURLtoBlob(e.target.result)  
                   console.log("resolveLocalFileSystemURL onloadend  blob :" + blob.substring(0,180));  
                   //BLOB对象转换为FILE对象     
                   var newfile = new File([blob],file.name);    
                   console.log("resolveLocalFileSystemURL  start" );    
                   console.log(newfile.size+'---'+newfile.name);    
                   console.log(entry.toLocalURL());    
                   console.log("resolveLocalFileSystemURL  end" );    
               }catch(e){  
                   //TODO handle the exception  
                   console.log('resolveLocalFileSystemURL cash' ,e)  
               }  
               // vueSelf.$center.fileUpload('mp4',blob)  
           }  
            reader.readAsDataURL(file, 'utf-8');    
           // reader.readAsText(file, 'utf-8');  
           //Base64转二进制  
           function  dataURLtoBlob(dataurl) {    
               var arr = dataurl.split(','),    
                   mime = arr[0].match(/:(.*?);/)[1],    
                   bstr = atob(arr[1]),    
                   n = bstr.length,    
                   u8arr = new Uint8Array(n);//8位无符号整数,长度1个字节    
               console.log(mime)    
               while (n--) {    
                   u8arr[n] = bstr.charCodeAt(n);    
               }    
               // console.log(JSON.stringify(u8arr));    
               return new Blob([u8arr], {    
                   type: mime    
               });    
           }  
        },
收起阅读 »

强烈建议 Dcloud 放弃 hbuilderX

HBuilderX uniapp

不知道 Dcloud 准备往哪个方向发展!
但无论什么方向,暂时放弃hbuilderX都是最佳的选择!!!
集中精力提高编译、调试体验是开发者最关心的。
我希望有这么一个工具:

无论我用什么开发工具:webstor?sublime?都可以
只要项目基于 cli 创建,就可以使用我进行编译或打包:
调试时,能有原生开发级别的效率,如调试信息的输出方面。
APP 级别的、webview 级别的消息如果能集成在一个地方查看那就更好了
各种异常都能给出提示,让用户不再无头苍蝇一般。

如果能集成发布工具那就更好了,一键上架 N个市场,辅助申请各种证书。

而不是正事不干,去开发一个四流的开发工具 IDE。

继续阅读 »

不知道 Dcloud 准备往哪个方向发展!
但无论什么方向,暂时放弃hbuilderX都是最佳的选择!!!
集中精力提高编译、调试体验是开发者最关心的。
我希望有这么一个工具:

无论我用什么开发工具:webstor?sublime?都可以
只要项目基于 cli 创建,就可以使用我进行编译或打包:
调试时,能有原生开发级别的效率,如调试信息的输出方面。
APP 级别的、webview 级别的消息如果能集成在一个地方查看那就更好了
各种异常都能给出提示,让用户不再无头苍蝇一般。

如果能集成发布工具那就更好了,一键上架 N个市场,辅助申请各种证书。

而不是正事不干,去开发一个四流的开发工具 IDE。

收起阅读 »

plus.statistic.eventTrig触发友盟统计事件,友盟后台无反应--解决

统计
                        //对于一些没有eventValue的事件 如果eventValue为空 或空对象  友盟后台会统计不到这个事件  
            //所以这里加空判断 如果为空 设置一个默认值  

            if(isEmptyObj(event.eventValue)){  
                plus.statistic.eventTrig(event.eventId,{"name":'default'});  
            }else{  
                plus.statistic.eventTrig(event.eventId, event.eventValue);  
            }

找了好久终于发现这个问题,触发事件时记得判断传入的值是否是空 或 空对象

继续阅读 »
                        //对于一些没有eventValue的事件 如果eventValue为空 或空对象  友盟后台会统计不到这个事件  
            //所以这里加空判断 如果为空 设置一个默认值  

            if(isEmptyObj(event.eventValue)){  
                plus.statistic.eventTrig(event.eventId,{"name":'default'});  
            }else{  
                plus.statistic.eventTrig(event.eventId, event.eventValue);  
            }

找了好久终于发现这个问题,触发事件时记得判断传入的值是否是空 或 空对象

收起阅读 »

uniapp打包时的问题

uniapp离线打包

现在的uniapp云打包是真的差劲,一个10mb左右的包给我打包了半个小时,忍不住吐槽

现在的uniapp云打包是真的差劲,一个10mb左右的包给我打包了半个小时,忍不住吐槽

App 下载视频到本地相册

const downloadTask = uni.downloadFile({  
                        url: url,  // 视频的下载地址  
                        success: (data) => {  
                            if (data.statusCode === 200) {  
                                 uni.saveImageToPhotosAlbum({ // 需要保存到相册 如果是下载文件 用uni.saveFile()  
                                      filePath: data.tempFilePath, // 视频的本地临时地址  
                                      success: function (res) {  
                                          console.log('下载成功')  
                                        uni.showToast({  
                                            title: '下载完成,请到相册查看',  
                                            position: 'center',  
                                            icon: 'none',  
                                            duration: 2000  
                                        });  
                                      },  
                                      fail: () => {  
                                        uni.showToast({  
                                            title: '下载视频失败请重试',  
                                            position: 'center',  
                                            icon: 'none',  
                                            duration: 2000  
                                        });  
                                      }  
                                    });  
                            }  
                        },  
                        fail: (err)=>{  
                            this.downText = '下载视频'  
                            uni.hideLoading()  
                            uni.showToast({  
                                title: err,  
                                position: 'center',  
                                icon: 'none',  
                                duration: 2000  
                            });  
                        },  
                        complete: ()=>{  
                            this.downText ='下载视频'  
                        }  
                    });  

                    downloadTask.onProgressUpdate((res) => { // 下载进度  
                        this.downText = `已下载${res.progress}%`  
                        if(res.progress == 100){  
                            this.downText = '下载视频'  

                        }  
                    });
继续阅读 »
const downloadTask = uni.downloadFile({  
                        url: url,  // 视频的下载地址  
                        success: (data) => {  
                            if (data.statusCode === 200) {  
                                 uni.saveImageToPhotosAlbum({ // 需要保存到相册 如果是下载文件 用uni.saveFile()  
                                      filePath: data.tempFilePath, // 视频的本地临时地址  
                                      success: function (res) {  
                                          console.log('下载成功')  
                                        uni.showToast({  
                                            title: '下载完成,请到相册查看',  
                                            position: 'center',  
                                            icon: 'none',  
                                            duration: 2000  
                                        });  
                                      },  
                                      fail: () => {  
                                        uni.showToast({  
                                            title: '下载视频失败请重试',  
                                            position: 'center',  
                                            icon: 'none',  
                                            duration: 2000  
                                        });  
                                      }  
                                    });  
                            }  
                        },  
                        fail: (err)=>{  
                            this.downText = '下载视频'  
                            uni.hideLoading()  
                            uni.showToast({  
                                title: err,  
                                position: 'center',  
                                icon: 'none',  
                                duration: 2000  
                            });  
                        },  
                        complete: ()=>{  
                            this.downText ='下载视频'  
                        }  
                    });  

                    downloadTask.onProgressUpdate((res) => { // 下载进度  
                        this.downText = `已下载${res.progress}%`  
                        if(res.progress == 100){  
                            this.downText = '下载视频'  

                        }  
                    });
收起阅读 »

微信支付商户平台app支付开通方法详解

微信h5 微信支付 微信app

一、创建移动应用

1、创建移动应用之前,必须得有微信开放平台的认证账号,如无可查阅“网创商盟”历史消息进行申请认证操作。

2、登录微信开放平台创建移动应用,按照页面填写一下信息,包括应用名称、应用简介、应用官网、应用图片(2828和108108的PNG格式各一张)、APP运行流程图、申请说明、应用签名、应用包名等。

资料填写完毕,直接提交审核等待通过即可,如有不明白之处,可以查阅“网创联盟”来公众号获取更多信息。

二、微信商户app支付的开通详解

1、登录微信商户平台,直接扫码登录,如果没有商户号,需要先去申请一个商户号;

2、点击产品中心,找到APP支付并点击进入

按照app支付产品设置页面,分别填写移动应用的App ID(需要在步骤一中审核通过后的应用中获取)、APP页面截图信息等。资料填写完毕,直接提交申请等待审核,等待审核通过后即可

继续阅读 »

一、创建移动应用

1、创建移动应用之前,必须得有微信开放平台的认证账号,如无可查阅“网创商盟”历史消息进行申请认证操作。

2、登录微信开放平台创建移动应用,按照页面填写一下信息,包括应用名称、应用简介、应用官网、应用图片(2828和108108的PNG格式各一张)、APP运行流程图、申请说明、应用签名、应用包名等。

资料填写完毕,直接提交审核等待通过即可,如有不明白之处,可以查阅“网创联盟”来公众号获取更多信息。

二、微信商户app支付的开通详解

1、登录微信商户平台,直接扫码登录,如果没有商户号,需要先去申请一个商户号;

2、点击产品中心,找到APP支付并点击进入

按照app支付产品设置页面,分别填写移动应用的App ID(需要在步骤一中审核通过后的应用中获取)、APP页面截图信息等。资料填写完毕,直接提交申请等待审核,等待审核通过后即可

收起阅读 »

Android uni-app实现音视频通话

webrtc Android uniapp

前言

上一篇讲解了怎么实现Android uni-app封装原生插件,这篇讲解一下,把anyRTC的RTC(音视频通讯)封装uni-app 实现音视频通话。

不了解anyRTC的小伙伴,可以点击下面链接:

开发者官网

1.效果图

先上图,后讲解!

1.1 首页

1.2 游客界面

1.3 主播界面

2.GitHub地址

uni-app demo: 点击下载

3.demo下载:

下载地址:点击下载

扫码下载:

4.代码

4.1 集成插件

const RtcModule = uni.requireNativePlugin('AR-RtcModule');
  • AR-RtcModule:插件名称,首页集成插件

4.2 初始事件回调

//callback 接收  
callbackFn() {  
    RtcModule.setCallBack((res) => {  
        switch (res.engineEvent) {  
            case "onWarning":  
                this.promptFn("warn", res.warningCode);  
                break;  
            case "onError":  
                res.errorCode != 18 ? this.promptFn("error", res.errorCode) : '';  
                break;  
            case "onJoinChannelSuccess": //用户加入成功  
                uni.hideLoading();  
                this.role == 1 ? this.PeerVideoUser.push(res.uid) : "";  
                this.videoShow = true;  
                setTimeout(() => {  
                    // this.videoShowBg = false;  
                    this.promptText = ""  
                    //扬声器  
                    RtcModule.setEnableSpeakerphone({  
                        "enabled": true  
                    }, (res) => {})  
                    setTimeout(() => {  
                        // 启用视频模块。  
                        this.role == 1 ? this.setupLocalVideoFn() : RtcModule.enableVideo((res) => {});  
                    }, 200)  
                }, 2000)  
                break;  
            case "onLeaveChannel": //离开频道回调  
                setTimeout(() => {  
                    this.closeAll()  
                }, 500)  
                break;  
            case "onUserJoined": //远端用户加入当前频道回调。  
                // this.promptFn("info", "远端用户加入当前频道回调");  
                this.PeerVideoUser.push(res.uid);  
                break;  
            case "onUserOffline": //远端用户离开当前频道回调。  
                this.PeerVideoUser = this.PeerVideoUser.filter((x) => x !== res.uid);  
                break;  

            case "onFirstLocalAudioFrame": //已发送本地音频首帧的回调。(页面上添加音频)  
                break;  
            case "onFirstLocalVideoFrame": //已显示本地视频首帧的回调。(页面添加本地视频)  
                // this.promptFn("error", "已显示本地视频首帧的回调");  
                break;  
            case "onFirstRemoteVideoDecoded": //已完成远端视频首帧解码回调。(页面添加远端视频)  
                // this.promptFn("info", "已完成远端视频首帧解码回调");  
                this.promptText = "请稍等。。。"  
                let uid = []  
                uid.push(res.uid)  
                setTimeout(() => {  
                    this.promptText = "";  
                    // this.videoShowBg = false; //设置背景开关  
                    setTimeout(() => {  
                        uid.map(item => {  
                            this.$refs[`popup${item}`][0].setupRemoteVideo({  
                                "renderMode": 1,  
                                "channelId": this.chanel,  
                                "uid": item,  
                                "mirrorMode": 0  
                            }, (res) => {})  
                            //预览  
                            RtcModule.startPreview((res) => {});  
                        })  
                    }, 500)  

                }, 2000)  
                break;  
        }  

    })  
},  
  • res.engineEvent:接收各种回调,加入频道成功,离开频道,错误码等。

4.3 创建实例

await RtcModule.create({  
    "appId": this.appid  //anyRTC 为 App 开发者签发的 App ID。每个项目都应该有一个独一无二的 App ID。如果你的开发包里没有 App ID,请从anyRTC官网(https://www.anyrtc.io)申请一个新的 App ID  
}, (res) => {});  

4.4 设置角色

setClientRole(num) {  
    this.role = num;  
    //设置直播场景下的用户角色  
    RtcModule.setClientRole({  
        "role": Number(num) //1:为主播,2:游客  
    }, (ret) => {});  
},  

4.5 加入频道

await RtcModule.joinChannel({  
    "token": "",  
    "channelId": this.channel,  
    "uid": this.uid  
}, (res) => {})  
  • token: 注册不开启token验证,可以为空着。
  • channelId: 你需要加入的频道ID。
  • uid: 每个用户分配唯一UID,不能重复。

4.6 离开销毁

RtcModule.leaveChannel((res) => {}); //离开频道  
RtcModule.destroyRtc((res) => {});    //销毁频道  

5.总结

基本重要的接口,在这里就基本上介绍完啦,如果大家还有什么疑问,可以在评论区留言!

作者:anyRTC-东慕雨

点击查看原

继续阅读 »

前言

上一篇讲解了怎么实现Android uni-app封装原生插件,这篇讲解一下,把anyRTC的RTC(音视频通讯)封装uni-app 实现音视频通话。

不了解anyRTC的小伙伴,可以点击下面链接:

开发者官网

1.效果图

先上图,后讲解!

1.1 首页

1.2 游客界面

1.3 主播界面

2.GitHub地址

uni-app demo: 点击下载

3.demo下载:

下载地址:点击下载

扫码下载:

4.代码

4.1 集成插件

const RtcModule = uni.requireNativePlugin('AR-RtcModule');
  • AR-RtcModule:插件名称,首页集成插件

4.2 初始事件回调

//callback 接收  
callbackFn() {  
    RtcModule.setCallBack((res) => {  
        switch (res.engineEvent) {  
            case "onWarning":  
                this.promptFn("warn", res.warningCode);  
                break;  
            case "onError":  
                res.errorCode != 18 ? this.promptFn("error", res.errorCode) : '';  
                break;  
            case "onJoinChannelSuccess": //用户加入成功  
                uni.hideLoading();  
                this.role == 1 ? this.PeerVideoUser.push(res.uid) : "";  
                this.videoShow = true;  
                setTimeout(() => {  
                    // this.videoShowBg = false;  
                    this.promptText = ""  
                    //扬声器  
                    RtcModule.setEnableSpeakerphone({  
                        "enabled": true  
                    }, (res) => {})  
                    setTimeout(() => {  
                        // 启用视频模块。  
                        this.role == 1 ? this.setupLocalVideoFn() : RtcModule.enableVideo((res) => {});  
                    }, 200)  
                }, 2000)  
                break;  
            case "onLeaveChannel": //离开频道回调  
                setTimeout(() => {  
                    this.closeAll()  
                }, 500)  
                break;  
            case "onUserJoined": //远端用户加入当前频道回调。  
                // this.promptFn("info", "远端用户加入当前频道回调");  
                this.PeerVideoUser.push(res.uid);  
                break;  
            case "onUserOffline": //远端用户离开当前频道回调。  
                this.PeerVideoUser = this.PeerVideoUser.filter((x) => x !== res.uid);  
                break;  

            case "onFirstLocalAudioFrame": //已发送本地音频首帧的回调。(页面上添加音频)  
                break;  
            case "onFirstLocalVideoFrame": //已显示本地视频首帧的回调。(页面添加本地视频)  
                // this.promptFn("error", "已显示本地视频首帧的回调");  
                break;  
            case "onFirstRemoteVideoDecoded": //已完成远端视频首帧解码回调。(页面添加远端视频)  
                // this.promptFn("info", "已完成远端视频首帧解码回调");  
                this.promptText = "请稍等。。。"  
                let uid = []  
                uid.push(res.uid)  
                setTimeout(() => {  
                    this.promptText = "";  
                    // this.videoShowBg = false; //设置背景开关  
                    setTimeout(() => {  
                        uid.map(item => {  
                            this.$refs[`popup${item}`][0].setupRemoteVideo({  
                                "renderMode": 1,  
                                "channelId": this.chanel,  
                                "uid": item,  
                                "mirrorMode": 0  
                            }, (res) => {})  
                            //预览  
                            RtcModule.startPreview((res) => {});  
                        })  
                    }, 500)  

                }, 2000)  
                break;  
        }  

    })  
},  
  • res.engineEvent:接收各种回调,加入频道成功,离开频道,错误码等。

4.3 创建实例

await RtcModule.create({  
    "appId": this.appid  //anyRTC 为 App 开发者签发的 App ID。每个项目都应该有一个独一无二的 App ID。如果你的开发包里没有 App ID,请从anyRTC官网(https://www.anyrtc.io)申请一个新的 App ID  
}, (res) => {});  

4.4 设置角色

setClientRole(num) {  
    this.role = num;  
    //设置直播场景下的用户角色  
    RtcModule.setClientRole({  
        "role": Number(num) //1:为主播,2:游客  
    }, (ret) => {});  
},  

4.5 加入频道

await RtcModule.joinChannel({  
    "token": "",  
    "channelId": this.channel,  
    "uid": this.uid  
}, (res) => {})  
  • token: 注册不开启token验证,可以为空着。
  • channelId: 你需要加入的频道ID。
  • uid: 每个用户分配唯一UID,不能重复。

4.6 离开销毁

RtcModule.leaveChannel((res) => {}); //离开频道  
RtcModule.destroyRtc((res) => {});    //销毁频道  

5.总结

基本重要的接口,在这里就基本上介绍完啦,如果大家还有什么疑问,可以在评论区留言!

作者:anyRTC-东慕雨

点击查看原

收起阅读 »