Building a Media Controller with Custom AVSession Communication in HarmonyOS

Media controller implementation leverages AVSession APIs to facilitate bidirectional communication with a media provider. The capabilities demonstrated here require a companion provider implementation for complete custom data flow, and controller interfaces are restricted to system-level applications.

Project Structure

entry/src/main/ets/
|---utils
|---|---Logger.ets                    // Encapsulated logging utilities
|---service
|---|---PlaybackController.ets        // Core controller orchestration
|---view
|---|---PlayerView.ets               // UI implementation

UI-to-Logic Synchronization

The presentation layer binds to backend state through @StorageLink. When underlying properties mutate, the interface refreshes automatically.

import { PlaybackController } from '../service/PlaybackController';
let controlHandler: PlaybackController = new PlaybackController();
await controlHandler.initializeSession();

Reactive linkage between business logic and the view relies on AppStorage. The following pattern establishes observable state:

private playbackStateLink: SubscribedAbstractProperty<boolean> | undefined = undefined;
this.playbackStateLink = AppStorage.setAndLink('playbackActive', false);
this.playbackStateLink.set(false);
let active: boolean = this.playbackStateLink.get();

Controller Initialization

Retrieve existing media sessions via getAllSessionDescriptors(), then instantiate a dedicated controller through createController(). Historical sessions are accessible using getHistoricalSessionDescriptors().

Registre event listeners to handle provider-side changes:

controller.on('metadataChange', (metadata: AVMetadata) => {
  this.updateTrackInfo(metadata);
});
controller.on('playbackStateChange', (state: AVPlaybackState) => {
  this.syncTransportState(state);
});
controller.on('sessionEvent', (event: string, data: Record<string, Object>) => {
  this.handleCustomEvent(event, data);
});

Command Dispatch

Send standard transport directives through sendControlCommand():

const playCmd: AVSessionManager.AVControlCommand = {
  command: 'play',
  parameter: undefined
};
await targetController.sendControlCommand(playCmd);

Supported directives include play, pause, playPrevious, and playNext.

For application-specific interactions, use sendCommonCommand(). The following snippet requests lyric visibility toggles:

const lyricPayload: Record<string, Object> = {
  'lyricsVisible': this.displayLyrics
};
await targetController.sendCommonCommand('lyrics', lyricPayload);

Upon receiving this instruction, the provider pushes lyric data through dispatchSessionEvent() paired with setExtras().

Session Data Retrieval

Fetch current queue and playback context through the following interfaces:

  • getAVQueueItems() — Current playlist entries
  • getAVQueueTitle() — Playlist name
  • getAVPlaybackState() — Transport status
  • getAVMetadata() — Track metadata

Required Permissions

System application privileges are mandatory. Configure the module signature with "app-feature": "hos_system_app".

Optional network access for remote artwork resources:

{
  "module": {
    "requestPermissions": [
      { "name": "ohos.permission.INTERNET" }
    ]
  }
}

Optional bundle resolution for retrieving provider application names and icons:

{
  "module": {
    "requestPermissions": [
      { "name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED" }
    ]
  }
}

Development Constraints

  • Target hardware: RK3568 and compatible standard-system devices
  • Application model: Stage
  • Minimum SDK: API Version 10 Release (image 4.0 Release)
  • Minimum IDE: DevEco Studio 4.0 Release
  • System interface access mandates system-application signing configuration

Tags: HarmonyOS AVSession Media Controller ArkTS System Application

Posted on Sat, 31 Oct 2026 16:44:00 +0000 by kaje