鸿蒙HarmonyOS入门-音乐app开发
本文介绍了基于HarmonyOS Next开发的音乐播放器项目MyAppmusic的技术实现。项目采用三层架构设计,包含应用入口管理(EntryAbility)、核心播放器(AVPlayerManager)、数据模型和页面组件等模块。重点讲解了播放器生命周期管理、事件驱动机制、状态同步(通过EventEmitter)和数据持久化(Preferences API)等关键技术实现。项目展示了主页面、播
目录
引言
随着HarmonyOS Next的正式发布,越来越多的开发者开始关注鸿蒙。作为开发者,如何快速上手HarmonyOS Next并构建一个功能完整的应用?音乐播放器是一个非常好的切入点,它涵盖了音频播放、UI交互、状态管理等多个核心技术点。
今天,我将基于我的实际项目经验,分享如何在HarmonyOS Next平台上构建一个功能完整的音乐播放应用,让你少走弯路,快速掌握HarmonyOS Next开发精髓。
本项目为学习项目,学习B站某马教程后进行修改,本项目为入门练习,没有后端接口(省流),项目中的的数据均为静态测试数据,仅供学习参考。
本项目源码链接:https://github.com/silver-kite-wu/HarmonyOS-MyAppmusic.git
一、项目目录

MyAppmusic采用了经典的三层架构,表现层,业务逻辑层,数据层。
二、项目展示




