当前位置: 首页 > news >正文

鸿蒙音乐播放器基础实现

下面我们将通过一个简单的音乐播放器示例,展示鸿蒙音乐应用开发的基本流程。

项目结构

MusicPlayer/
├── entry/
│   └── src/
│       ├── main/
│       │   ├── java/com/example/musicplayer/
│       │   │   ├── MainAbility.java
│       │   │   ├── MusicService.java
│       │   │   └── MusicPlayer.java
│       │   └── resources/
│       │       ├── base/layout/ability_main.xml
│       │       └── base/media/ (存放音乐文件)

布局文件 (ability_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="match_parent"ohos:width="match_parent"ohos:orientation="vertical"ohos:padding="32"><Textohos:id="$+id:music_title"ohos:height="match_content"ohos:width="match_parent"ohos:text="鸿蒙音乐播放器"ohos:text_size="32fp"ohos:text_alignment="center"ohos:margin="0 0 0 20"/><Textohos:id="$+id:current_song"ohos:height="match_content"ohos:width="match_parent"ohos:text="未选择歌曲"ohos:text_size="24fp"ohos:text_alignment="center"ohos:margin="0 0 0 10"/><Sliderohos:id="$+id:progress_slider"ohos:height="match_content"ohos:width="match_parent"ohos:max_value="100"ohos:min_value="0"ohos:margin="0 0 0 20"/><Textohos:id="$+id:time_display"ohos:height="match_content"ohos:width="match_parent"ohos:text="00:00 / 00:00"ohos:text_size="18fp"ohos:text_alignment="center"/><DirectionalLayoutohos:height="match_content"ohos:width="match_parent"ohos:orientation="horizontal"ohos:top_margin="40"><Buttonohos:id="$+id:prev_btn"ohos:height="match_content"ohos:width="120"ohos:text="上一首"ohos:background_element="$graphic:button_element"ohos:layout_alignment="center"ohos:margin="0 10 0 0"/><Buttonohos:id="$+id:play_btn"ohos:height="match_content"ohos:width="120"ohos:text="播放"ohos:background_element="$graphic:button_element"ohos:layout_alignment="center"ohos:margin="0 10 0 10"/><Buttonohos:id="$+id:next_btn"ohos:height="match_content"ohos:width="120"ohos:text="下一首"ohos:background_element="$graphic:button_element"ohos:layout_alignment="center"ohos:margin="0 0 0 10"/></DirectionalLayout><ListContainerohos:id="$+id:song_list"ohos:height="300"ohos:width="match_parent"ohos:top_margin="40"ohos:bottom_margin="40"/></DirectionalLayout>

音乐播放器核心类 (MusicPlayer.java)

package com.example.musicplayer;import ohos.media.player.Player;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.*;
import ohos.media.common.Source;
import ohos.app.Context;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;public class MusicPlayer {private Player mediaPlayer;private List<Song> songList;private int currentSongIndex = 0;private boolean isPlaying = false;private Timer progressTimer;private Slider progressSlider;private Text timeDisplay;private Text currentSongText;private Button playButton;public MusicPlayer(Context context) {mediaPlayer = new Player(context);initializeSongList();setupMediaPlayerListeners();}private void initializeSongList() {songList = new ArrayList<>();// 添加示例歌曲songList.add(new Song("鸿蒙之歌", "artist1", "resource://rawfile/song1.mp3"));songList.add(new Song("分布式交响曲", "artist2", "resource://rawfile/song2.mp3"));songList.add(new Song("万物互联旋律", "artist3", "resource://rawfile/song3.mp3"));}private void setupMediaPlayerListeners() {mediaPlayer.setPlayerCallback(new Player.IPlayerCallback() {@Overridepublic void onPrepared() {// 准备完成if (progressSlider != null) {progressSlider.setMaxValue(mediaPlayer.getDuration());}updateTimeDisplay();}@Overridepublic void onMessage(int i, int i1) {// 处理消息}@Overridepublic void onError(int i, int i1) {// 错误处理HiLog.error(LABEL, "播放器错误: %{public}d", i1);}@Overridepublic void onResolutionChanged(int i, int i1) {// 分辨率改变}@Overridepublic void onPlayBackComplete() {// 播放完成playNext();}@Overridepublic void onRewindToComplete() {// 重定向完成}@Overridepublic void onBufferingChange(int i) {// 缓冲进度改变}@Overridepublic void onNewTimedMetaData(Player.MediaTimedMetaData mediaTimedMetaData) {// 新的定时元数据}@Overridepublic void onMediaTimeIncontinuity(Player.MediaTimeInfo mediaTimeInfo) {// 媒体时间不连续}});}public void setUIComponents(Slider slider, Text timeText, Text songText, Button playBtn) {this.progressSlider = slider;this.timeDisplay = timeText;this.currentSongText = songText;this.playButton = playButton;// 设置进度条监听progressSlider.setValueChangedListener(new Slider.ValueChangedListener() {@Overridepublic void onProgressUpdated(Slider slider, int progress, boolean fromUser) {if (fromUser && mediaPlayer != null && mediaPlayer.isNowPlaying()) {mediaPlayer.rewindTo(progress);}}@Overridepublic void onTouchStart(Slider slider) {// 触摸开始}@Overridepublic void onTouchEnd(Slider slider) {// 触摸结束}});}public void playSong(int index) {if (index < 0 || index >= songList.size()) {return;}try {if (mediaPlayer.isNowPlaying()) {mediaPlayer.stop();}mediaPlayer.reset();Song song = songList.get(index);Source source = new Source(song.getPath());mediaPlayer.setSource(source);mediaPlayer.prepare();mediaPlayer.play();currentSongIndex = index;isPlaying = true;if (currentSongText != null) {currentSongText.setText(song.getTitle() + " - " + song.getArtist());}if (playButton != null) {playButton.setText("暂停");}startProgressTimer();} catch (IOException e) {HiLog.error(LABEL, "播放歌曲失败: %{public}s", e.getMessage());}}public void play() {if (mediaPlayer != null && !mediaPlayer.isNowPlaying()) {mediaPlayer.play();isPlaying = true;if (playButton != null) {playButton.setText("暂停");}startProgressTimer();}}public void pause() {if (mediaPlayer != null && mediaPlayer.isNowPlaying()) {mediaPlayer.pause();isPlaying = false;if (playButton != null) {playButton.setText("播放");}stopProgressTimer();}}public void playNext() {int nextIndex = (currentSongIndex + 1) % songList.size();playSong(nextIndex);}public void playPrevious() {int prevIndex = (currentSongIndex - 1 + songList.size()) % songList.size();playSong(prevIndex);}private void startProgressTimer() {stopProgressTimer();progressTimer = new Timer();progressTimer.scheduleAtFixedRate(new TimerTask() {@Overridepublic void run() {updateProgress();}}, 0, 1000);}private void stopProgressTimer() {if (progressTimer != null) {progressTimer.cancel();progressTimer = null;}}private void updateProgress() {if (mediaPlayer != null && mediaPlayer.isNowPlaying()) {int currentPosition = mediaPlayer.getCurrentTime();int duration = mediaPlayer.getDuration();if (progressSlider != null) {progressSlider.setProgressValue(currentPosition);}updateTimeDisplay();}}private void updateTimeDisplay() {if (timeDisplay != null && mediaPlayer != null) {int current = mediaPlayer.getCurrentTime();int total = mediaPlayer.getDuration();String currentTime = formatTime(current);String totalTime = formatTime(total);timeDisplay.setText(currentTime + " / " + totalTime);}}private String formatTime(int milliseconds) {int seconds = milliseconds / 1000;int minutes = seconds / 60;seconds = seconds % 60;return String.format("%02d:%02d", minutes, seconds);}public void release() {stopProgressTimer();if (mediaPlayer != null) {mediaPlayer.release();mediaPlayer = null;}}public List<Song> getSongList() {return songList;}public boolean isPlaying() {return isPlaying;}// 歌曲数据模型public static class Song {private String title;private String artist;private String path;public Song(String title, String artist, String path) {this.title = title;this.artist = artist;this.path = path;}public String getTitle() { return title; }public String getArtist() { return artist; }public String getPath() { return path; }}
}

主Ability实现 (MainAbility.java)

package com.example.musicplayer;import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.*;
import ohos.agp.window.service.WindowManager;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import java.util.ArrayList;
import java.util.List;public class MainAbility extends Ability {private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MainAbility");private MusicPlayer musicPlayer;private ListContainer songListContainer;private ArrayAdapter<MusicPlayer.Song> songAdapter;@Overridepublic void onStart(Intent intent) {super.onStart(intent);// 保持屏幕常亮getWindow().addFlags(WindowManager.LayoutConfig.MARK_KEEP_SCREEN_ON);super.setUIContent(ResourceTable.Layout_ability_main);initializeMusicPlayer();setupUIComponents();setupSongList();}private void initializeMusicPlayer() {musicPlayer = new MusicPlayer(this);}private void setupUIComponents() {// 获取UI组件Slider progressSlider = (Slider) findComponentById(ResourceTable.Id_progress_slider);Text timeDisplay = (Text) findComponentById(ResourceTable.Id_time_display);Text currentSongText = (Text) findComponentById(ResourceTable.Id_current_song);Button playButton = (Button) findComponentById(ResourceTable.Id_play_btn);Button prevButton = (Button) findComponentById(ResourceTable.Id_prev_btn);Button nextButton = (Button) findComponentById(ResourceTable.Id_next_btn);songListContainer = (ListContainer) findComponentById(ResourceTable.Id_song_list);// 设置音乐播放器UI组件musicPlayer.setUIComponents(progressSlider, timeDisplay, currentSongText, playButton);// 设置按钮点击事件playButton.setClickedListener(component -> togglePlayPause());prevButton.setClickedListener(component -> musicPlayer.playPrevious());nextButton.setClickedListener(component -> musicPlayer.playNext());}private void togglePlayPause() {if (musicPlayer.isPlaying()) {musicPlayer.pause();} else {if (musicPlayer.getSongList().isEmpty()) {// 如果没有歌曲在播放,播放第一首musicPlayer.playSong(0);} else {musicPlayer.play();}}}private void setupSongList() {List<MusicPlayer.Song> songs = musicPlayer.getSongList();songAdapter = new ArrayAdapter<MusicPlayer.Song>(this, ResourceTable.Layout_song_list_item, songs) {@Overridepublic void onItemChanged(Component component, MusicPlayer.Song song, int position) {Text songTitle = (Text) component.findComponentById(ResourceTable.Id_song_title);Text songArtist = (Text) component.findComponentById(ResourceTable.Id_song_artist);if (songTitle != null) {songTitle.setText(song.getTitle());}if (songArtist != null) {songArtist.setText(song.getArtist());}// 设置列表项点击事件component.setClickedListener(comp -> {musicPlayer.playSong(position);});}};songListContainer.setItemProvider(songAdapter);}@Overrideprotected void onBackground() {super.onBackground();// 应用进入后台时,可以继续播放音乐}@Overrideprotected void onStop() {super.onStop();// 释放资源if (musicPlayer != null) {musicPlayer.release();}}
}

歌曲列表项布局 (song_list_item.xml)

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="60vp"ohos:width="match_parent"ohos:orientation="vertical"ohos:padding="16"ohos:background_element="$graphic:background_list_item"><Textohos:id="$+id:song_title"ohos:height="match_content"ohos:width="match_parent"ohos:text_size="20fp"ohos:text_color="#000000"ohos:text_alignment="center"/><Textohos:id="$+id:song_artist"ohos:height="match_content"ohos:width="match_parent"ohos:text_size="16fp"ohos:text_color="#666666"ohos:text_alignment="center"ohos:top_margin="5"/></DirectionalLayout>
功能扩展建议
分布式播放:利用鸿蒙的分布式能力,实现多设备协同播放歌词显示:解析LRC文件并实现实时歌词显示音效处理:添加均衡器、音效设置等功能在线音乐:集成音乐API,实现在线播放和下载语音控制:结合鸿蒙的语音助手,实现语音控制播放

总结

本文介绍了如何在鸿蒙系统上开发音乐播放器应用,涵盖了基本的播放控制、进度显示、歌曲列表等功能。鸿蒙系统的分布式特性为音乐应用开发带来了新的可能性,开发者可以在此基础上进一步探索更复杂的功能,打造更加出色的音乐体验。

通过这个示例,我们可以看到鸿蒙系统在多媒体应用开发方面的强大能力,以及其简洁高效的开发模式。随着鸿蒙生态的不断完善,音乐类应用将有更多创新空间和发展机遇。

http://www.dtcms.com/a/395022.html

相关文章:

  • Vue3》》Vite》》文件路由 vite-plugin-pages、布局系统 vite-plugin-vue-layouts
  • 深入解析 MySQL MVCC:高并发背后的数据时光机
  • 汽车冷却系统的冷却水管介绍
  • 基础架构设计
  • 从分散到统一:基于Vue3的地图模块重构之路
  • JVM实际内存占用
  • Spark SQL 桶抽样(Bucket Sampling)
  • 常见的【垃圾收集算法】
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘django’ 问题
  • jvm之【垃圾回收器】
  • Tomcat基础知识
  • Will、NGC游戏模拟器 Dolphin海豚模拟器2509最新版 电脑+安卓版 附游戏
  • ELK企业级日志分析系统详解:从入门到部署实践
  • 2025年Spring Security OAuth2实现github授权码模式登录
  • Kafka面试精讲 Day 22:Kafka Streams流处理
  • ELK大总结20250922
  • 基于Hadoop生态的汽车全生命周期数据分析与可视化平台-基于Python+Vue的二手车智能估价与市场分析系统
  • 基于TV模型利用Bregman分裂算法迭代对图像进行滤波和复原处理
  • 利用 Perfmon.exe 与 UMDH 组合分析 Windows 程序内存消耗
  • hello算法笔记 02
  • 二级域名解析与配置
  • 如何学习国库会计知识
  • 【读论文】压缩双梳光谱技术
  • Spark Structured Streaming端到端延迟优化实践指南
  • 【.NET实现输入法切换的多种方法解析】,第566篇
  • 性能测试-jmeter13-性能资源指标监控
  • 基于华为openEuler系统安装PDF查看器PdfDing
  • PyTorch 神经网络工具箱核心知识梳理
  • 【LangChain指南】Agents
  • Linux 的进程信号与中断的关系