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 entriesgetAVQueueTitle()— Playlist namegetAVPlaybackState()— Transport statusgetAVMetadata()— 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