三、核心能力:应用的入口
1.EntryAbility:应用的生命周期管理
EntryAbility.ets 是应用的主入口,负责管理应用的生命周期:
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
// 传递上下文并初始化播放器
const rm = this.context.resourceManager;
avplayerClass.setContext(this.context.cacheDir,
this.context.filesDir,
(path: string) => rm.getRawFileDescriptor(path));
// 异步初始化播放器
avplayerClass.init().then(async ()=>{
console.log('播放器初始化成功');
})
// 加载页面
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content.');
return;
}
});
}
onNewWant(want: Want): void {
// 点击通知后进入播放页
router.pushUrl({ url: 'pages/Playnow' })
}
}
关键实现点 :
1. 上下文传递 :将应用的上下文传递给播放器管理类
2. 异步初始化 :播放器初始化不阻塞页面加载
3. 通知处理 : onNewWant 方法处理通知点击事件
2.EntryBackupAbility:数据备份能力
EntryBackupAbility.ets 提供了应用数据备份功能,这是HarmonyOS的一个重要特性。通过备份能力,用户可以在更换设备或重装应用时恢复数据。
四、播放器核心:音乐的心脏
1.AVPlayerManager:播放器的灵魂
avplayermanager.ets 是整个应用的核心,管理着音频播放的全生命周期:
export default class avplayerClass {
static player: media.AVPlayer | null = null;
static isplay: boolean = false;
static playmodel: 'auto' | 'repeat' | 'random' = 'auto';
static playlist: songtype[] = songlist;
static playindex: number = -1;
static async init(): Promise<void> {
if (avplayerClass.isInitialized && avplayerClass.player) {
return;
}
try {
avplayerClass.player = await media.createAVPlayer();
avplayerClass.isInitialized = true;
// 监听播放器状态变化
avplayerClass.player.on('stateChange', (state: string) => {
switch (state) {
case 'playing':
avplayerClass.isplay = true;
break;
case 'paused':
avplayerClass.isplay = false;
break;
case 'completed':
avplayerClass.next();
break;
}
avplayerClass.updatestate();
});
// 监听播放进度更新
avplayerClass.player.on('timeUpdate', (time: number) => {
avplayerClass.time = Math.max(0, Number(time) || 0);
avplayerClass.updatestate();
});
} catch (error) {
console.error('初始化播放器失败:', error);
}
}
}
技术亮点 :
1. 单例模式 :确保全局只有一个播放器实例
2. 事件驱动 :通过监听播放器事件来更新状态
3. 状态同步 :使用事件总线广播播放状态
2.播放模式切换
static async next(): Promise<void> {
switch (avplayerClass.playmodel) {
case 'repeat':
// 单曲循环
await avplayerClass.playSongByIndex(avplayerClass.playindex);
break;
case 'random':
// 随机播放
const randomIndex = Math.floor(Math.random() * avplayerClass.playlist.length);
avplayerClass.playindex = randomIndex;
await avplayerClass.playSongByIndex(randomIndex);
break;
case 'auto':
default:
// 自动播放
avplayerClass.playindex++;
if (avplayerClass.playindex >= avplayerClass.playlist.length) {
avplayerClass.playindex = 0;
}
await avplayerClass.playSongByIndex(avplayerClass.playindex);
}
}
这部分没有按钮进行实现,感兴趣的可以自行修改,进行实现。
五、数据模型:信息的载体
1.音乐数据模型
music.ets 定义了音乐的数据结构:
export interface songtype {
img: string; // 封面图片URL
name: string; // 歌曲名称
author: string; // 歌手名称
url: string; // 音乐URL
id: number; // 唯一标识
}
export const songlist: songtype[] = [
{
img: "https://y.qq.com/music/photo_new/...",
name: "起风了",
author: "买辣椒也用券",
url: "rawfile:1.mp3",
id: 0
},
// 更多歌曲...
];
本来原先URL是http链接,测试的时候一会能播放一会播放不了,可能是音乐源服务器有防外联的机制,不允许同一IP高频访问,也有可能是其他问题,可以在评论区说说其他可能。现在使用的是本地文件来播放。
2.其他数据模型
项目还包含其他数据模型:
- maintabdata.ets :标签栏数据
- swiperdata.ets :轮播图数据
- maindailytype.ets :每日推荐数据
- recommenddata.ets :推荐歌单数据
- pinglundata.ets :评论数据
数据组织原则 :
- 每个数据模型文件负责一类数据
- 使用接口定义数据结构
- 导出默认数据数组
本项目没有后端接口,数据均为静态测试数据,感兴趣的可以自行优化
六、页面组件:用户的面孔
1.主页面组件
mainpage.ets 是应用的主页面,使用Tabs组件实现标签切换:
@Entry
@Component
struct main {
@State curr_index: number = 0
tabdata: Tabclass[] = [
{txt:'主页', image:$r('app.media.recommend')},
{txt:'发现', image:$r('app.media.find')},
{txt:'评论', image:$r('app.media.pinglu')},
{txt:'我的', image:$r('app.media.my')}
]
build() {
NavDestination() {
Tabs({barPosition:BarPosition.End}){
ForEach(this.tabdata,(itme:Tabclass,index:number)=>{
TabContent(){
if (index===0) {
main_page()
} else if (index===1) {
find_page()
} else if(index===2) {
pinglun_page()
} else {
my_page()
}
}
.tabBar(this.tabbuilder(itme,index))
})
}
}
}
}
这里可以进一步优化,不用官方的Tabs,改成自定义组件,原生的不知道为什么,它在左右滑动的时候有延迟,不如自定义组件,在开发者社区,Tabs效果也都是用的自定义组件来实现,或者禁止左右滑动。
2.播放页面
Playnow.ets 是音乐播放的详细页面,包含丰富的交互功能:
@Entry
@Component
export struct Playnow {
@State playstate: playstate = {
duration: 0,
time: 0,
isplay: false,
playmodel: 'auto',
playindex: this.playindex,
img: songlist[this.playindex].img,
name: songlist[this.playindex].name,
author: songlist[this.playindex].author
}
build() {
Column() {
// 顶部标题栏
Row() {
Image($r('app.media.back'))
.onClick(() => router.back())
Text('正在播放')
.fontSize(22)
.fontColor('#fff')
}
// 专辑封面(带旋转动画)
Stack() {
Image(this.playstate.img)
.width(300)
.height(300)
.borderRadius(150)
.rotate({
x: 0, y: 0, z: 1,
angle: this.start
})
}
// 播放控制
Row() {
Image($r('app.media.previous'))
.onClick(() => avplayerClass.previous())
Image(this.playstate.isplay ? $r('app.media.pause') : $r('app.media.play'))
.onClick(async () => {
if (this.playstate.isplay) {
await avplayerClass.pause();
} else {
await avplayerClass.play();
}
})
Image($r('app.media.next'))
.onClick(() => avplayerClass.next())
}
}
}
}

