我是靠谱客的博主 尊敬钻石,最近开发中收集的这篇文章主要介绍HarmongOS音乐播放器开发示例教程前言1. 所需知识和最终效果2. 资源获取3. UI布局4. 播放逻辑,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

HarmongOS音乐播放器开发示例教程

  • 前言
    • 完整项目代码链接[GMusic-HarmongOS-Samples](https://github.com/SakurajimaMaii/GMusic-HarmongOS-Samples)欢迎⭐和fork
    • 对应BiliBili视频[鸿蒙开发教程之音乐软件](https://www.bilibili.com/video/BV1z5411M7WU)
  • 1. 所需知识和最终效果
  • 2. 资源获取
    • 2.1 权限申请
      • 2.1.1 在config.json文件中的“reqPermissions”字段中声明所需要的权限。
      • 2.1.2 在Ability中动态申请
    • 2.2 数据模型
    • 2.3 数据读取
      • 2.3.1 通过外部存储的Uri来获取对应的ResultSet
      • 2.3.2 通过ResultSet获取对应的音频对象
  • 3. UI布局
    • 3.1 主页面布局
    • 3.2 音乐布局
  • 4. 播放逻辑
    • 4.1 列表点击事件的设置
    • 4.2 底部播放控件的设置
      • 4.2.1 playMusic()函数
      • 4.2.2 lastMusic()函数
      • 4.2.3 nextMusic()函数
      • 4.2.4 play()函数

前言

完整项目代码链接GMusic-HarmongOS-Samples欢迎⭐和fork

对应BiliBili视频鸿蒙开发教程之音乐软件

1. 所需知识和最终效果

屏幕截图

Music Hap
资源获取
权限申请
数据模型
数据读取
UI界面
布局
控件
DirectionalLayout
Text
Button
ListContainer
播放逻辑
List Item点击事件
底部控制栏

2. 资源获取

2.1 权限申请

2.1.1 在config.json文件中的“reqPermissions”字段中声明所需要的权限。

config.json配置

2.1.2 在Ability中动态申请

  1. 申请对应权限
@Override
public void onStart(Intent intent) {
    super.onStart(intent);
    super.setMainRoute(MainAbilitySlice.class.getName());

    if (verifySelfPermission("ohos.permission.READ_MEDIA") != IBundleManager.PERMISSION_GRANTED) {
        if (canRequestPermission("ohos.permission.READ_MEDIA")) {
            // 是否可以申请弹框授权(首次申请或者用户未选择禁止且不再提示)
            requestPermissionsFromUser(
                    new String[] { "ohos.permission.READ_MEDIA" } , MY_PERMISSIONS_REQUEST_RW);
        } else {
            new ToastDialog(this).setText("需要授予应用读取存储权限").setAlignment(LayoutAlignment.CENTER).show();
        }
    }
}
  1. 检测申请结果
@Override
public void onRequestPermissionsFromUserResult (int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == MY_PERMISSIONS_REQUEST_RW) {// 匹配requestPermissions的requestCode
        if (grantResults.length > 0
                && grantResults[0] == IBundleManager.PERMISSION_GRANTED) {
            new ToastDialog(this).setText("所有权限已经被授予").setAlignment(LayoutAlignment.CENTER).show();
        } else {
            new ToastDialog(this).setText("所有权限已经被拒绝").setAlignment(LayoutAlignment.CENTER).show();
        }
    }
}

2.2 数据模型

声明对应的音乐对象

public class MusicBean {
    private int id;
    private String title;
    private String song;
    private String data;
    private String duration;
    private String artist;
    private String album;

    public MusicBean() {
    }

    /**
     * @param id       music_id
     * @param title    music_name
     * @param song
     * @param data     music_path
     * @param duration music_duration
     * @param artist music_artist
     */
    public MusicBean(int id, String title, String song, String data, String duration,String artist,String album) {
        this.id = id;
        this.title = title;
        this.song = song;
        this.data = data;
        this.duration = duration;
        this.artist = artist;
        this.album = album;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getSong() {
        return song;
    }

    public void setSong(String song) {
        this.song = song;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public String getDuration() {
        return duration;
    }

    public void setDuration(String duration) {
        this.duration = duration;
    }

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public String getAlbum() {
        return album;
    }

    public void setAlbum(String album) {
        this.album = album;
    }
}

2.3 数据读取

2.3.1 通过外部存储的Uri来获取对应的ResultSet

/**
* @param context Context
* @return
* If you want to get information about AVStorage.Audio.Media, please refer to:
* https://developer.harmonyos.com/cn/docs/documentation/doc-references/avstorage_audio_media-0000001054678942
* If you want to get information about this function, please refer to:
* https://developer.harmonyos.com/cn/docs/documentation/doc-guides/tv-media-playback-0000001050714866
*/
private ResultSet queryAvStore(Context context) {
    ResultSet resultSet = null;
    DataAbilityHelper helper = DataAbilityHelper.creator(context);
    try {
        resultSet = helper.query(AVStorage.Audio.Media.EXTERNAL_DATA_ABILITY_URI, null, null);
    } catch (DataAbilityRemoteException e) {
        e.printStackTrace();
    }
    return resultSet;
}

2.3.2 通过ResultSet获取对应的音频对象

关于 artistalbum 字段的获取可以参考文章HarmongOS音频开发之音频信息获取(以获取艺术家为例)

/**
* @param context Context
* @return
* get playlist
* If you want to get information about AVStorage.AVBaseColumns.ID or others, please refer to:
* https://developer.harmonyos.com/cn/docs/documentation/doc-references/avstorage_avbasecolumns-0000001054358919#ZH-CN_TOPIC_0000001054358919__DATA
*/
private List<MusicBean> getMusicBeanList(Context context) {
    ResultSet resultSet = queryAvStore(context);
    List<MusicBean> musicBeans = new ArrayList<>();
    while (resultSet.goToNextRow()) {
        MusicBean musicBean = new MusicBean();
        musicBean.setId(resultSet.getInt(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.ID)));
        musicBean.setData(resultSet.getString(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.DATA)));
        musicBean.setTitle(resultSet.getString(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.TITLE)));
        musicBean.setDuration(new SimpleDateFormat("mm:ss").format(new Date(resultSet.getLong(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.DURATION)))));
        musicBean.setSong(resultSet.getString(resultSet.getColumnIndexForName(AVStorage.AVBaseColumns.DISPLAY_NAME)));
        musicBean.setArtist(resultSet.getString(resultSet.getColumnIndexForName("artist")));
        musicBean.setAlbum(resultSet.getString(resultSet.getColumnIndexForName("album")));
        musicBeans.add(musicBean);
    }
    return musicBeans;
}

