【2024】uniapp 接入声网音频RTC【H5+Android】Unibest模板下Vue3+Typescript

需求

最近开发一个项目,需要实现声网的接入。由于采用uniapp模式,按照最佳实践采用优先开发H5再适配的模式。因此实现了H5和Android两种模式的接入,Android里采用离线打包自定义基座来进行调试。怕自己忘记了,在这里详细的记录完整的核心整合逻辑

准备

开始前,准备了以下组件:

unibest 菲鸽开源的uniapp模板,对于安卓代码,采用的是中间编译模式。因此APP模式下已经是混淆压缩过的代码了,即使采用uniapp云打包上传代码,也是相对的安全。当然对于咱的开发来说可以更抠门一点,连云打包都不用了,直接离线编译基座🤪(项目没上线,银子有限而已)

JDK 万年不变的1.8版本,主要是因为下来的参考代码也都是jdk1.8编译级别的

AndroidStudio 版本是2024.1.2,SDK下载了30和28的版本(为什么是28?因为目前各大市场都要求最低最少兼容安卓9.0)

HBuilder安卓示例 这个是HBuilder的安卓示例项目。里面包含了AS插件项目以及AS整合项目。你需要以这个为基础项目来参考修改。【福利】百度网盘太慢,这里我自己收录了一份

Agora-RTC_3.7.0_example AgoraRTC SDK使用的示例项目,由于unibest使用的是Typescript,因此需要这个项目里包含的typescript模式的sdk使用代码

Agora-RTC_3.7.2 AgoraRTC的uniapp插件包,可以从DCloud市场下载,里面包含了安卓插件编译aar文件

接入步骤

H5接入

H5接入的前提假设你使用unibest模板建立了一个基础项目。

1.添加npm组件

首先是给项目添加npm组件

bash 复制代码
pnpm i agora-rtc-sdk-ng

2.导入组件

在页面的script头部申明导入

TypeScript 复制代码
import AgoraRTC, { IAgoraRTCClient } from 'agora-rtc-sdk-ng'

3.定义控制对象

对于H5,我们只需要两个组件变量即可,一个是RTC客户端,一个是用于控制本地音频采集的本地音轨

TypeScript 复制代码
let client: IAgoraRTCClient, localAudioTrack

4.初始化引擎

TypeScript 复制代码
client = AgoraRTC.createClient({ mode: 'rtc', codec: 'h264' })

5.订阅音轨

这样可以收听到其它用户声音,注意时间额度用光后,这里是进不来的

TypeScript 复制代码
      client.on('user-published', async (user, mediaType) => {
        // 声网IP/ID每日免费额度到了后这里进不来(大坑)
        console.log('==== start subscribe audio track ====')
        // 开始订阅远端用户。
        await client.subscribe(user, mediaType)
        console.log('subscribe success')

        // 表示本次订阅的是音频。
        if (mediaType === 'audio') {
          // 订阅完成后,从 `user` 中获取远端音频轨道对象。
          const remoteAudioTrack = user.audioTrack
          // 播放音频因为不会有画面,不需要提供 DOM 元素的信息。
          remoteAudioTrack.play()
        }
      })

6.加入Channel

这里由于我们后端采用的是雪花分片算法,属于64位长整型,因此不能直接采用number传入,这里有坑。API备注写的很清楚,如果要长整型的用户ID,请使用string传入

生成token其它文章官网或其它的文章很多,我就不啰嗦了,包括生成临时token或者channel专用token。不懂生成token的先搜索下其他文章。appId是你在声网建立的应用ID。

TypeScript 复制代码
      const uid = await client.join(
        groupVoiceConf.appId,
        groupId.toString(),
        groupVoiceConf.token,
        currentUserId.toString()
      )

7.发布音频

发布和停止发布音频即上麦和下麦功能。

上麦代码:

TypeScript 复制代码
  try {
    if (client) {
      localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack()
      await client.publish(localAudioTrack) // 发布音频
    }
  } catch (e) {
    console.log(e)
  }

下麦代码:

TypeScript 复制代码
  try {
    if (localAudioTrack) {
      await client.unpublish(localAudioTrack)
      localAudioTrack.stop()
      localAudioTrack.close()
    }
  } catch (e) {
    console.log(e)
  }

8.离开频道

离开频道后不会收听以及发言,代码如下:

TypeScript 复制代码
  if (client) await client.leave()

9.HTML引擎不支持怎么办

对于某些精简的浏览器以及小米浏览器,存在无法兼容AgoraRTC代码的情况。是否可以根据支持情况提前判断呢?其实AgoraRTC提供了检测API checkSystemRequirements,只需要先检测,然后再执行RTC的代码即可,格式看上去这样的:

