From 6356b071aca573a5b73f7f08083efc6517f4ff63 Mon Sep 17 00:00:00 2001 From: fanpeng <438123081@qq.com> Date: Thu, 19 Jun 2025 10:18:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=8F=91=E9=80=81?= =?UTF-8?q?=E8=AF=AD=E9=9F=B3=E7=9B=B8=E5=85=B3=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 2 +- manifest.json | 211 +++++++++--------- pages/p2p/p2pPlayer.vue | 132 ++++++++++- .../utssdk/app-android/index.uts | 81 +++++++ 4 files changed, 319 insertions(+), 107 deletions(-) diff --git a/App.vue b/App.vue index 2bfcb22..04a7a20 100644 --- a/App.vue +++ b/App.vue @@ -31,7 +31,7 @@ return 'XHJ' } // #endif - return 'XHJ' + return 'DEV' } }, computed: { diff --git a/manifest.json b/manifest.json index 4d30de7..3387736 100644 --- a/manifest.json +++ b/manifest.json @@ -1,110 +1,113 @@ { - "name": "星星锁Lite", - "appid": "__UNI__933D519", - "description": "", - "versionName": "1.3.0", - "versionCode": "37", - "mp-weixin": { - "appid": "wx9829a39e65550757", - "setting": { - "urlCheck": true, - "minified": true - }, - "permission": { - "scope.bluetooth": { - "desc": "蓝牙将用于控制和管理您的智能门锁" - } - }, - "usingComponents": true, - "lazyCodeLoading": "requiredComponents", - "optimization": { - "subPackages": true - }, - "plugins": { - "wmpf-voip": { - "version": "latest", - "provider": "wxf830863afde621eb", - "genericsImplementation": { - "call-page-plugin": { - "custombox": "pages/main/customBox" - } - } - } - } - }, - "vueVersion": "3", - "app-plus": { - "distribute": { - "icons": { - "android": { - "hdpi": "unpackage/res/icons/72x72.png", - "xhdpi": "unpackage/res/icons/96x96.png", - "xxhdpi": "unpackage/res/icons/144x144.png", - "xxxhdpi": "unpackage/res/icons/192x192.png" + "name" : "星星锁Lite", + "appid" : "__UNI__933D519", + "description" : "", + "versionName" : "1.3.0", + "versionCode" : "37", + "mp-weixin" : { + "appid" : "wx9829a39e65550757", + "setting" : { + "urlCheck" : true, + "minified" : true }, - "ios": { - "appstore": "unpackage/res/icons/1024x1024.png", - "ipad": { - "app": "unpackage/res/icons/76x76.png", - "app@2x": "unpackage/res/icons/152x152.png", - "notification": "unpackage/res/icons/20x20.png", - "notification@2x": "unpackage/res/icons/40x40.png", - "proapp@2x": "unpackage/res/icons/167x167.png", - "settings": "unpackage/res/icons/29x29.png", - "settings@2x": "unpackage/res/icons/58x58.png", - "spotlight": "unpackage/res/icons/40x40.png", - "spotlight@2x": "unpackage/res/icons/80x80.png" - }, - "iphone": { - "app@2x": "unpackage/res/icons/120x120.png", - "app@3x": "unpackage/res/icons/180x180.png", - "notification@2x": "unpackage/res/icons/40x40.png", - "notification@3x": "unpackage/res/icons/60x60.png", - "settings@2x": "unpackage/res/icons/58x58.png", - "settings@3x": "unpackage/res/icons/87x87.png", - "spotlight@2x": "unpackage/res/icons/80x80.png", - "spotlight@3x": "unpackage/res/icons/120x120.png" - } + "permission" : { + "scope.bluetooth" : { + "desc" : "蓝牙将用于控制和管理您的智能门锁" + } + }, + "usingComponents" : true, + "lazyCodeLoading" : "requiredComponents", + "optimization" : { + "subPackages" : true + }, + "plugins" : { + "wmpf-voip" : { + "version" : "latest", + "provider" : "wxf830863afde621eb", + "genericsImplementation" : { + "call-page-plugin" : { + "custombox" : "pages/main/customBox" + } + } + } } - }, - "android": { - "permissions": [ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - ] - }, - "ios": { - "dSYMs": false - } }, - "modules": { - "Bluetooth": {}, - "VideoPlayer": {}, - "LivePusher": {}, - "Camera": {}, - "Record": {} - }, - "splashscreen": { - "waiting": false + "vueVersion" : "3", + "app-plus" : { + "distribute" : { + "icons" : { + "android" : { + "hdpi" : "unpackage/res/icons/72x72.png", + "xhdpi" : "unpackage/res/icons/96x96.png", + "xxhdpi" : "unpackage/res/icons/144x144.png", + "xxxhdpi" : "unpackage/res/icons/192x192.png" + }, + "ios" : { + "appstore" : "unpackage/res/icons/1024x1024.png", + "ipad" : { + "app" : "unpackage/res/icons/76x76.png", + "app@2x" : "unpackage/res/icons/152x152.png", + "notification" : "unpackage/res/icons/20x20.png", + "notification@2x" : "unpackage/res/icons/40x40.png", + "proapp@2x" : "unpackage/res/icons/167x167.png", + "settings" : "unpackage/res/icons/29x29.png", + "settings@2x" : "unpackage/res/icons/58x58.png", + "spotlight" : "unpackage/res/icons/40x40.png", + "spotlight@2x" : "unpackage/res/icons/80x80.png" + }, + "iphone" : { + "app@2x" : "unpackage/res/icons/120x120.png", + "app@3x" : "unpackage/res/icons/180x180.png", + "notification@2x" : "unpackage/res/icons/40x40.png", + "notification@3x" : "unpackage/res/icons/60x60.png", + "settings@2x" : "unpackage/res/icons/58x58.png", + "settings@3x" : "unpackage/res/icons/87x87.png", + "spotlight@2x" : "unpackage/res/icons/80x80.png", + "spotlight@3x" : "unpackage/res/icons/120x120.png" + } + } + }, + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + "ios" : { + "dSYMs" : false + } + }, + "modules" : { + "Bluetooth" : {}, + "VideoPlayer" : {}, + "LivePusher" : {}, + "Camera" : {}, + "Record" : {} + }, + "splashscreen" : { + "waiting" : false + } } - } } diff --git a/pages/p2p/p2pPlayer.vue b/pages/p2p/p2pPlayer.vue index 44a4fba..5b7c020 100644 --- a/pages/p2p/p2pPlayer.vue +++ b/pages/p2p/p2pPlayer.vue @@ -187,7 +187,14 @@ // #endif // #ifdef APP-PLUS - import { startService, getLiveUrl, stopService } from '@/uni_modules/xhj-tencent-xp2p' + import { + startService, + getLiveUrl, + stopService, + runSendService, + stopSendService, + dataSend + } from '@/uni_modules/xhj-tencent-xp2p' // #endif const $bluetooth = useBluetoothStore() @@ -223,6 +230,8 @@ onMounted(async () => { // #ifdef APP-PLUS isApp.value = true + // 初始化录音管理器 + initRecorder() // #endif // #ifdef MP-WEIXIN @@ -268,6 +277,11 @@ }) if (urlResult.code === 0) { url.value = urlResult.data.url + runSendService( + `${deviceInfo.value.productId}/${deviceInfo.value.deviceName}`, + 'channel=0', + true + ) handlePlaySuccess() } else { $basic.backAndToast(message) @@ -284,6 +298,12 @@ onUnload(() => { // #ifdef APP-PLUS + // 停止录音 + if (isVoice.value && recorderManager.value) { + stopRecording() + } + + stopSendService(`${deviceInfo.value.productId}/${deviceInfo.value.deviceName}`) stopService({ id: `${deviceInfo.value.productId}/${deviceInfo.value.deviceName}` }) @@ -460,6 +480,103 @@ return false } + // #ifdef APP-PLUS + const recorderManager = ref(null) + const recordingFilePath = ref('') + // #endif + + const convertAudioFileToUint8Array = filePath => { + // #ifdef APP-PLUS + try { + plus.io.resolveLocalFileSystemURL(filePath, entry => { + entry.file( + file => { + console.log(11111, file) + if (file.size === 0) return + + const fileReader = new plus.io.FileReader() + + fileReader.onloadend = async evt => { + try { + const base64 = evt.target.result.split(',')[1] + + const binaryString = atob(base64) + const byteArray = [] + + for (let i = 0; i < binaryString.length; i++) { + byteArray[i] = binaryString.charCodeAt(i) + } + + const id = `${deviceInfo.value.productId}/${deviceInfo.value.deviceName}` + + await dataSend(id, byteArray) + } catch (error) { + console.error('音频数据转换失败:', error) + } + } + + fileReader.onerror = () => { + console.error('音频文件读取失败') + } + + fileReader.readAsDataURL(file) + }, + error => console.error('获取文件对象失败:', error) + ) + }) + } catch (error) { + console.error('音频文件处理异常:', error) + } + // #endif + } + + const initRecorder = () => { + // #ifdef APP-PLUS + recorderManager.value = uni.getRecorderManager() + + recorderManager.value.onStart(() => { + console.log('录音开始') + }) + + recorderManager.value.onError(error => { + console.error('录音出错:', error) + }) + + recorderManager.value.onStop(res => { + console.log('录音结束:', res) + recordingFilePath.value = res.tempFilePath + + convertAudioFileToUint8Array(res.tempFilePath) + }) + // #endif + } + + // 开始录音 + const startRecording = () => { + // #ifdef APP-PLUS + if (!recorderManager.value) { + initRecorder() + } + + recorderManager.value.start({ + duration: 60000, + sampleRate: 16000, + format: 'aac' + }) + console.log('开始录音') + // #endif + } + + // 停止录音 + const stopRecording = () => { + // #ifdef APP-PLUS + if (recorderManager.value) { + recorderManager.value.stop() + console.log('停止录音') + } + // #endif + } + const toggleVoice = () => { // #ifdef MP-WEIXIN if (isVoice.value) { @@ -479,7 +596,18 @@ } } // #endif - console.log(1111) + // #ifdef APP-PLUS + if (isVoice.value) { + isVoice.value = false + + stopRecording() + } else { + uni.vibrateLong() + isVoice.value = true + // 初始化并开始录音 + startRecording() + } + // #endif } const handlePlaySuccess = () => { diff --git a/uni_modules/xhj-tencent-xp2p/utssdk/app-android/index.uts b/uni_modules/xhj-tencent-xp2p/utssdk/app-android/index.uts index d5cad3d..c047467 100644 --- a/uni_modules/xhj-tencent-xp2p/utssdk/app-android/index.uts +++ b/uni_modules/xhj-tencent-xp2p/utssdk/app-android/index.uts @@ -77,3 +77,84 @@ export const stopService = async function (params: IdParams): Promise { // console.log(2, error) // } // } +export const runSendService = async function ( + id: string, + cmd: string, + crypto: boolean +): Promise { + try { + await XP2P.runSendService(id, cmd, crypto) + console.log('开始发送服务') + return { + code: 0, + data: {}, + message: '成功' + } + } catch (error) { + return { + code: -1, + data: {}, + message: error.toString() + } + } +} + +export const stopSendService = async function (id: string): Promise { + try { + await XP2P.stopSendService(id, null) + console.log('停止发送服务') + return { + code: 0, + data: {}, + message: '成功' + } + } catch (error) { + return { + code: -1, + data: {}, + message: error.toString() + } + } +} + +export const dataSend = async function (id: string, data: Array): Promise { + try { + let byteTest = new ByteArray((data.length + 7).toInt()) + byteTest.set(0, (0xff).toByte()) + byteTest.set(1, (0xf9).toByte()) + + let profile = 2 + let freqIdx = 8 + let chanCfg = 1 + let packetLen = data.length + 7 + + byteTest.set(2, (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2)).toByte()) + byteTest.set(3, (((chanCfg & 3) << 6) + (packetLen >> 11)).toByte()) + byteTest.set(4, ((packetLen & 0x7ff) >> 3).toByte()) + byteTest.set(5, (((packetLen & 7) << 5) + 0x1f).toByte()) + byteTest.set(6, (0xfc).toByte()) + + for (let i = 0; i < data.length; i++) { + byteTest.set((i + 7).toInt(), data[i].toByte()) + } + + console.log(byteTest) + console.log(1, id, byteTest[0], byteTest[1], (data.length + 7).toInt()) + + const result = await XP2P.dataSend(id, byteTest, (data.length + 7).toInt()) + + console.log('发送数据', result) + + return { + code: 0, + data: {}, + message: '成功' + } + } catch (error) { + return { + code: -1, + data: {}, + message: error.toString() + } + } +}