3. UI布局

3.1 主页面布局

主页面布局主要采用了DirectionalLayout布局,如果你想获取对应的布局信息,可以参考链接DirectionalLayout布局,以下是ability_main.xml布局

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:width="match_parent"
    ohos:height="match_parent"
    ohos:orientation="vertical">
    <ListContainer
        ohos:id="$+id:music_bean_lc"
        ohos:height="0vp"
        ohos:width="match_parent"
        ohos:orientation="vertical"
        ohos:weight="1"
        ohos:background_element="$media:background"/>
    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:background_element="#E6000000"
        ohos:orientation="horizontal"
        ohos:padding="5vp">
        <DirectionalLayout
            ohos:height="match_content"
            ohos:width="0vp"
            ohos:weight="1"
            ohos:orientation="vertical"
            ohos:layout_alignment="vertical_center">
            <Text
                ohos:id="$+id:bottom_music_name_tv"
                ohos:height="match_content"
                ohos:width="match_content"
                ohos:text="$string:music_name"
                ohos:text_size="20fp"
                ohos:text_color="$color:color_white"/>
            <Text
                ohos:id="$+id:bottom_music_artists_tv"
                ohos:height="match_content"
                ohos:width="match_content"
                ohos:text="$string:music_artist"
                ohos:text_size="10fp"
                ohos:text_color="$color:color_white"/>
        </DirectionalLayout>
        <Button
            ohos:id="$+id:bottom_last_btn"
            ohos:height="50vp"
            ohos:width="50vp"
            ohos:margin="10vp"
            ohos:background_element="$graphic:ic_last"/>
        <Button
            ohos:id="$+id:bottom_play_btn"
            ohos:height="50vp"
            ohos:width="50vp"
            ohos:margin="10vp"
            ohos:background_element="$graphic:ic_play"/>
        <Button
            ohos:id="$+id:bottom_next_btn"
            ohos:height="50vp"
            ohos:width="50vp"
            ohos:margin="10vp"
            ohos:background_element="$graphic:ic_next"/>
    </DirectionalLayout>
</DirectionalLayout>

3.2 音乐布局

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_content"
    ohos:width="match_parent"
    ohos:padding="10vp"
    ohos:orientation="horizontal">
    <DirectionalLayout
        ohos:height="match_content"
        ohos:width="0vp"
        ohos:weight="3"
        ohos:orientation="vertical">
        <Text
            ohos:id="$+id:music_name_tv"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:text="$string:music_name"
            ohos:text_size="20fp"
            ohos:text_color="$color:color_white"/>
        <Text
            ohos:id="$+id:music_artists_tv"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:text="$string:music_artist"
            ohos:text_size="10fp"
            ohos:text_color="$color:color_white"/>
    </DirectionalLayout>
    <Text
        ohos:id="$+id:music_duration_tv"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:text="$string:music_duration"
        ohos:text_size="10fp"
        ohos:layout_alignment="right|bottom"
        ohos:text_color="$color:color_white"/>
