0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

HarmonyOS開發(fā)案例:【音樂播放器】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-04-23 15:44 ? 次閱讀

介紹

使用ArkTS語言實現(xiàn)了一個簡易的音樂播放器應(yīng)用,主要包含以下功能:

  1. 播放應(yīng)用中的音頻資源文件,并可進行上一曲、下一曲、播放、暫停、切換播放模式(順序播放、單曲循環(huán)、隨機播放)等操作。
  2. 結(jié)合后臺任務(wù)管理模塊,實現(xiàn)熄屏后繼續(xù)播放音頻。

相關(guān)概念

  • [AVPlayer]:AVPlayer主要工作是將Audio/Video媒體資源轉(zhuǎn)碼為可供渲染的圖像和可聽見的音頻模擬信號,并通過輸出設(shè)備進行播放,同時對播放任務(wù)進行管理,包括開始播放、暫停播放、停止播放、釋放資源、設(shè)置音量、跳轉(zhuǎn)播放位置、獲取軌道信息等功能控制。
  • [后臺任務(wù)管理]:針對應(yīng)用或業(yè)務(wù)模塊處于后臺(無可見界面)時,有需要繼續(xù)執(zhí)行或者后續(xù)執(zhí)行的業(yè)務(wù),可基于業(yè)務(wù)類型,申請短時任務(wù)延遲掛起或者長時任務(wù)避免進入掛起狀態(tài);如后臺播放音樂可使用長時任務(wù)避免進入掛起狀態(tài)。
  • 鴻蒙開發(fā)指導(dǎo)文檔:[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]

約束與限制

  1. 本篇Codelab部分能力依賴于系統(tǒng)API,需下載full-SDK并替換DevEco Studio自動下載的public-SDK。具體操作可參考指南[《如何替換full-SDK》]。
  2. 本篇Codelab使用的部分API僅系統(tǒng)應(yīng)用可用,需要提升應(yīng)用等級。

環(huán)境搭建

軟件要求

  • [DevEco Studio]版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 開發(fā)板類型:[潤和RK3568開發(fā)板]。
  • OpenHarmony系統(tǒng):3.2 Release。

環(huán)境搭建

完成本篇Codelab我們首先要完成開發(fā)環(huán)境的搭建,本示例以RK3568開發(fā)板為例,參照以下步驟進行:

  1. [獲取OpenHarmony系統(tǒng)版本]:標準系統(tǒng)解決方案(二進制)。以3.2 Release版本為例:
  2. 搭建燒錄環(huán)境。
    1. [完成DevEco Device Tool的安裝]
    2. [完成RK3568開發(fā)板的燒錄]
  3. 搭建開發(fā)環(huán)境。
    1. 開始前請參考[工具準備],完成DevEco Studio的安裝和開發(fā)環(huán)境配置。
    2. 開發(fā)環(huán)境配置完成后,請參考[使用工程向?qū)創(chuàng)建工程(模板選擇“Empty Ability”)。
    3. 工程創(chuàng)建完成后,選擇使用[真機進行調(diào)測]。
    4. HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿

搜狗高速瀏覽器截圖20240326151450.png

代碼結(jié)構(gòu)解讀

本篇Codelab只對核心代碼進行講解,對于完整代碼,我們會在gitee中提供。

├──entry/src/main/ets               // 代碼區(qū)
│  ├──common              
│  │  ├──constants                   
│  │  │  └──CommonConstants.ets     // 公共常量
│  │  ├──model                   
│  │  │  └──PlayBarModel            // 播放欄數(shù)據(jù)模型
│  │  └──utils
│  │     ├──AvSessionUtil.ets  	    // 媒體會話工具類	
│  │     ├──BackgroundTaskUtil.ets  // 后臺任務(wù)工具類
│  │     ├──CommonUtil.ets  	    // 公共工具類	
│  │     ├──GlobalContext.ets  	    // 公共工具類	
│  │     ├──Logger.ets              // 日志類          
│  │     └──ResourceManagerUtil.ets // 資源管理工具類
│  ├──controller           
│  │  ├──AudioPlayerController.ets  // 音樂播放器控制器
│  │  └──PlayBarController.ets      // 播放欄控制器
│  ├──entryability                    
│  │  └──EntryAbility.ets           // 程序入口類
│  ├──pages                          
│  │  ├──AudioStartUp.ets           // 啟動頁
│  │  ├──MusicList.ets              // 歌單頁
│  │  └──Play.ets                   // 播放頁
│  ├──view                         
│  │  ├──MusicCardView.ets          // 播放卡片模塊
│  │  ├──MusicView.ets              // 歌單音樂模塊
│  │  ├──PlayBarView.ets            // 播放控制模塊
│  │  ├──PlayListDialogView.ets     // 彈窗模塊
│  │  ├──PlayListMusicView.ets      // 彈窗音樂模塊
│  │  └──ProgressView.ets           // 播放頁
│  └──viewmodel  
│     ├──MusicItem.ets              // 音樂類
│     └──MusicViewModel.ets         // 歌單音樂模型
└──entry/src/main/resources         // 應(yīng)用資源目錄