TypeScript 复制代码
  const result = AgoraRTC.checkSystemRequirements()
  if (result) {
    try {
    // your RTC code
    } catch (e) {
      console.log(e)
    }
  } else {
    utils.alert('您的浏览器不支持交互语音')
  }

注意RTC引擎都是Promise结构,因此都需要await调用和try...catch接口来判断调用失败

另外请在https环境下执行代码(搜一下plugin-basic-ssl把这个接入到vite去),直接在http环境下功能是受限制的。

另外按照官方的要求,自己生成token后,是需要定时刷新的,这部分代码页面使用一个定时器刷新即可,具体代码请自己琢磨前后端代码。

安卓接入

由于unibest开发模式推荐VSCode不是基于HBuilder,这里会有取舍:

坏处:不能像直接使用HBuilder那样在Manifest提供多个可视化选项来进行插件云打包。

好处:如果不用打自定义基座,云打包上传的代码都是压缩编译过的,相对来说比较安全。

虽然无法直接使用云打包的插件,但是我们可以使用离线打包,来弥补这个不足。

注意后面如果不特别说明,项目都是指AndroidStudio项目。

1.导入AS

我们解开Android-SDK@4.28.82186_20240923.zip,将里面的HBuilder-Integrate-AS目录释放到一个文件夹,将这个项目导入到AndroidStudio,开始配置。

2.AS配置:证书

按照官网的流程,生成自己的证书,并上传到DCloud后台(这里不是HBuilder,要登录DCloud开发者平台)。详细的自己查,这里只记录几个简要的流程:

生成证书:

bash 复制代码
set PATH=C:/JDK11/bin
keytool -genkey -alias <aliasName> -keyalg RSA -keysize 2048 -validity 36500 -keystore simpleDemo/<aliasName>.keystore

aliasName以及密码等根据自己实际情况设置。注意后面上传到DCloud后台要用这些信息的。

查看填写到DCloud后台的几个信息

bash 复制代码
set PATH=C:/JDK11/bin
keytool -list -v -keystore simpleDemo/<aliasName>.keystore
pause

查看时要输入前面genkey时的密码

然后要把证书的几个信息都配置到simpleDemo/build.gradle的signingConfigs

Groovy 复制代码
    signingConfigs {
        config {
            keyAlias '<aliasName>'
            keyPassword '<yourPass>'
            storeFile file('<aliasName>.keystore')
            storePassword '<yourStorePass>'
            v1SigningEnabled true
            v2SigningEnabled true
        }
    }

建议前面的keypass和storepass设置成一致,免得密码太多了操作蛋疼

这里有坑,注意如果上传DCloud后台时包名发生了变更,也一定要在AndroidManifest.xml里修改包名,不然有签名设置不正确报错

3.AS配置:权限

打开项目的manifests/AndroidManifest.xml,在<manifest xmlns:android>这个节点下加入权限申明(本项目只使用音频):

XML 复制代码
    <!-- 声音 -->
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>

4.AS配置:开启调试

修改项目的assets/data/dcloud_control.xml,将根节点修改为以下格式:

XML 复制代码
<hbuilder debug="true" syncDebug="true">

这个模式表示是打包自定义调试基座,如果要做正式发布时,要把debug和syncDebug去掉

另外按照uniapp整合规范,需要把appid修改为你自己项目的appid值

5.AS配置:相关的gradle组件包

打开项目根目录下的simpleDemo/build.gradle,在dependencies节点下添加4个组件

Groovy 复制代码
    implementation 'io.agora.rtc:agora-special-full:3.7.2.4'
    implementation 'io.agora.rtc:full-screen-sharing:3.7.2.4'
    implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.3.50'

    //自定义基座需要的
    implementation 'com.squareup.okhttp3:okhttp:4.12.0'

okhttp如果不导入的话,当做自定义基座就会无法将调试信息发送到HBuilder,如果你用adb的话就无所谓。建议始终带上。

另外在Agora-Uniapp-SDK.zip里找到uniplugin_agora_rtc-release.aar,把这个放入项目simpleDemo\libs下。如果要打正式release包,要把这个组件去掉,不用删除,直接写在exclude里好了:

复制代码
    implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: ['debug-server-release.aar'])

然后记得点AS菜单File->Sync Project With Gradle Files

6.AS配置:配置自定义插件

在项目simpleDemo\assets下建立文件dcloud_uniplugins.json,内容如下:

