鸿蒙音乐播放器基础实现
·
下面我们将通过一个简单的音乐播放器示例,展示鸿蒙音乐应用开发的基本流程。
项目结构
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"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical"
ohos:padding="32">
<Text
ohos: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"/>
<Text
ohos: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"/>
<Slider
ohos: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"/>
<Text
ohos: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"/>
<DirectionalLayout
ohos:height="match_content"
ohos:width="match_parent"
ohos:orientation="horizontal"
ohos:top_margin="40">
<Button
ohos: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"/>
<Button
ohos: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"/>
<Button
ohos: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>
<ListContainer
ohos: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() {
@Override
public void onPrepared() {
// 准备完成
if (progressSlider != null) {
progressSlider.setMaxValue(mediaPlayer.getDuration());
}
updateTimeDisplay();
}
@Override
public void onMessage(int i, int i1) {
// 处理消息
}
@Override
public void onError(int i, int i1) {
// 错误处理
HiLog.error(LABEL, "播放器错误: %{public}d", i1);
}
@Override
public void onResolutionChanged(int i, int i1) {
// 分辨率改变
}
@Override
public void onPlayBackComplete() {
// 播放完成
playNext();
}
@Override
public void onRewindToComplete() {
// 重定向完成
}
@Override
public void onBufferingChange(int i) {
// 缓冲进度改变
}
@Override
public void onNewTimedMetaData(Player.MediaTimedMetaData mediaTimedMetaData) {
// 新的定时元数据
}
@Override
public 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() {
@Override
public void onProgressUpdated(Slider slider, int progress, boolean fromUser) {
if (fromUser && mediaPlayer != null && mediaPlayer.isNowPlaying()) {
mediaPlayer.rewindTo(progress);
}
}
@Override
public void onTouchStart(Slider slider) {
// 触摸开始
}
@Override
public 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() {
@Override
public 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;
@Override
public 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) {
@Override
public 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);
}
@Override
protected void onBackground() {
super.onBackground();
// 应用进入后台时,可以继续播放音乐
}
@Override
protected void onStop() {
super.onStop();
// 释放资源
if (musicPlayer != null) {
musicPlayer.release();
}
}
}
歌曲列表项布局 (song_list_item.xml)
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns: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">
<Text
ohos:id="$+id:song_title"
ohos:height="match_content"
ohos:width="match_parent"
ohos:text_size="20fp"
ohos:text_color="#000000"
ohos:text_alignment="center"/>
<Text
ohos: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,实现在线播放和下载
语音控制:结合鸿蒙的语音助手,实现语音控制播放
总结
本文介绍了如何在鸿蒙系统上开发音乐播放器应用,涵盖了基本的播放控制、进度显示、歌曲列表等功能。鸿蒙系统的分布式特性为音乐应用开发带来了新的可能性,开发者可以在此基础上进一步探索更复杂的功能,打造更加出色的音乐体验。
通过这个示例,我们可以看到鸿蒙系统在多媒体应用开发方面的强大能力,以及其简洁高效的开发模式。随着鸿蒙生态的不断完善,音乐类应用将有更多创新空间和发展机遇。
更多推荐


所有评论(0)