實現(xiàn)音頻播放

本案例使用播放管理類AVPlayer,實現(xiàn)應(yīng)用內(nèi)音頻資源的播放,并可進行上一曲、下一曲、播放、暫停、切換播放模式(順序播放、單曲循環(huán)、隨機播放)等操作。

使用AVPlayer播放器,需要先創(chuàng)建一個AVPlayer實例。在AudioPlayerController中使用createAVPlayer方法完成音頻播放實例的創(chuàng)建。

// AudioPlayerController.ets
initAudioPlayer() {
  media.createAVPlayer((error, video) = > {
    if (video === undefined) {
      this.avPlayer = video;
      Logger.error(TAG, `createAVPlayer fail, error: ${error}`);
    } else {
      this.avPlayer = video;
      Logger.info(TAG, 'createAVPlayer success');
    }
  });
}

根據(jù)業(yè)務(wù)需要設(shè)置監(jiān)聽事件,搭配播放場景使用。

// AudioPlayerController.ets
// 注冊AVPlayer回調(diào)函數(shù)
setEventCallBack() {
  ...
  // 狀態(tài)變更回調(diào)函數(shù)。
  this.avPlayer.on('stateChange', async (state) = > {
    ...
    switch (state) {
      case StateEvent.IDLE: // 調(diào)用reset成功后觸發(fā)此狀態(tài)。
        ...
      case StateEvent.INITIALIZED: // 設(shè)置播放源觸發(fā)此狀態(tài)。
        ...
      case StateEvent.PREPARED:
        ...
      case StateEvent.PLAYING:
        ...
      case StateEvent.COMPLETED:
        ...
      default:
        Logger.error('unknown state: ' + state);
        break;
    }
  })
}

設(shè)置音頻資源,AVPlayer進入initialized狀態(tài)。在initialized狀態(tài)回調(diào)中,調(diào)用prepare方法,準備播放,AVPlayer進入prepared狀態(tài)。

// AudioPlayerController.ets
async play(src: media.AVFileDescriptor, seekTo: number) {
  Logger.info(TAG, 'audioPlayer play');
  ...
  // 設(shè)置播放源
  this.avPlayer.fdSrc = src;
}

setEventCallBack() {
  ...
  this.avPlayer.on('stateChange', async (state) = > {
    ...
    switch (state) {
      ...
      case StateEvent.INITIALIZED:// 設(shè)置播放源后進入initialized狀態(tài)
        Logger.info(TAG, 'state initialized called');
        this.avPlayerState = PlayerState.INITIALIZED;
        this.avPlayer.prepare().then(() = > {
          Logger.info(TAG, 'prepare success');
        }, (err) = > {
          Logger.error(TAG, `prepare failed,error message is: ${err.message}`);
        })
        break;
      ...
    }
  })
}

AVPlayer進入prepared狀態(tài),可進行音頻播控操作。包括播放play()、跳轉(zhuǎn)至指定位置播放seek()、暫停pause()、停止stop()等操作。

// AudioPlayerController.ets
setEventCallBack() {
  ...
  this.avPlayer.on('stateChange', async (state) = > {
    ...
    switch (state) {
      ...
      case StateEvent.PREPARED:
        Logger.info(TAG, 'state prepared called');
        this.avPlayer.play();
        break;
      ...
    }
  })
}

切換歌曲播放時,需調(diào)用reset()重置資源。此時AVPlayer重新進入idle狀態(tài),允許更換資源。

