【Purple Pi OH RK3566鸿蒙开发板】OpenHarmony音频播放应用,真实体验感爆棚!
本文转载于Purple Pi OH开发爱好者,作者ITMING 。
原文链接:https://bbs.elecfans.com/jishu_2376383_1_1.html
01注意事项
-
DevEco Studio 4.0 Beta2(Build Version: 4.0.0.400)
-
OpenHarmony SDK API 9
-
创建工程类型选择Application
-
修改entry/build-profile.json5配置文件中的targets>runtimeOS为OpenHarmony,然后进行Sync Now(同步)
02工程概述
PPI有声是一款基于OpenHarmony API 9 开发的,运行于Purple Pi 开发板(安装OpenHarmony标准系统)的音频播放应用程序。
03场景化
-
智慧家居类(电子门铃,温湿度显示仪,屏显灯控开关等)
-
智慧办公类(打卡机,大屏显示等)
-
智慧教育类(电子班牌,校园大屏,电子讲台等)
04创建工程

-
Project name:工程名称
-
Bundle name:包名
-
Save location:工程存储路径
-
Compile SDK:编译API版本
-
Compatible SDK:兼容的最新API版本
-
Module name:模块名称
-
Model:模型
-
Enable Super Visual:是否启用低代码开发
-
Device Type:设备类型
-
Node:nodejs路径
05媒体服务
媒体子系统为开发者提供一套简单且易于理解的接口,使得开发者能够方便接入系统使用系统的媒体资源。
媒体子系统包含了音视频相关媒体业务,提供以下常用共功能:
-
音视频播放(AVPlayer)
-
音视频录制(AVRecorder)
5.1 AVPlayer概述
AVPlayer主要工作是将Audio/Video媒体资源(比如mp4/mp3/mkv/mpeg-ts等)转码为可供渲染的图像或可听见的模拟信号,并通过输出设备进行播放。
使用AVPlayer可以实现端到端播放原始媒体资源,播放对的全流程包含:创建AVPlayer,设置播放资源,设置播放参数 (音量/倍速/焦点模式),播放控制(播放/暂停/跳转/停止),重置,销毁资源。
开发过程中开发者可以通过AVPlayer的state属性主动获取当前状态或使用on('stateChange')方法监听状态变化。若应用在音频播放器处于错误状态时执行操作,系统可能会抛出异常或生成其他未定义的行为。

主:当播放处于
prepared/playing/paused/completed状态时,播放引擎处于工作状态,需要占用系统较多的运行内容。当客户端暂时不适用播放器时,调用reset()或release()回收内存资源。
5.2 开发步骤
-
导入media模块,调用
createAVPlayer()方法创建AVPlayer实例,AVPlayer初始化idle状态。 -
设置业务监听事件,搭配全流程场景使用,如监听播放器state属性改变的
stateChange;监听播放器错误信息的error;用于进度条,监听进度条长度,刷新资源时长的durationUpdate等。 -
设置资源:设置属性url,AVPlayer进入initialized状态
-
准备播放:调用prepare(),AVPlayer进入prepared状态,此时可以获取duration,设置音量。
-
音频播控:播放play(),暂停pause(),跳转seek(),停止stop()等操作。
-
调用reset()重置资源,AVPlayer重新进入idle状态,此时可更换播放源url。
-
调用release()销毁实例,AVPlayer进入released状态,退出播放。
06构建PPI有声
6.1 准备资源文件
-
音频文件拷贝到resources/rawfile目录
-
将拷贝到resources/base/mdiea目录
-
音频播放背景图audio_bg.png
-
音频播放旋转图audio.png
-
暂停ic_pause.svg
-
播放ic_play.svg