</DirectionalLayout>

4. 播放逻辑

4.1 列表点击事件的设置

listContainer.setItemClickedListener((listContainer1, component, i, l) -> {
    //get music object
    MusicBean item = (MusicBean) listContainer1.getItemProvider().getItem(i);
    //update some information
    currentPlayMusicPos = i;
    musicNameTv.setText(item.getTitle());
    musicArtistTv.setText(item.getArtist()+"-"+item.getAlbum());
    //update the button image
    //Regarding this execution statement, I hope you refer to the link below
    //https://blog.csdn.net/weixin_43699716/article/details/117448709?spm=1001.2014.3001.5501
    playBtn.setBackground(new VectorElement(this,ResourceTable.Graphic_ic_pause));
    //play the music
    try {
        if (PlayManager.getInstance().play(new Source(DataAbilityHelper
                                .creator(component.getContext())
                                .openFile(Uri.appendEncodedPathToUri(AVStorage.Audio.Media.EXTERNAL_DATA_ABILITY_URI, String.valueOf(item.getId())), "r")),0)) {
            HiLog.info(hiLogLabel, "播放成功");
        } else {
            HiLog.info(hiLogLabel, "播放失败");
        }
    } catch (DataAbilityRemoteException | FileNotFoundException e) {
        e.printStackTrace();
        HiLog.info(hiLogLabel, "播放失败");
    }
});

4.2 底部播放控件的设置

在这里用到的PlayManager() 类你可以在链接音乐播放器开发指导
中获取详情

playBtn.setClickedListener(component -> playMusic(component.getContext()));
lastBtn.setClickedListener(component -> lastMusic(component.getContext()));
nextBtn.setClickedListener(component -> nextMusic(component.getContext()));

4.2.1 playMusic()函数

private void playMusic(Context context){
    if(currentPlayMusicPos == -1){
        new ToastDialog(context).setText("请从播放列表中选择歌曲").setAlignment(LayoutAlignment.CENTER).show();
    }else{
        if(PlayManager.getInstance().isPlaying()){
            PlayManager.getInstance().pause();
            playBtn.setBackground(new VectorElement(this,ResourceTable.Graphic_ic_play));
        }else{
            MusicBean item = list.get(currentPlayMusicPos);
            play(item,context,PlayManager.getInstance().getAudioCurrentPosition());
        }
    }
}

4.2.2 lastMusic()函数

private void lastMusic(Context context){
    currentPlayMusicPos--;
    if (currentPlayMusicPos < 0) {
        currentPlayMusicPos = list.size() - 1;
    }
    MusicBean item = list.get(currentPlayMusicPos);
    play(item,context,0);
}

4.2.3 nextMusic()函数

private void lastMusic(Context context){
    currentPlayMusicPos--;
    if (currentPlayMusicPos < 0) {
        currentPlayMusicPos = list.size() - 1;
    }
    MusicBean item = list.get(currentPlayMusicPos);
    play(item,context,0);
}

4.2.4 play()函数

private void play(MusicBean musicBean,Context context,int time){
    musicNameTv.setText(musicBean.getTitle());
    musicArtistTv.setText(musicBean.getArtist()+"-"+musicBean.getAlbum());
    try {
        if (PlayManager.getInstance().play(new Source(DataAbilityHelper
                .creator(context)
                .openFile(Uri.appendEncodedPathToUri(AVStorage.Audio.Media.EXTERNAL_DATA_ABILITY_URI, String.valueOf(musicBean.getId())),"r")),time)) {
            HiLog.info(hiLogLabel, "播放成功");
            playBtn.setBackground(new VectorElement(this,ResourceTable.Graphic_ic_pause));
        } else {
            HiLog.info(hiLogLabel, "播放失败");
        }
    } catch (DataAbilityRemoteException | FileNotFoundException e) {
        e.printStackTrace();
        HiLog.info(hiLogLabel, "播放失败");
    }
}

最后

以上就是尊敬钻石为你收集整理的HarmongOS音乐播放器开发示例教程前言1. 所需知识和最终效果2. 资源获取3. UI布局4. 播放逻辑的全部内容,希望文章能够帮你解决HarmongOS音乐播放器开发示例教程前言1. 所需知识和最终效果2. 资源获取3. UI布局4. 播放逻辑所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部