// AudioPlayerController.ets
async play(src: media.AVFileDescriptor, seekTo: number) {
  ...
  if (this.avPlayerState === PlayerState.INITIALIZED) {
    await this.avPlayer.reset();
    Logger.info(TAG, 'play reset success');
  }
  ...
}

說明: 只能在initialized/prepared/playing/paused/complete/stopped/error狀態(tài)調(diào)用reset()。

調(diào)用release()銷毀實例,AVPlayer進入released狀態(tài),退出播放。

// AudioPlayerController.ets
async release() {
  Logger.info(TAG, 'audioPlayer release');
  if (typeof (this.avPlayer) !== 'undefined') {
    if (this.timeId === CommonConstants.DEFAULT_TIME_ID) {
      clearInterval(this.timeId);
    }
    await this.avPlayer.release();
    this.avPlayer = undefined;
  }
}

實現(xiàn)熄屏后播放

通過后臺任務(wù)管理模塊申請長時任務(wù),可避免設(shè)備熄屏后,應(yīng)用進入掛起狀態(tài)。

首先在module.json5文件中配置長時任務(wù)權(quán)限和后臺模式類型。

"module": {
  ...
  "abilities": [
    {
      ...
      "backgroundModes": [
        "audioPlayback"
      ],
      ...
    }
  ],
  "requestPermissions": [
    {
      "name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
    }
  ],
}

在播放音樂時,申請長時任務(wù)。這樣在應(yīng)用切換至后臺或設(shè)備熄屏后,仍可以繼續(xù)播放音樂。

// BackgroundTaskUtil.ets
import wantAgent from '@ohos.app.ability.wantAgent';
import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
...
export class BackgroundTaskUtil {
  ...
  public static startContinuousTask(context: Context) {
    if (context === undefined) {
      Logger.info(TAG, 'startContinuousTask fail,context is empty.');
      return;
    }
    let wantAgentInfo = {
      // 點擊通知后需要執(zhí)行的動作
      wants: [
        {
          bundleName: CommonConstants.BUNDLE_NAME,
          abilityName: CommonConstants.ABILITY_NAME
        }
      ],
      // 單擊通知后的動作類型
      operationType: wantAgent.OperationType.START_ABILITY,
      // 用戶定義的私有屬性
      requestCode: CommonConstants.BACKGROUND_REQUEST_CODE
    } as wantAgent.WantAgentInfo;

    // 通過WanAgent模塊的方法獲取WanAgent對象
    wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) = > {
      try {
        backgroundTaskManager.startBackgroundRunning(context, backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,
          wantAgentObj).then(() = > {
          Logger.info(TAG, 'startBackgroundRunning succeeded');
        }).catch((err: Error) = > {
          Logger.error(TAG, 'startBackgroundRunning failed, Cause: ' + JSON.stringify(err));
        });
      } catch (error) {
        Logger.error(TAG, `startBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
      }
    });
  }
  ...
}

暫停音樂播放,結(jié)束長時任務(wù)。

// BackgroundTaskUtil.ets
import wantAgent from '@ohos.app.ability.wantAgent';
import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
...
export class BackgroundTaskUtil {
  ...
  public static stopContinuousTask(context: Context) {
    if (context === undefined) {
      Logger.info(TAG, 'stopContinuousTask fail,context is empty.');
      return;
    }
    try {
      backgroundTaskManager.stopBackgroundRunning(context).then(() = > {
        Logger.info(TAG, 'stopBackgroundRunning succeeded');
      }).catch((err: Error) = > {
        Logger.error(TAG, 'stopBackgroundRunning failed Cause: ' + JSON.stringify(err));
      });
    } catch (error) {
      Logger.error(TAG, `stopBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
    }
  }
}

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 鴻蒙
    +關(guān)注

    關(guān)注

    57

    文章

    2352

    瀏覽量

    42863
  • HarmonyOS
    +關(guān)注

    關(guān)注

    79

    文章

    1975

    瀏覽量

    30209
  • OpenHarmony
    +關(guān)注

    關(guān)注

    25

    文章

    3722

    瀏覽量

    16323
收藏 人收藏

    評論

    相關(guān)推薦

    基于RTT-LVGL的音樂播放器設(shè)計案例