此处可以添加新的组件,实现之前说的三种播放状态,随机,自动,单曲。
交互:
1. 专辑封面旋转 :播放时封面旋转,暂停时停止
2. 进度条拖拽 :用户可以拖动进度条调整播放进度
3. 播放控制 :完整的播放、暂停、上一首、下一首功能
3.迷你播放器
zhu_page.ets 中的迷你播放器是应用的一大特色:

Row() {
// 封面
Image(this.miniImg)
.width(40)
.height(40)
.borderRadius(6)
// 歌曲信息
Column({ space: 4 }) {
Text(this.miniName || '未播放')
.fontSize(14)
.fontWeight(600)
Text(this.miniAuthor || '')
.fontSize(12)
.fontColor('#666')
Progress({value:this.val,total:this.total,type:ProgressType.Linear})
}
// 播放/暂停
Image(this.miniIsPlay ? $r('app.media.play') : $r('app.media.pause'))
.onClick(() => this.togglePlay())
}
设计理念 :
- 始终可见:悬浮在页面底部,不随页面滚动
- 状态同步:实时显示播放状态和进度
- 快速跳转:点击可进入完整播放页面
七、状态管理:数据的流动
1.事件总线的应用
使用HarmonyOS的EventEmitter实现跨页面状态同步:
static updatestate(): void {
const stateData: PlayStateData = {
duration: avplayerClass.duration,
time: avplayerClass.time,
isplay: avplayerClass.isplay,
playmodel: avplayerClass.playmodel,
playlist: avplayerClass.playlist,
playindex: avplayerClass.playindex,
img: currentSong.img || '',
name: currentSong.name || '',
author: currentSong.author || ''
};
// 发送状态更新事件
emitter.emit('play_state_update', {
data: {
img: stateData.img,
name: stateData.name,
author: stateData.author,
isplay: stateData.isplay,
playindex: stateData.playindex,
time: stateData.time,
duration: stateData.duration
}
});
}
订阅事件 :
emitter.on('play_state_update', (eventData) => {
const d = eventData.data;
if (!d) return;
this.miniImg = d.img || this.miniImg;
this.miniName = d.name || this.miniName;
this.miniAuthor = d.author || this.miniAuthor;
this.miniIsPlay = d.isplay !== undefined ? !!d.isplay : this.miniIsPlay;
});
2.数据持久化
使用Preferences API实现数据持久化(用户首选项):
export async function saveLastMini(context: Context, state: MiniPlayState): Promise<void> {
try {
const dataPreferences = await preferences.getPreferences(context, 'music_prefs');
await dataPreferences.put('lastMini', JSON.stringify(state));
await dataPreferences.flush();
} catch (err) {
console.error('保存播放状态失败:', err);
}
}
export async function loadLastMini(context: Context): Promise<MiniPlayState | null> {
try {
const dataPreferences = await preferences.getPreferences(context, 'music_prefs');
const value = await dataPreferences.get('lastMini', '');
return value ? JSON.parse(value as string) : null;
} catch (err) {
console.error('加载播放状态失败:', err);
return null;
}
}
八、其他页面展示
1.首页搜索功能


2.其他应用(跳转web网页)

这是内嵌的Web页面,点击右上角可以跳转到浏览器查看。
3.每日推荐和推荐歌单
其可以跳转到对应的歌单

4.登录页

蓝色协议点击可以弹出协议内容。
5.设置个人位置

其他的功能还有外联转置,头像更换,通知栏等等。。。
开发心得
1. 架构设计的重要性 :好的架构能让开发事半功倍
2. 代码规范的价值 :统一的规范能提高团队协作效率
3. 性能优化的必要性 :优化能显著提升用户体验
4. 持续学习的态度 :HarmonyOS生态在快速发展,需要不断学习
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、分享给更多的开发者!
让我们一起,在HarmonyOS的世界里,创造更多精彩的应用! 🎵🚀
更多推荐



所有评论(0)