@capawesome-team/capacitor-media-session¶
Capacitor plugin to interact with media controllers, volume keys and media buttons.
Features¶
We are proud to offer one of the most complete and feature-rich Capacitor plugins for media sessions. Here are some of the key features:
- 🖥️ Cross-platform: Supports Android, iOS and Web.
- 🎮 Media Controls: Handle hardware media keys, lock screen controls, and notification controls.
- 🎵 Rich Metadata: Display song title, artist, album, and artwork on lock screen and notifications.
- ▶️ Action Handlers: Support for play, pause, seek, next/previous track, and more.
- 📍 Position State: Track and display playback position, duration, and playback rate.
- 🔧 Native APIs: Uses MediaSession API on Android and MPNowPlayingInfoCenter on iOS for the best possible integration.
- 🤝 Compatibility: Compatible with the Audio Player plugin.
- 📦 SPM: Supports Swift Package Manager for iOS.
- 🔁 Up-to-date: Always supports the latest Capacitor version.
- ⭐️ Support: Priority support from the Capawesome Team.
- ✨ Handcrafted: Built from the ground up with care and expertise, not forked or AI-generated.
Missing a feature? Just open an issue and we'll take a look!
Compatibility¶
Plugin Version | Capacitor Version | Status |
---|---|---|
7.x.x | >=7.x.x | Active support |
Demo¶
Android | iOS | Web |
---|---|---|
![]() |
![]() |
![]() |
Installation¶
This plugin is only available to Capawesome Insiders. First, make sure you have the Capawesome npm registry set up. You can do this by running the following commands:
npm config set @capawesome-team:registry https://npm.registry.capawesome.io
npm config set //npm.registry.capawesome.io/:_authToken <YOUR_LICENSE_KEY>
Attention: Replace <YOUR_LICENSE_KEY>
with the license key you received from Polar. If you don't have a license key yet, you can get one by becoming a Capawesome Insider.
Next, install the package:
Android¶
Variables¶
If needed, you can define the following project variable in your app’s variables.gradle
file to change the default version of the dependency:
$androidMediaVersion
version ofandroidx.media:media
(default:1.7.1
)
Usage¶
import { AudioPlayer } from '@capawesome-team/capacitor-audio-player';
import {
MediaSession,
MediaSessionAction,
MediaSessionPlaybackState
} from '@capawesome-team/capacitor-media-session';
const setMetadata = async () => {
await MediaSession.setMetadata({
title: 'Test Song',
artist: 'My Awesome Artist',
album: 'My Awesome Album',
artwork: [
{
src: 'https://example.com/cover-96x96.png',
sizes: '96x96',
type: 'image/png',
},
{
src: 'https://example.com/cover-512x512.png',
sizes: '512x512',
type: 'image/png',
},
],
});
};
const registerActions = async () => {
await MediaSession.registerActionHandler({
action: MediaSessionAction.Play
});
await MediaSession.registerActionHandler({
action: MediaSessionAction.Pause
});
await MediaSession.registerActionHandler({
action: MediaSessionAction.SeekBackward
});
await MediaSession.registerActionHandler({
action: MediaSessionAction.SeekForward
});
await MediaSession.registerActionHandler({
action: MediaSessionAction.SeekTo
});
await MediaSession.registerActionHandler({
action: MediaSessionAction.Stop
});
};
const setPlaybackState = async () => {
await MediaSession.setPlaybackState({
playbackState: MediaSessionPlaybackState.Playing,
});
};
const setPositionState = async () => {
await MediaSession.setPositionState({
duration: 180,
playbackRate: 1.0,
position: 30,
});
};
const addActionListener = () => {
MediaSession.addListener('action', async (event) => {
switch (event.action) {
case MediaSessionAction.Play:
await AudioPlayer.resume();
await MediaSession.setPlaybackState({
playbackState: MediaSessionPlaybackState.Playing,
});
break;
case MediaSessionAction.Pause:
await AudioPlayer.pause();
await MediaSession.setPlaybackState({
playbackState: MediaSessionPlaybackState.Paused,
});
break;
case MediaSessionAction.SeekBackward:
const { position: currentPos } = await AudioPlayer.getCurrentPosition();
const offsetMs = event.seekOffset ? event.seekOffset * 1000 : 10000;
await AudioPlayer.seekTo({
position: Math.max(0, currentPos - offsetMs)
});
break;
case MediaSessionAction.SeekForward:
const { position: pos } = await AudioPlayer.getCurrentPosition();
const { duration } = await AudioPlayer.getDuration();
const offset = event.seekOffset ? event.seekOffset * 1000 : 10000;
await AudioPlayer.seekTo({
position: Math.min(duration, pos + offset)
});
break;
case MediaSessionAction.SeekTo:
if (event.seekTime !== undefined) {
await AudioPlayer.seekTo({
position: event.seekTime * 1000
});
}
break;
case MediaSessionAction.Stop:
await AudioPlayer.stop();
await MediaSession.setPlaybackState({
playbackState: MediaSessionPlaybackState.None,
});
break;
}
});
};
const removeActionListener = async () => {
await MediaSession.unregisterActionHandler({
action: MediaSessionAction.Play
});
await MediaSession.unregisterActionHandler({
action: MediaSessionAction.Pause
});
await MediaSession.removeAllListeners();
};
API¶
registerActionHandler(...)
setCameraActive(...)
setMetadata(...)
setMicrophoneActive(...)
setPlaybackState(...)
setPositionState(...)
unregisterActionHandler(...)
addListener('action', ...)
removeAllListeners()
- Interfaces
- Enums
registerActionHandler(...)¶
Register a handler for a media session action.
If the action handler is registered, the media session will respond to the action
by calling the action
event listener. If the action handler is not registered,
the media session will not respond to the action.
Make sure to unregister the action handler when it is no longer needed.
Param | Type |
---|---|
options |
RegisterActionHandlerOptions |
Since: 0.0.1
setCameraActive(...)¶
Set the camera active state.
Only available on Web.
Param | Type |
---|---|
options |
SetCameraActiveOptions |
Since: 0.0.1
setMetadata(...)¶
Set the metadata for the media session.
Param | Type |
---|---|
options |
SetMetadataOptions |
Since: 0.0.1
setMicrophoneActive(...)¶
Set the microphone active state.
Only available on Web.
Param | Type |
---|---|
options |
SetMicrophoneActive |
Since: 0.0.1
setPlaybackState(...)¶
Set the playback state.
Param | Type |
---|---|
options |
SetPlaybackStateOptions |
Since: 0.0.1
setPositionState(...)¶
Set the position state.
Param | Type |
---|---|
options |
SetPositionStateOptions |
Since: 0.0.1
unregisterActionHandler(...)¶
Unregister a handler for a media session action.
If the action handler is unregistered, the media session will no longer respond to the action
and the action
event listener will no longer be called for the specific action.
Param | Type |
---|---|
options |
UnregisterActionHandlerOptions |
Since: 0.0.1
addListener('action', ...)¶
addListener(eventName: 'action', listenerFunc: (event: ActionEvent) => void) => Promise<PluginListenerHandle>
Param | Type |
---|---|
eventName |
'action' |
listenerFunc |
(event: ActionEvent) => void |
Returns: Promise<PluginListenerHandle>
Since: 0.0.1
removeAllListeners()¶
Remove all listeners for this plugin.
Since: 0.0.1
Interfaces¶
RegisterActionHandlerOptions¶
Prop | Type | Description | Since |
---|---|---|---|
action |
MediaSessionAction |
The action to handle. | 0.0.1 |
SetCameraActiveOptions¶
Prop | Type | Description | Since |
---|---|---|---|
active |
boolean |
Whether or not the camera is active. | 0.0.1 |
SetMetadataOptions¶
Prop | Type | Description | Since |
---|---|---|---|
album |
string |
0.0.1 | |
artist |
string |
0.0.1 | |
artwork |
MediaMetadataArtwork[] |
Only available on iOS and Web. | 0.0.1 |
title |
string |
0.0.1 |
MediaMetadataArtwork¶
Prop | Type | Description | Since |
---|---|---|---|
sizes |
string |
The size of the artwork. | 0.0.1 |
src |
string |
The URL from which the user agent fetches the image's data. | 0.0.1 |
type |
string |
The MIME type hint for the user agent. | 0.0.1 |
SetMicrophoneActive¶
Prop | Type | Description | Since |
---|---|---|---|
active |
boolean |
Whether or not the microphone is active. | 0.0.1 |
SetPlaybackStateOptions¶
Prop | Type | Description | Since |
---|---|---|---|
playbackState |
MediaSessionPlaybackState |
The playback state to set. | 0.0.1 |
SetPositionStateOptions¶
Prop | Type | Description | Since |
---|---|---|---|
duration |
number |
The duration of the media in seconds. | 0.0.1 |
playbackRate |
number |
The playback rate of the media. | 0.0.1 |
position |
number |
The current position of the media in seconds. | 0.0.1 |
UnregisterActionHandlerOptions¶
Prop | Type | Description | Since |
---|---|---|---|
action |
MediaSessionAction |
The action to unregister. | 0.0.1 |
PluginListenerHandle¶
Prop | Type |
---|---|
remove |
() => Promise<void> |
ActionEvent¶
Prop | Type | Description | Since |
---|---|---|---|
action |
MediaSessionAction |
The action that was handled. | 0.0.1 |
fastSeek |
boolean |
Whether or not the action was a fast seek. | 0.0.1 |
seekOffset |
number |
The offset in seconds to seek to. | 0.0.1 |
seekTime |
number |
The time in seconds to seek to. | 0.0.1 |
Enums¶
MediaSessionAction¶
Members | Value | Description | Since |
---|---|---|---|
Play |
'PLAY' |
0.0.1 | |
Pause |
'PAUSE' |
0.0.1 | |
SeekBackward |
'SEEK_BACKWARD' |
0.0.1 | |
SeekForward |
'SEEK_FORWARD' |
0.0.1 | |
PreviousTrack |
'PREVIOUS_TRACK' |
0.0.1 | |
NextTrack |
'NEXT_TRACK' |
0.0.1 | |
SkipAd |
'SKIP_AD' |
Only available on Web. | 0.0.1 |
Stop |
'STOP' |
0.0.1 | |
SeekTo |
'SEEK_TO' |
0.0.1 | |
ToggleMicrophone |
'TOGGLE_MICROPHONE' |
Only available on Web. | 0.0.1 |
ToggleCamera |
'TOGGLE_CAMERA' |
Only available on Web. | 0.0.1 |
ToggleScreenShare |
'TOGGLE_SCREEN_SHARE' |
Only available on Web. | 0.0.1 |
HangUp |
'HANG_UP' |
Only available on Web. | 0.0.1 |
PreviousSlide |
'PREVIOUS_SLIDE' |
Only available on Web. | 0.0.1 |
NextSlide |
'NEXT_SLIDE' |
Only available on Web. | 0.0.1 |
EnterPictureInPicture |
'ENTER_PICTURE_IN_PICTURE' |
Only available on Web. | 0.0.1 |
VoiceActivity |
'VOICE_ACTIVITY' |
Only available on Web. | 0.0.1 |
MediaSessionPlaybackState¶
Members | Value | Since |
---|---|---|
None |
'NONE' |
0.0.1 |
Paused |
'PAUSED' |
0.0.1 |
Playing |
'PLAYING' |
0.0.1 |
Changelog¶
See CHANGELOG.md.
Breaking Changes¶
See BREAKING.md.
License¶
See LICENSE.