DEV Community

HarmonyOS
HarmonyOS

Posted on • Edited on

Getting Started with AudioKit in HarmonyOS (AVPlayer)

Read the original article:Getting Started with AudioKit in HarmonyOS (AVPlayer)
Audio Kit

Audio Kit

Build a simple audio player in HarmonyOS using AVPlayer to play embedded .mp3 files and manage song data with a model.

Introduction

Ever wanted to build a music player in your HarmonyOS app? In this guide, we will walk through a basic audio service using AVPlayer. We will also show how to structure a SongModel to manage song data like name, artist, path, and favorites.

What You Need

  • HarmonyOS Next environment
  • AudioKit and MediaKit libraries
  • An .mp3 file inside your raw resources folder

Let’s dive in.

Song Model: Storing Song Information

Before building the service, let’s define our song structure. We will use a simple class to store metadata.
With this model, you can list songs, filter favorites, or access paths for playback.

export class SongModel {
  public songName: string;
  public songAuthor: string;
  public isFavorite: boolean;
  public songPath: string;

  constructor(songName: string, songAuthor: string, songPath: string, isFavorite: boolean = false) {
    this.songName = songName;
    this.songAuthor = songAuthor;
    this.isFavorite = isFavorite;
    this.songPath = songPath;
  }

  static empty() {
    return new SongModel('', '', '')
  }
}
Enter fullscreen mode Exit fullscreen mode
SongModel to use in our Player

Audio Service with AVPlayer

We will build a singleton AudioService class to manage playback. It ensures only one audio instance is used.

import { media } from '@kit.MediaKit';
import { audio } from '@kit.AudioKit';
import { common } from '@kit.AbilityKit';
import { SongModel } from '../models/SongModel';

export enum AudioStatus {
  Undefined,
  Playing,
  Paused,
  Released,
}

@ObservedV2
export class AudioService {
  static _instance: AudioService;

  static getInstance() {
    if (!AudioService._instance) {
      AudioService._instance = new AudioService(AudioStatus.Undefined);
    }
    return AudioService._instance;
  }

  constructor(audioStatus: AudioStatus) {
    this.audioStatus = audioStatus;
  }

  private player: media.AVPlayer | undefined;
  @Trace audioStatus: AudioStatus;

  setCallbacks(avPlayer: media.AVPlayer) {
    avPlayer.on('stateChange', async (state: string) => {
      console.info('AVPlayer state:', state);
      switch (state) {
        case 'initialized':
          avPlayer.audioRendererInfo = {
            usage: audio.StreamUsage.STREAM_USAGE_MUSIC,
            rendererFlags: 0,
          };
          avPlayer.prepare();
          break;
        case 'prepared':
          this.audioStatus = AudioStatus.Playing
          avPlayer.play();
          break;
        case 'completed':
          this.audioStatus = AudioStatus.Released
          avPlayer.stop();
          break;
        case 'stopped':
          avPlayer.reset();
          break;
        case 'pause':
          avPlayer.pause();
          break;
      }
    });

    avPlayer.on('error', (err) => {
      console.error('AVPlayer error:', err.message);
      avPlayer.reset();
    });
  }

  public async playEmbeddedMp3(fileName: string) {
    this.release();
    const context = getContext(this) as common.UIAbilityContext;
    const resourceFd = await context.resourceManager.getRawFd(fileName);

    const avFileDescriptor: media.AVFileDescriptor = {
      fd: resourceFd.fd,
      offset: resourceFd.offset,
      length: resourceFd.length,
    };
    this.player = await media.createAVPlayer();
    this.setCallbacks(this.player);
    this.player.fdSrc = avFileDescriptor;
  }

  public pause() {
    this.audioStatus = AudioStatus.Paused
    this.player?.pause();
  }

  public resume() {
    this.audioStatus = AudioStatus.Playing
    this.player?.play();
  }

  public stop() {
    this.audioStatus = AudioStatus.Released
    this.player?.stop();
  }

  public release() {
    this.audioStatus = AudioStatus.Released
    this.player?.reset();
  }
}
Enter fullscreen mode Exit fullscreen mode
AudioService to paste and use

This service manages all audio states (play, pause, stop, release). With callbacks, we listen for player events like completed, paused, or error.

How to Use It

You can call your service like this:

//Define
const audioService = AudioService.getInstance();
audioService.playEmbeddedMp3('demo.mp3');

//Pause or resume
audioService.pause();
audioService.resume();

//Stop
audioService.stop();
Enter fullscreen mode Exit fullscreen mode
How to use

Tips & Tricks

  • Always call release() before loading a new file to avoid memory leaks.
  • Use a progress tracker or timer to update UI (not shown here).
  • You can link this with SongModel to dynamically show metadata. Conclusion We built a basic audio player using AVPlayer in HarmonyOS. With AudioService and SongModel, your app can now play music files and manage song data. This is a simple but solid base to build advanced features. Next steps: Try adding a UI or integrating favorite songs using SongModel. ​​​​​​​
    Example Audio Player

References

(https://forums.developer.huawei.com/forumPortal/en/topic/0203189343495001014?fid=0102647487706140266)

Written by Emirhan Serin

Top comments (0)