    此次項目主要是基于瑞薩HMI board 開發(fā)板實現(xiàn)音樂播放器功能,主要可以實現(xiàn)sd卡wav 文件掃描,音樂播放,音量調(diào)節(jié)、上一曲、下一曲
    的頭像 發(fā)表于 09-18 11:07 ?2256次閱讀
    基于RTT-LVGL的<b class='flag-5'>音樂</b><b class='flag-5'>播放器</b>設(shè)計案例

    音樂播放器

    音樂播放器,播放和暫停
    發(fā)表于 05-28 17:30

    網(wǎng)頁音樂播放器代碼

    網(wǎng)頁音樂播放器代碼:有MP3的,有Windows Media Player音樂播放器代碼的,也有視頻的,
    發(fā)表于 01-10 11:18 ?86次下載

    Windows Media Player音樂播放器代碼

    Windows Media Player音樂播放器代碼 一、Windows Media Player音樂播放器代碼:
    發(fā)表于 01-10 11:14 ?2272次閱讀

    rm格式音樂播放器代碼

      rm格式音樂播放器代碼
    發(fā)表于 01-10 11:15 ?1262次閱讀

    基于單片機的音樂播放器

    基于單片機的音樂播放器,內(nèi)容包含程序代碼和電路proteus仿真。
    發(fā)表于 03-10 11:14 ?35次下載

    音樂播放器

    音樂播放器,比較簡單。能實現(xiàn)基本的播放停止暫停等功能。喜歡研究可以改進
    發(fā)表于 09-09 17:32 ?38次下載

    基于Android音樂播放器的研究

    Android平臺是目前智能移動終端的主流系統(tǒng)。隨著人們生活、工作節(jié)奏的加快,乘車、運動、學習等碎片時間的增多,音樂播放器成為人們所關(guān)心的必備應(yīng)用之一,廣受大家歡迎。 目前,Android市場上以酷
    發(fā)表于 12-11 11:44 ?7次下載
    基于Android<b class='flag-5'>音樂</b><b class='flag-5'>播放器</b>的研究

    數(shù)碼播放器開發(fā)案

    數(shù)碼播放器開發(fā)案例說明。
    發(fā)表于 05-19 11:07 ?6次下載

    基于Labview制作的音樂播放器源碼分享

    基于Labview制作的音樂播放器源碼分享
    發(fā)表于 12-01 10:07 ?70次下載

    基于Arduino的音樂播放器設(shè)計

    厭倦了呆板的音響設(shè)備,那就動手制作一個音樂播放器吧。本項目可播放WAV格式音樂,用戶只需簡單的接線和焊接技能即可完成制作。
    發(fā)表于 03-25 11:27 ?6180次閱讀
    基于Arduino的<b class='flag-5'>音樂</b><b class='flag-5'>播放器</b>設(shè)計

    如何利用Arduino UNO和SD卡制作音樂播放器

    前面用ATtiny85制作SD卡音樂播放器,本次主要利用Arduino UNO 和SD卡制作音樂播放器。這個播放器不需要添加多余的模塊,只需
    的頭像 發(fā)表于 04-13 16:45 ?7981次閱讀
    如何利用Arduino UNO和SD卡制作<b class='flag-5'>音樂</b><b class='flag-5'>播放器</b>

    HarmonyOS開發(fā)案例:【視頻播放器

    基于video、swiper和slider組件,實現(xiàn)簡單的視頻播放器,可支持海報輪播、視頻播放等功能。
    的頭像 發(fā)表于 04-22 21:06 ?469次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發(fā)案</b>例:【視頻<b class='flag-5'>播放器</b>】

    HarmonyOS開發(fā)案例:【視頻播放器

    使用ArkTS語言實現(xiàn)視頻播放器,主要包括主界面和視頻播放界面,
    的頭像 發(fā)表于 04-23 17:25 ?703次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發(fā)案</b>例:【視頻<b class='flag-5'>播放器</b>】

    HarmonyOS開發(fā)案例:【視頻播放器

    使用ArkTS語言實現(xiàn)視頻播放器,主要包括主頁面和視頻播放頁面
    的頭像 發(fā)表于 04-24 14:52 ?903次閱讀
    <b class='flag-5'>HarmonyOS</b><b class='flag-5'>開發(fā)案</b>例:【視頻<b class='flag-5'>播放器</b>】