Uniapp 安卓实现讯飞语音听写(复制即用)
在移动应用开发中,语音交互功能能够极大提升用户体验,让操作更加便捷自然。讯飞语音听写技术凭借其高准确率和稳定性,成为众多开发者的选择。本文将详细介绍如何在 Uniapp 项目中,实现安卓端的讯飞语音听写功能,帮助你快速为应用增添实用的语音交互能力。
但是,由于uniapp录音管理器 uni.getRecorderManager()的实时监听音频大小帧的功能onFrameRecorded不支持app,app端只能在录音结束后获取临时录音文件,因此需要把录音文件转成base64,在切片传输给讯飞的接口。
一、准备工作
1. 注册讯飞开放平台账号
首先,你需要前往讯飞开放平台注册账号,完成实名认证。认证通过后,你将获得使用讯飞相关服务的权限。
2. 创建应用并获取 AppID 和密钥
在讯飞开放平台控制台中,创建一个新的应用。创建成功后,你会得到该应用的 AppID、AppKey 和 AppSecret,这些信息在后续集成过程中至关重要,用于验证应用身份。
二、实现代码
以下是已经实现的uniapp在app端的一个简单的利用讯飞语音听写api完成的语音识别的demo,复制代码到你的项目中,把你申请的appid、apiSecret、apiKey替换到代码中,即可运行识别。
<template><div class="asr"><button class="btn" shape="circle" type="info" @touchstart="openMedia" @touchend="stopMedia">按住说话</button><view v-if="show" class="iating"><text text="正在说话中...." color="#49ABFE" size="27rpx" line-height="60rpx" align="center"></text></view></div>
</template><script>
import CryptoJS from "crypto-js";export default {data() {return {config: {hostUrl: "wss://iat-api.xfyun.cn/v2/iat",host: "iat-api.xfyun.cn",appid: "申请的讯飞appid",apiSecret: "申请的讯飞apiSecret",apiKey: "申请的apiKey",uri: "/v2/iat",highWaterMark: 1280,},uniSocketTask: null,show: false,resultText: "",resultTextTemp: "",renderText: ""};},methods: {// 鉴权签名getAuthStr(date) {let signatureOrigin = `host: ${this.config.host}\ndate: ${date}\nGET ${this.config.uri} HTTP/1.1`;let signatureSha = CryptoJS.HmacSHA256(signatureOrigin, this.config.apiSecret);let signature = CryptoJS.enc.Base64.stringify(signatureSha);let authorizationOrigin =`api_key="${this.config.apiKey}", algorithm="hmac-sha256", headers="host date request-line", signature="${signature}"`;let authStr = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(authorizationOrigin));return authStr;},getUrl() {let date = new Date().toUTCString();let wssUrl =this.config.hostUrl +"?authorization=" +this.getAuthStr(date) +"&date=" +encodeURIComponent(date) +"&host=" +this.config.host;console.log("websocke科大讯飞的地址为", wssUrl);return wssUrl;},// 打开麦克风openMedia() {this.connectSocket();},// 创建连接并返回数据connectSocket() {if (this.uniSocketTask === null) {this.uniSocketTask = uni.connectSocket({url: this.getUrl(),success() {},});this.uniSocketTask.onOpen(() => {console.log("监听到开启连接成功");this.startRecord();});this.uniSocketTask.onClose(() => {console.log("监听到关闭连接成功");this.uniSocketTask = null;});this.uniSocketTask.onError(() => {console.log("监听到连接发生错误");});this.uniSocketTask.onMessage((res) => {const message = JSON.parse(res.data);if (res.data) {console.log("收到服务器消息,并开始渲染", message);this.renderResult(message);if (message.code === 0 && message.data.status === 2) {console.log('最后一条', this.renderText);this.closeSocket();// 注意:这里需要根据实际情况处理事件触发// this.$emit('renderText', this.renderText);}if (message.code !== 0) {this.closeSocket();console.error(message);}} else {console.log("未监听到消息:原因:", JSON.stringify(res));}});} else {console.log("socketTask实例已存在");}},// 发送给科大讯飞的第一帧的模板数据格式getInitialFrame() {return {common: {app_id: this.config.appid,},business: {language: "zh_cn",domain: "iat",accent: "mandarin",dwa: "wpgs", // 可选参数,动态修正vad_eos: 5000,},data: {status: 0,format: "audio/L16;rate=16000",encoding: "lame"},};},// 发送消息sendMessage(sendData) {console.log('发送', JSON.stringify(sendData));this.uniSocketTask.send({data: JSON.stringify(sendData),success() {},fail() {console.log("发送失败");},});},// 关闭连接closeSocket() {console.log("开始尝试关闭连接");this.uniSocketTask.close();},// 开启录音startRecord() {const recordOption = {sampleRate: 16000,format: "mp3",};const recordManager = uni.getRecorderManager();recordManager.onStart(() => {console.log("开始录音");this.show = true;});recordManager.onStop((res) => {console.log("录音停止,文件路径为:", res.tempFilePath);this.sendMessage(this.getInitialFrame());this.pathToBase64(res.tempFilePath).then(base64 => {let buff = base64.split(",")[1];const arrayBuffer = uni.base64ToArrayBuffer(buff);const audioString = this.toString(arrayBuffer);console.log("文件读取成功", audioString.length);let offset = 0;while (offset < audioString.length) {const subString = audioString.substring(offset, offset + 1280);offset += 1280;const isEnd = offset >= audioString.length;let params = {data: {status: isEnd ? 2 : 1,format: "audio/L16;rate=16000",encoding: "lame",audio: btoa(subString)}};this.sendMessage(params);}}).catch(error => {console.error(error);});});recordManager.onError((err) => {console.log("录音出现错误", err);});recordManager.start(recordOption);},// 关闭录音stopMedia() {const recordManager = uni.getRecorderManager();recordManager.stop();this.show = false;},// 工具方法toString(buffer) {var binary = '';var bytes = new Uint8Array(buffer);var len = bytes.byteLength;for (var i = 0; i < len; i++) {binary += String.fromCharCode(bytes[i]);}return binary;},// 录音文件路径转base64pathToBase64(path) {return new Promise((resolve, reject) => {if (typeof plus === 'object') {plus.io.resolveLocalFileSystemURL(path, function(entry) {entry.file(function(file) {var fileReader = new plus.io.FileReader();fileReader.onload = function(evt) {resolve(evt.target.result);};fileReader.onerror = function(error) {reject(error);};fileReader.readAsDataURL(file);}, function(error) {reject(error);});}, function(error) {reject(error);});return;}reject(new Error('not support'));});},// 讯飞回复字段拼接renderResult(jsonData) {if (jsonData.data && jsonData.data.result) {let data = jsonData.data.result;let str = "";let ws = data.ws;for (let i = 0; i < ws.length; i++) {str = str + ws[i].cw[0].w;}if (data.pgs) {if (data.pgs === "apd") {this.resultText = this.resultTextTemp;}this.resultTextTemp = this.resultText + str;} else {this.resultText = this.resultText + str;}this.renderText = this.resultTextTemp || this.resultText || "";}console.log("渲染后的数据为", this.renderText);}}
}
</script><style scoped>
.asr {display: flex;justify-content: center;padding: 20rpx;
}.btn {width: 200rpx;height: 200rpx;
}.iating {position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);display: flex;flex-direction: column;align-items: center;background-color: rgba(0, 0, 0, 0.7);padding: 30rpx;border-radius: 20rpx;z-index: 999;
}</style>
相关文章:
Uniapp 安卓实现讯飞语音听写(复制即用)
在移动应用开发中,语音交互功能能够极大提升用户体验,让操作更加便捷自然。讯飞语音听写技术凭借其高准确率和稳定性,成为众多开发者的选择。本文将详细介绍如何在 Uniapp 项目中,实现安卓端的讯飞语音听写功能,帮助你…...
【FileZilla】 从事件类型到消息类型的函数形参类型转化
本篇其实是前篇【Filezilla】 dispatch函数重载的例子-CSDN博客的一个补充,其中涉及到【FileZilla】事件调用机制代码解析-CSDN博客中的事件分发机制时钩子函数的参数传递怎么实现的。跟【FileZilla】sftp协议的数据传输上传和下载-CSDN博客同样,用事件是…...
python打卡day26
函数、参数、变量 知识点回顾: 函数的定义变量作用域:局部变量和全局变量函数的参数类型:位置参数、默认参数、不定参数传递参数的手段:关键词参数传递参数的顺序:同时出现三种参数类型时 def function_name(parameter…...
RPC框架源码分析学习(二)
RPC框架源码分析与原理解读 前言 在分布式系统开发中,远程过程调用(RPC)是一项基础且关键的技术。通过对KVstorageBaseRaft-cpp项目RPC模块的源码分析,我深入理解了RPC框架的工作原理和实现细节。本文将从程序员视角分享我的学习心得。 框架概述 本项…...
算法分析:蛮力法
一、实验目的 1 掌握蛮力法的设计思想(利用计算机去穷举所有的可能解,再从中依次找出可行解) 2 掌握蛮力法的具体实现和时间复杂度分析 3 理解蛮力法的常见特性 实验要求:先用伪代码描述利用蛮力法解决的算法解决方案,再用程序实现,计算时间…...
构建RAG混合开发---PythonAI+JavaEE+Vue.js前端的实践
写在前文:之所以设计这一套流程,是因为 Python在前沿的科技前沿的生态要比Java好,而Java在企业级应用层开发比较活跃; 毕竟许多企业的后端服务、应用程序均采用Java开发,涵盖权限管理、后台应用、缓存机制、中间件集成…...
游戏引擎学习第280天:精简化的流式实体sim
回顾并为今天的内容做铺垫 今天的任务是让之前关于实体存储方式的改动真正运行起来。我们现在希望让实体系统变得更加真实和实用,能够支撑我们游戏实际所需的功能。这就要求我们对它进行更合理的实现和调试。 昨天我们基本让代码编译通过了,但实际上还…...
小程序映射逻辑处理
onLoad: function (options) { // 如果直接从options获取数据 this.setData({ jielunpin:发羽音, birthStr: 1944-01-01 }); // 处理诊断结论 this.processJielunpin(); // 添加一个处理诊断结论的函数 processJielunpin: function() { // 获取jielunpin和birthSt…...
亚马逊,temu测评采购低成本养号策略:如何用一台设备安全批量管理买家账号
只要能够巧妙规避平台的检测和风控措施,测评便可安全进行。 自养号测评,它更便于卖家掌控,且能降低风险。现在很多卖家都是自己养号,自己养号都是精养,不是自动的机刷,买家账号掌握在自己手里,更…...
TCP实现安全传输的核心机制 + TCP的报文讲解(全程图文讲解)
目录 一、TCP的协议和数据报格式 二、TCP常见的核心机制 1. 确认应答 2. 超时重传 3. 连接管理 三次握手(建立连接) 四次挥手(断开连接) 常见的状态和整体的传输流程 4. 滑动窗口 5. 流量控制 6. 拥塞控制 7. 延迟应…...
【测试工具】selenium和playwright如何选择去构建自动化平台
构建UI自动化平台服务,在底层选择自动化框架,selenium和playwright这两个如何选择 在构建UI自动化平台服务时,选择底层自动化框架(如 Selenium 和 Playwright)是一个非常关键的决策,直接影响平台的性能、可…...
ES常识8:ES8.X如何实现热词统计
文章目录 一、数据采集与存储设计1. 确定需记录的字段2. 设计搜索日志索引 二、数据写入与采集三、热门搜索词统计(核心逻辑)1. 基础版:近 7 天热门搜索词(按出现次数排序)2. 进阶版:加权热门词(…...
可解释性AI 综述《Explainable AI for Industrial Fault Diagnosis: A Systematic Review》
一、研究背景与动因(Background & Motivation) 随着工业4.0与工业5.0的发展,工业生产越来越依赖自动化与智能化手段,以实现高效、预测性维护与运行优化。在这一背景下,人工智能(AI)与机器学…...
数据可视化-----子图的绘制及坐标轴的共享
目录 绘制固定区域的子图 (一)、绘制单子图 subplot()函数 Jupyter Notebook的绘图模式 (二)、多子图 subplots()--可以在规划好的所有区域中一次绘制多个子图 (三)、跨行跨列 subplot2grid()---将整…...
nginx 配置
proxy_pass 结尾斜杠规则 不带斜杠:保留原始请求路径。 location /api {proxy_pass http://backend; # 转发到 http://backend/api }带斜杠:剥离 location 匹配的路径前缀。 location /api/ {proxy_pass http://backend/; # 转发到 http://back…...
《从零开始入门递归算法:搜索与回溯的核心思想 + 剑指Offer+leetcode高频面试题实战(含可视化图解)》
一.递归 1.汉诺塔 题目链接:面试题 08.06. 汉诺塔问题 - 力扣(LeetCode) 题目解析:将A柱子上的盘子借助B柱子全部移动到C柱子上。 算法原理:递归 当A柱子上的盘子只有1个时,我们可以直接将A上的盘子直…...
船舶制造业数字化转型:驶向智能海洋新航道
在全球海洋经济蓬勃发展的当下,船舶制造业作为海洋产业的重要支柱,正面临着前所未有的机遇与挑战。船舶制造周期长、技术复杂,从设计图纸到最终交付,涉及成千上万的零部件和复杂的工艺流程,传统制造模式已难以满足市场…...
SpringBoot 自动装配流程
Spring Boot 的自动装配(Auto Configuration)是其最核心的特性之一,它让你能“开箱即用”,极大简化了配置。下面是 Spring Boot 自动装配的整体流程(从启动到生效) 的详细解析: ✅ 一、整体流程…...
Vue 3 实现后端 Excel 文件流导出功能(Blob 下载详解)
💡 本文以告警信息导出为例,介绍 Vue 3 中如何通过 Axios 调用后端接口并处理文件流,实现 Excel 自动下载功能。 📑 目录 一、前言 二、后端接口说明 三、前端实现思路 四、导出功能完整代码 五、常见问题处理 六、效果展示 …...
基于IBM BAW的Case Management进行项目管理示例
说明:使用IBM BAW的难点是如何充分利用其现有功能根据实际业务需要进行设计,本文是示例教程,因CASE Manager使用非常简单,这里重点是说明如何基于CASE Manager进行项目管理,重点在方案设计思路上,其中涉及的…...
《Python星球日记》 第78天:CV 基础与图像处理
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、计算机视觉(CV)简介1. 什么是计算机视觉?2. 计算机视觉的应用场景3. 图像的基本属性a》像素(Pixel)b》通道(Channel)c》分辨率(Res…...
Google DeepMind 推出AlphaEvolve
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
Flink 1.13.2 日志配置优化:保留最近 7 天日志文件
Flink 1.13.2 日志配置优化:保留最近 7 天日志文件 在使用 Apache Flink 1.13.2 进行流处理任务时,合理的日志配置对于作业的监控、调试和故障排查至关重要。本文将介绍如何通过修改log4j.properties文件,将 Flink 的默认日志配置升级为保留最近 7 天的日志文件配置,并解决…...
【优化算法】协方差矩阵自适应进化策略(Covariance Matrix Adaptation Evolution Strategy,CMA-ES)
CMA-ES(Covariance Matrix Adaptation Evolution Strategy)算法是一种无导数、基于多元正态分布的迭代优化方法,通过自适应地调整搜索分布的均值、协方差矩阵和步长,能够高效地解决非线性、非凸的连续优化问题。 算法以最大似然和…...
基于Leaflet和天地图的免费运动场所WebGIS可视化-以长沙市为例
目录 前言 一、免费运动场所数据整理 1、本地宝数据简介 2、Java后台数据解析 二、Leaflet前端地图展示 1、基础数据准备 2、具体位置及属性标记 三、成果展示 1、空间位置分布 2、东风路立交桥运动公园 3、芙蓉区花侯路浏阳河大桥下方 4、梅岭国际小区 5、湖南大学…...
399. 除法求值
https://leetcode.cn/problems/evaluate-division/description/?envTypestudy-plan-v2&envIdtop-interview-150思路:读完题后我们可以发现这题的考察已经很明确了就是考我们矩阵,我们将矩阵构建出来后,这题就变成可达性分析题了。 所以解…...
QMK固件OLED显示屏配置教程:从零开始实现个性化键盘显示(实操部分)
QMK固件OLED显示屏配置教程:从零开始实现个性化键盘显示 📢 前言: 作为一名键盘爱好者,近期研究了QMK固件的OLED显示屏配置,发现网上的教程要么太过复杂,要么过于简单无法实际操作。因此决定写下这篇教程,从零基础出发,带大家一步步实现键盘OLED屏幕的配置与个性化显示…...
深度解析 Meta 开源 MR 项目《North Star》:从交互到渲染的沉浸式体验设计
🌌 一、项目概览:什么是 North Star? North Star 是由 Meta 官方推出并开源 的一款面向 Meta Quest 平台 的混合现实(MR)视觉演示项目。它不仅上线了 Horizon Store,更以完整的技术栈与高质量内容向开发者展示了如何在 VR/MR 设备上实现“视觉上限”和“交互潜力”的结…...
使用VS Code通过SSH编译Linux上的C++程序
引言 在软件开发领域,跨平台开发是一项常见需求。特别是对于C开发者来说,有时需要在Windows环境下编写代码,但却需要在Linux环境中编译和运行。这种情况在系统编程、嵌入式开发或高性能计算领域尤为常见。 Visual Studio Code (VS Code) 提…...
Datawhale 5月llm-universe 第2次笔记
第二章 使用 LLM API 开发应用 名词解释 Temperature 参数/场景低 Temperature(0 ~ 0.3)高 Temperature(0.7 ~ 1.0)输出特点保守、稳定、可预测创造性强、多样化、不可预测语言模型行为更少的随机性,倾向于选择高概…...
【Vue】CSS3实现关键帧动画
关键帧动画 两个重点keyframesanimation子属性 实现案例效果展示: 两个重点 keyframes 和 animation 作用:通过定义关键帧(keyframes)和动画(animation)规则,实现复杂的关键帧动画。 keyframes 定义动画的关键帧序列…...
Spring 模拟转账开发实战
一、转账业务场景分析 转账是金融类应用的核心场景之一,涉及付款方扣减金额和收款方增加金额两个关键操作。在开发中需解决以下问题: 业务层与数据层解耦:通过分层架构(Service 层调用 Dao 层)实现逻辑分离。数据库事…...
Baklib内容中台赋能资源管理升级
内容中台驱动管理升级 在数字化转型进程中,企业级内容管理工具的效能直接影响资源协同效率。以全渠道资源整合为核心的内容中台,通过集中化处理文档、FAQ及社区论坛等非结构化数据,有效解决信息孤岛问题。例如,某金融集团通过部署…...
数据结构(九)——排序
一、排序的基本概念 1.排序:重新排列表中的元素,使表中的元素满足按关键字有序 2.稳定性:Ri和Rj相对位置保持不变 3.内部排序:指在排序期间元素全部存在内存中的排序(比较和移动),如插入排序…...
MinerU安装(pdf转markdown、json)
在Windows上安装MinerU,参考以下几个文章,可以成功安装,并使用GPU解析。 整体安装教程: MinerU本地化部署教程——一款AI知识库建站的必备工具 其中安装conda的教程: 一步步教你在 Windows 上轻松安装 Anaconda以及使…...
Spring框架核心技术深度解析:JDBC模板、模拟转账与事务管理
一、JDBC模板技术:简化数据库操作 在传统JDBC开发中,繁琐的资源管理和重复代码一直是开发者的痛点。Spring框架提供的 JDBC模板(JdbcTemplate) 彻底改变了这一现状,它通过封装底层JDBC操作,让开发者仅需关注SQL逻辑&a…...
LCD电视LED背光全解析:直下式 vs 侧光式、全局调光 vs 局部调光与HDR体验
Abstract: This article explores the various types of LED backlighting used in televisions and monitors. It categorizes backlight systems based on structural design—direct-lit and edge-lit—as well as by dimming technology—global dimming and local dimmin…...
ET EntityRef EntityWeakRef 类分析
EntityRef EntityWeakRef 相同点 也是这两个的作用:这两个都是用来表示一个实体引用。一般来说使用一个对象,直接持有对象就可以,但是如果对象来自于对象池,这个时候直接持有对象不合适,对象可能已经被对象池回收&…...
Python----神经网络(基于DNN的风电功率预测)
一、基于DNN的风电功率预测 1.1、背景 在全球能源转型的浪潮中,风力发电因其清洁和可再生的特性而日益重要。然而,风力发电功率的波动性给电网的稳定运行和能源调度带来了挑战。准确预测风力发电机的功率输出,对于优化能源管理、提高电网可靠…...
Web前端入门:JavaScript 的应用领域
截至目前,您应该对前端的 HTML CSS 应该有了很清楚的认知,至少实现一个静态网页已经完全不在话下了。 当然,CSS 功能绝不止这些,一些不太常用的 CSS 相关知识,后续将通过案例进行分享。 那么咱们接下来看看 JavaScrip…...
实用工具:微软软件PowerToys(完全免费),实现多台电脑共享鼠标和键盘(支持window系统)
实用工具:微软软件 PowerToys 让多台电脑共享鼠标和键盘 在如今的数字化办公与生活场景中,我们常常会面临同时使用多台电脑的情况。例如,办公时可能一台电脑用于处理工作文档,另一台用于运行专业软件或查看资料;家庭环…...
精益数据分析(61/126):移情阶段评分体系构建与实战案例解析
精益数据分析(61/126):移情阶段评分体系构建与实战案例解析 在创业的移情阶段,如何科学评估用户需求的真实性与紧迫性,是决定后续产品方向的关键。今天,我们结合《精益数据分析》中的评分框架,…...
面试题:介绍一下JAVA中的反射机制
什么是反射机制? Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性。这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的…...
yarn任务筛选spark任务,判断内存/CPU使用超过限制任务
yarn任务筛选spark任务,判断内存/CPU使用超过限制任务 curl -s “http://it-cdh-node01:8088/ws/v1/cluster/apps?statesRUNNING” | jq ‘select(.apps.app[].applicationType “SPARK”) | .apps.app[].id’ | xargs -I {} curl -s “http://it-cdh-node01:808…...
ArcGIS Pro地块图斑顺序编号(手绘线顺序快速编号)-004
ArcGIS全系列实战视频教程——9个单一课程组合系列直播回放_arcgis初学者使用视频-CSDN博客 4大遥感软件!遥感影像解译!ArcGISENVIErdaseCognition_遥感解译软件-CSDN博客 今天介绍一下在ArcGIS Pro地块图斑顺序编号(手绘线顺序快速编号&am…...
红黑树解析
目录 一、引言 二、红黑树的概念与性质 2.1 红黑树的概念 2.2 红黑树的性质 三、红黑树的节点定义与结构 3.1 节点定义 四、红黑树的插入操作 4.1 插入步骤 4.2 插入代码实现 五、红黑树的验证 5.1 验证步骤 5.2 验证代码实现 六、红黑树迭代器的实现 6.1 迭代器的…...
在线文档管理系统 spring boot➕vue|源码+数据库+部署教程
📌 一、项目简介 本系统采用Spring Boot Vue ElementUI技术栈,支持管理员和员工两类角色,涵盖文档上传、分类管理、公告发布、员工资料维护、部门岗位管理等核心功能。 系统目标是打造一个简洁高效的内部文档管理平台,便于员工…...
Python3 简易DNS服务器实现
使用Python3开发一个简单的DNS服务器,支持配置资源记录(RR),并能通过dig命令进行查询。 让自己理解DNS原理 实现方案 我们将使用socketserver和dnslib库来构建这个DNS服务器。dnslib库能帮助我们处理DNS协议的复杂细节。 1. 安装依赖 首先确保安装了d…...
雾锁王国开服联机教程-专用服务器
一。阿里云服务器搭建 服务器地址:1分钟畅玩!一键部署联机服务器 《雾锁王国(Enshrouded)》融合了生存、制作以及动作 RPG 战斗,游戏背景设定在了一个基于体素构筑的辽阔大陆。无论是攀登山脉还是跨越沙漠࿰…...
鸿蒙OSUniApp 开发的一键分享功能#三方框架 #Uniapp
使用 UniApp 开发的一键分享功能 在移动应用开发中,分享功能几乎是必不可少的一环。一个好的分享体验不仅能带来更多用户,还能提升产品的曝光度。本文将详细讲解如何在 UniApp 框架下实现一个简单高效的一键分享功能,适配多个平台。 各平台分…...