6.2 构建UI页面
整个UI以Flex弹性布局为主,子组件以列方式排列,分别为可旋转的音频播放控件,播放进度条以及播放控制按钮组成。
6.2.1 可旋转的音频播放控件
使用Stack堆叠布局容器为主,将旋转控件置于背景图之上。
Stack({ alignContent: Alignment.Center }) {Image($r('app.media.audio_bg')).width(200).height(200)Image($r('app.media.audio')).width(100).height(100).backgroundColor(Color.White).borderRadius(50).rotate({ angle: this.angleNum }).animation({duration: this.duration,tempo: 1,curve: Curve.Linear,iterations: -1,playMode: PlayMode.Normal})}
6.2.2 进度条
播放进度由置于上部的播放时长和总时长,底部的播放进度条组成,包裹在Column列容器中。
Column({ space: 4 }) {Row() {Text(this.msToS(this.currentProgress)).fontSize(12).fontColor(0xc1c3c5)Text(this.msToS(this.duration)).fontSize(12).fontColor(0xc1c3c5)}.width('100%').justifyContent(FlexAlign.SpaceBetween)// 播放进度条Slider({value: this.currentProgress,min: 0,max: this.duration,style: SliderStyle.OutSet}).showTips(true).onChange((value: number, mode: SliderChangeMode) => {this.currentProgress = value;// 跳转到指定位置播放this.avPlayer.seek(value);})}.width('90%')
6.2.3 播放控件
播放控件通过当前AVPlayer的状态判断显示播放/暂停图标按钮。
Row({ space: 10 }) {if (this.state === 'playing') {// 暂停Image($r('app.media.ic_pause')).width(64).height(64).fillColor(0xff5722).onClick(() => {// 暂停播放this.avPlayer.pause().then(() => {this.angleNum = 0;})})} else {// 播放Image($r('app.media.ic_play')).width(64).height(64).fillColor(0x00aaee).onClick(async () => {if (this.avPlayer && this.avPlayer.state === "paused") {this.avPlayer.play().then(() => {this.angleNum = 360;})} else {await this.initAVPlayer();}})}}.width('100%').justifyContent(FlexAlign.Center)
6.3 实现音频播放
6.3.1 初始化AVPlayer
// 播放音频AVPlayer实例private avPlayer: media.AVPlayer = undefined;// 初始化AVPlayerasync initAVPlayer() {// 创建AVPlayer实例对象this.avPlayer = await media.createAVPlayer();// 创建状态机变化回调函数this.setAVPlayerCallback();await this.loadingResourceFile();}
6.3.2 加载HAP包资源文件
// 加载HAP包资源文件loadingResourceFile = async () => {// 通过UIAbilityContext的resourceManager成员的getRawFd接口获取媒体资源播放地址let context = getContext(this) as common.UIAbilityContext;let fileDir = await context.resourceManager.getRawFd("audio.wav");// 为fdSrc赋值触发initialized状态机上报this.avPlayer.fdSrc = fileDir;}
6.3.3 注册AVPlayer回调函数
// 注册AVPlayer回调函数setAVPlayerCallback = () => {// 状态机变化回调函数// state:表示当前播放状态// reason:表示当前播放状态的切换原因this.avPlayer.on('stateChange', async (state, reason) => {this.state = this.avPlayer.state;switch (state) {case 'initialized':this.avPlayer.prepare().then(() => {// 音频播放准备完毕后,获取音频总时长this.duration = this.avPlayer.duration;})break;case 'prepared':// 开始播放this.avPlayer.play().then(() => {// 设置图标开始旋转this.angleNum = 360;})break;}})// 播放错误回调函数this.avPlayer.on('error', (err) => {console.error(`Error happened. Cause: ${JSON.stringify(err)}`);})// 监听资源播放当前时间回调函数this.avPlayer.on('timeUpdate', (time: number) => {if (this.avPlayer.state === 'completed') {this.currentProgress = 0;this.duration = 0;this.angleNum = 0;} else {this.currentProgress = time;}})}
07效果预览


相关文章:
【Purple Pi OH RK3566鸿蒙开发板】OpenHarmony音频播放应用,真实体验感爆棚!
本文转载于Purple Pi OH开发爱好者,作者ITMING 。 原文链接:https://bbs.elecfans.com/jishu_2376383_1_1.html 01注意事项 DevEco Studio 4.0 Beta2(Build Version: 4.0.0.400) OpenHarmony SDK API 9 创建工程类型选择Appli…...
Android rom开发:9.0系统上实现4G wifi 以太网共存
framework层修改网络优先级,4G > wifi > eth 修改patch如下: diff --git a/frameworks/base/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/frameworks/base/services/core/java/com/android/server/connectivit…...
高速自动驾驶HMI人机交互
概述 目的 本文档的目的是描述高速自动驾驶功能涉及的HMI显示需求技术规范和设计说明。 范围 术语及缩写 设计与实验标准 设计标准 设计标准-非法规类设计标准-法规类 HMI交互需求 CL4功能界面 HMI显示器[伊1] 中应包含CL4功能设置界面,提供给用户进行设置操作或显…...
【自然语言处理】关系抽取 —— SOLS 讲解
SOLS 论文信息 标题:Speaker-Oriented Latent Structures for Dialogue-Based Relation Extraction 作者:Guoshun Nan, Guoqing Luo, Sicong Leng, Yao Xiao, Wei Lu 发布时间与更新时间:2021.09.11 主题:自然语言处理、关系抽取、对话场景、跨语句、DialogRE、GCN arXiv:…...
周易算卦流程c++实现
代码 #include<iostream> using namespace std; #include<vector> #include<cstdlib> #include<ctime> #include<Windows.h>int huaYiXiangLiang(int all, int& left) {Sleep(3000);srand(time(0));left rand() % all 1;while (true) {if…...
软件架构设计(十三) 构件与中间件技术
中间件的定义 其实中间件是属于构件的一种。是一种独立的系统软件或服务程序,可以帮助分布式应用软件在不同技术之间共享资源。 我们把它定性为一类系统软件,比如我们常说的消息中间件,数据库中间件等等都是中间件的一种体现。一般情况都是给应用系统提供服务,而不是直接…...
PyTorch深度学习实战——基于ResNet模型实现猫狗分类
PyTorch深度学习实战——基于ResNet模型实现猫狗分类 0. 前言1. ResNet 架构2. 基于预训练 ResNet 模型实现猫狗分类相关链接 0. 前言 从 VGG11 到 VGG19,不同之处仅在于网络层数,一般来说,神经网络越深,它的准确率就越高。但并非…...
机器学习第六课--朴素贝叶斯
朴素贝叶斯广泛地应用在文本分类任务中,其中最为经典的场景为垃圾文本分类(如垃圾邮件分类:给定一个邮件,把它自动分类为垃圾或者正常邮件)。这个任务本身是属于文本分析任务,因为对应的数据均为文本类型,所以对于此类任务我们首先…...
基于Java+SpringBoot+Vue的图书借还小程序的设计与实现(亮点:多角色、点赞评论、借书还书、在线支付)
图书借还管理小程序 一、前言二、我的优势2.1 自己的网站2.2 自己的小程序(小蔡coding)2.3 有保障的售后2.4 福利 三、开发环境与技术3.1 MySQL数据库3.2 Vue前端技术3.3 Spring Boot框架3.4 微信小程序 四、功能设计4.1 主要功能描述 五、系统实现5.1 小…...
【校招VIP】前端计算机网络之UDP相关
考点介绍 UDP是一个简单的面向消息的传输层协议,尽管UDP提供标头和有效负载的完整性验证(通过校验和),但它不保证向上层协议提供消息传递,并且UDP层在发送后不会保留UDP 消息的状态。因此,UDP有时被称为不可…...
前缀和实例4(和可被k整除的子数组)
题目: 给定一个整数数组 nums 和一个整数 k ,返回其中元素之和可被 k 整除的(连续、非空) 子数组 的数目。 子数组 是数组的 连续 部分。 示例 1: 输入:nums [4,5,0,-2,-3,1], k 5 输出:7 …...
Android获取系统读取权限
第一步在Androidifest.xml文件中加上授权语句 <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE"/>并且在Application标签下添加 androi…...
输入学生成绩(最多不超过40),输入为负值时表示输入结束,统计成绩高于平均成绩的学生人数
#include<stdio.h> #define N 40 int scanfscore(int score[N]) {int i -1;do {i;printf("输入学生成绩:");scanf("%d", &score[i]);} while (score[i] > 0);return i; } int average(int score[N], int n) {int j 0;int k 0;double sum …...
【力扣周赛】第 363 场周赛(完全平方数和质因数分解)
文章目录 竞赛链接Q1:100031. 计算 K 置位下标对应元素的和竞赛时代码写法2——手写二进制中1的数量 Q2:100040. 让所有学生保持开心的分组方法数(排序后枚举分界)竞赛时代码 Q3:100033. 最大合金数(二分答…...
RocketMQ的介绍和环境搭建
一、介绍 我也不知道是啥,知道有什么用、怎么用就行了,说到mq(MessageQueue)就是消息队列,队列是先进先出的一种数据结构,但是RocketMQ不一定是这样,简单的理解一下,就是临时存储的…...
【web开发】7、Django(2)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、部门列表二、部门管理(增删改)三、用户管理过渡到modelform组件四、modelform实例:靓号操作五、自定义分页组件六、datepick…...
Prometheus+Grafana可视化监控【Nginx状态】
文章目录 一、安装Docker二、安装Nginx(Docker容器方式)三、安装Prometheus四、安装Grafana五、Pronetheus和Grafana相关联六、安装nginx_exporter七、Grafana添加Nginx监控模板 一、安装Docker 注意:我这里使用之前写好脚本进行安装Docker,如果已经有D…...
R 语言的安装教程
一、下载相关软件 1、R 下载 官网:R: The R Project for Statistical Computing 找到中国镜像,下载快 历史版本点击这里 2、Rtools 下载 进入镜像后,点击这里 然后选择与上面下载的R版本相对应的版本即可 3、Rstudio 下载 官网࿱…...
uniapp-提现功能(demo)
页面布局 提现页面 有一个输入框 一个提现按钮 一段提现全部的文字 首先用v-model 和data内的数据双向绑定 输入框逻辑分析 输入框的逻辑 为了符合日常输出 所以要对输入框加一些条件限制 因为是提现 所以对输入的字符做筛选,只允许出现小数点和数字 这里用正则实现的小数点…...
Spring 篇
1、什么是 Spring? Spring是一个轻量级的IOC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。常见的配置方式有三种:基于XML的配置、基于注解的配置…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