Groovy 复制代码
{
  "nativePlugins": [
    {
      "plugins": [
          {
            "type": "module",
            "name": "Agora-RTC-EngineModule",
            "class": "io.agora.rtc.uni.AgoraRtcEngineModule"
          },
          {
            "type": "module",
            "name": "Agora-RTC-ChannelModule",
            "class": "io.agora.rtc.uni.AgoraRtcChannelModule"
          },
          {
            "type": "component",
            "name": "Agora-RTC-SurfaceView",
            "class": "io.agora.rtc.uni.AgoraRtcSurfaceView"
          },
          {
            "type": "component",
            "name": "Agora-RTC-TextureView",
            "class": "io.agora.rtc.uni.AgoraRtcTextureView"
          }
        ]
    }
  ]
}

7.链接你的编译结果

在你的unibest项目下执行命令

bash 复制代码
pnpm build:app-android --mode production

然后把项目dist\build\app拷贝到项目的simpleDemo/assets/apps/<你项目的UNIAPP_ID>/www下。

如果你嫌每次拷贝麻烦,直接建立一个软链接过去就好(WINDOWS下不会?搜一下mklink怎么用)

最后一步,注意了,我就是在这里没操作正确导致卡了2天。

删除项目下的simpleDemo/build目录,然后

A)出基座,使用Build -> Build App Bundle(s)/APK(s)

B)出release,使用Build -> Generate Singed App Bundle /APK

如果你的操作正确,后面接入代码后HBuilder启动时就不会出现下面报错:

JS Framework\] 当前运行的基座不包含原生插件\[Agora-RTC-ChannelModule\],请在manifest中配置该插件,重新制作包括该原生插件的自定义运行基座 \[JS Framework\] 当前运行的基座不包含原生插件\[Agora-RTC-EngineModule\],请在manifest中配置该插件,重新制作包括该原生插件的自定义运行基座 #### 8.接入TypeScript组件 下一步要接入代码了,但是unibest是Typescript代码,Agora-RTC_3.7.0_example里的就不顶用了。实际上,在官网github里有一份typescript代码,只是没放到发布包里。从github里把整个项目下下来,找到src/components,把整个目录放到unibest项目的src/components下。在VSCode里看上去的文件是这样: ![](https://i-blog.csdnimg.cn/direct/90aab1cff0c14098b3b8c87f059b17dd.png) #### 9.引入组件 然后就可以在语音界面开始调用了,script里引入组件 ```TypeScript import RtcEngine, { RtcChannel } from '../../components/Agora-RTC-JS/index' import { ClientRole, ChannelProfile } from '../../components/Agora-RTC-JS/common/Enums' ``` 10.定义rtcEngine APP这里定义变量简单点,只需要定义好rtcEngine即可 ```TypeScript let rtcEngine: RtcEngine ``` 11.初始化引擎 申请录音权限是自己的框架代码,您可以自己封装一下。然后就是收听其它人员,加入频道等。这里就不一一解释了,加入频道支持雪花ID需要使用joinChannelWithUserAccount。代码在下面 ```TypeScript if (uni.getSystemInfoSync().platform === 'android') { // 华为市场规范,先申请权限 await requestPermission('RECORD', '用于听美丽的歌声啊啊啊啊') } rtcEngine = await RtcEngine.create(groupVoiceConf.appId) // 创建引擎 await rtcEngine.enableAudio() // 收听其它伙伴的发言 await rtcEngine.setChannelProfile(ChannelProfile.LiveBroadcasting) await rtcEngine.setClientRole(ClientRole.Broadcaster) await rtcEngine.joinChannelWithUserAccount( groupVoiceConf.token, groupId.toString(), currentUserId.toString() ) await rtcEngine.enableLocalAudio(false) // 默认进入频道麦克风是开启的,需要关闭 ``` 12.上/下麦 代码如下 ```TypeScript await rtcEngine.enableLocalAudio(true) // 上麦 await rtcEngine.enableLocalAudio(false) // 下麦 ``` 12.离开频道 ```TypeScript if (rtcEngine) await rtcEngine.leaveChannel() ``` ### IOS接入(略)

相关推荐
Wect10 小时前
LeetCode 130. 被围绕的区域:两种解法详解(BFS/DFS)
前端·算法·typescript
Dilettante25810 小时前
这一招让 Node 后端服务启动速度提升 75%!
typescript·node.js
jonjia1 天前
模块、脚本与声明文件
typescript
jonjia1 天前
配置 TypeScript
typescript
jonjia1 天前
TypeScript 工具函数开发
typescript
jonjia1 天前
注解与断言
typescript
jonjia1 天前
IDE 超能力
typescript
jonjia1 天前
对象类型
typescript
jonjia1 天前
快速搭建 TypeScript 开发环境
typescript
jonjia1 天前
TypeScript 的奇怪之处
typescript