---
description: Capacitor plugin to interact with media controls and metadata for a seamless media playback experience across platforms.
title: Capacitor Media Session Plugin for Android, iOS & Web - Capawesome
image: https://capawesome.io/docs/assets/images/social/sdks/capacitor/media-session.png
---

<!doctype html> 

[Skip to content ](#capacitor-media-session-plugin) 

[🖥️ Introducing the **Capacitor Electron Platform** — build desktop apps for macOS, Windows, and Linux. Free & open source. ](/blog/announcing-the-capacitor-electron-platform/) 

* [ SDKs ](/docs/sdks/)
* [ Formbricks ](/docs/sdks/capacitor/formbricks/)
* [ Geocoder ](/docs/sdks/capacitor/geocoder/)
* [ Google Sign-In ](/docs/sdks/capacitor/google-sign-in/)
* [ Grafana Faro ](/docs/sdks/capacitor/grafana-faro/)
* [ Gyroscope ](/docs/sdks/capacitor/gyroscope/)
* [ Haptics ](/docs/sdks/capacitor/haptics/)
* [ Home Indicator ](/docs/sdks/capacitor/home-indicator/)
* [ In-App Browser ](/docs/sdks/capacitor/in-app-browser/)
* [ Install Referrer ](/docs/sdks/capacitor/install-referrer/)
* [ Intercom ](/docs/sdks/capacitor/intercom/)
* [ Intune ](/docs/sdks/capacitor/intune/)
* [ Keep Awake ](/docs/sdks/capacitor/keep-awake/)
* [ libSQL ](/docs/sdks/capacitor/libsql/)
* [ Light Sensor ](/docs/sdks/capacitor/light-sensor/)
* [ Live Update ](/docs/sdks/capacitor/live-update/)
* [ Localization ](/docs/sdks/capacitor/localization/)
* [ Mail Composer ](/docs/sdks/capacitor/mail-composer/)
* [ Managed Configurations ](/docs/sdks/capacitor/managed-configurations/)
* [ Maps Launcher ](/docs/sdks/capacitor/maps-launcher/)
* Media Session [ Media Session ](/docs/sdks/capacitor/media-session/)
* [ Configuration ](#configuration)
* [ Usage ](#usage)
* [ API ](#api)
* [ Enums ](#enums)
* [ FAQ ](#faq)
* [ Related Plugins ](#related-plugins)
* [ Newsletter ](#newsletter)
* [ Changelog ](#changelog)
* [ Breaking Changes ](#breaking-changes)
* [ License ](#license)
* [ ML Kit ](/docs/sdks/capacitor/mlkit/)
* [ Navigation Bar ](/docs/sdks/capacitor/navigation-bar/)
* [ Network ](/docs/sdks/capacitor/network/)
* [ NFC ](/docs/sdks/capacitor/nfc/)
* [ Node.js ](/docs/sdks/capacitor/nodejs/)
* [ OAuth ](/docs/sdks/capacitor/oauth/)
* [ Passkeys ](/docs/sdks/capacitor/passkeys/)
* [ Password Autofill ](/docs/sdks/capacitor/password-autofill/)
* [ PDF Generator ](/docs/sdks/capacitor/pdf-generator/)
* [ PDF Viewer ](/docs/sdks/capacitor/pdf-viewer/)
* [ Pedometer ](/docs/sdks/capacitor/pedometer/)
* [ Permissions ](/docs/sdks/capacitor/permissions/)
* [ Phone Dialer ](/docs/sdks/capacitor/phone-dialer/)
* [ Photo Editor ](/docs/sdks/capacitor/photo-editor/)
* [ Photo Manipulator ](/docs/sdks/capacitor/photo-manipulator/)
* [ PixLive ](/docs/sdks/capacitor/pixlive/)
* [ PostHog ](/docs/sdks/capacitor/posthog/)
* [ Printer ](/docs/sdks/capacitor/printer/)
* [ Privacy Screen ](/docs/sdks/capacitor/privacy-screen/)
* [ Proximity Sensor ](/docs/sdks/capacitor/proximity-sensor/)
* [ Purchases ](/docs/sdks/capacitor/purchases/)
* [ RealtimeKit ](/docs/sdks/capacitor/realtimekit/)
* [ Root Detection ](/docs/sdks/capacitor/root-detection/)
* [ Screen Brightness ](/docs/sdks/capacitor/screen-brightness/)
* [ Screen Orientation ](/docs/sdks/capacitor/screen-orientation/)
* [ Screen Reader ](/docs/sdks/capacitor/screen-reader/)
* [ Screenshot ](/docs/sdks/capacitor/screenshot/)
* [ Secure Preferences ](/docs/sdks/capacitor/secure-preferences/)
* [ Settings Launcher ](/docs/sdks/capacitor/settings-launcher/)
* [ Shake ](/docs/sdks/capacitor/shake/)
* [ Silent Mode ](/docs/sdks/capacitor/silent-mode/)
* [ SIM ](/docs/sdks/capacitor/sim/)
* [ SMS Composer ](/docs/sdks/capacitor/sms-composer/)
* [ Speech Recognition ](/docs/sdks/capacitor/speech-recognition/)
* [ Speech Synthesis ](/docs/sdks/capacitor/speech-synthesis/)
* [ Share Target ](/docs/sdks/capacitor/share-target/)
* [ Square Mobile Payments ](/docs/sdks/capacitor/square-mobile-payments/)
* [ SQLite ](/docs/sdks/capacitor/sqlite/)
* [ Superwall ](/docs/sdks/capacitor/superwall/)
* [ System WebView ](/docs/sdks/capacitor/system-webview/)
* [ Tauri ](/docs/sdks/capacitor/tauri/)
* [ Text Interaction ](/docs/sdks/capacitor/text-interaction/)
* [ Text Zoom ](/docs/sdks/capacitor/text-zoom/)
* [ Thermal State ](/docs/sdks/capacitor/thermal-state/)
* [ Toast ](/docs/sdks/capacitor/toast/)
* [ Torch ](/docs/sdks/capacitor/torch/)
* [ Vault ](/docs/sdks/capacitor/vault/)
* [ Volume ](/docs/sdks/capacitor/volume/)
* [ Wallet ](/docs/sdks/capacitor/wallet/)
* [ Wifi ](/docs/sdks/capacitor/wifi/)
* [ YouTube Player ](/docs/sdks/capacitor/youtube-player/)
* [ Zip ](/docs/sdks/capacitor/zip/)
* [ Cordova ](/docs/sdks/cordova/)
* [ Cloud ](/docs/cloud/)
* [ Integrations ](/docs/cloud/live-updates/integrations/)
* Concepts
* Reference
* [ Troubleshooting ](/docs/cloud/live-updates/troubleshooting/)
* [ FAQ ](/docs/cloud/live-updates/faq/)
* [ Native Builds ](/docs/cloud/native-builds/)
* [ Set Up Environments ](/docs/cloud/native-builds/environments/)
* [ Overwrite Native Configurations ](/docs/cloud/native-builds/native-configurations/)
* [ Auto-Increment Build Numbers ](/docs/cloud/native-builds/auto-incrementing-build-numbers/)
* [ Configure the Web Build Script ](/docs/cloud/native-builds/web-build-script/)
* [ Build from a Monorepo ](/docs/cloud/native-builds/monorepo/)
* [ Use pnpm, Yarn, or bun ](/docs/cloud/native-builds/package-managers/)
* [ Install Private npm Packages ](/docs/cloud/native-builds/npm-private-registry/)
* [ Override the Java Version ](/docs/cloud/native-builds/override-java-version/)
* [ Custom iOS Provisioning Profiles ](/docs/cloud/native-builds/custom-ios-provisioning-profiles/)
* [ Build without Git ](/docs/cloud/native-builds/build-without-git/)
* [ Access Git Behind a Firewall ](/docs/cloud/native-builds/firewall-access/)
* [ Integrations ](/docs/cloud/native-builds/integrations/)
* Reference
* [ Troubleshooting ](/docs/cloud/native-builds/troubleshooting/)
* [ FAQ ](/docs/cloud/native-builds/faq/)
* [ App Store Publishing ](/docs/cloud/app-store-publishing/)
* [ Submit a Build ](/docs/cloud/app-store-publishing/submit-a-build/)
* [ Submit Automatically After a Build ](/docs/cloud/app-store-publishing/submit-automatically/)
* [ Troubleshooting ](/docs/cloud/app-store-publishing/troubleshooting/)
* [ FAQ ](/docs/cloud/app-store-publishing/faq/)
* [ Automations ](/docs/cloud/automations/)
* [ Reference ](/docs/cloud/automations/reference/)
* [ Troubleshooting ](/docs/cloud/automations/troubleshooting/)
* [ FAQ ](/docs/cloud/automations/faq/)
* [ Assist ](/docs/cloud/assist/)
* [ CLI ](/docs/cloud/cli/)
* APIs and SDKs
* [ Webhooks ](/docs/cloud/webhooks/)
* [ Integrations ](/docs/cloud/integrations/)
* Account
* [ Organization ](/docs/cloud/organizations/)
* [ Two-Factor Enforcement ](/docs/cloud/organizations/two-factor-authentication/)
* [ Audit Logs ](/docs/cloud/organizations/audit-logs/)
* [ Billing ](/docs/cloud/organizations/billing/)
* [ License Keys ](/docs/cloud/license-keys/)
* [ AI ](/docs/ai/)
* [ Insiders ](/docs/insiders/)
* [ Billing & Plans ](/docs/insiders/billing-and-plans/)
* [ FAQ ](/docs/insiders/faq/)
* [ License ](https://capawesome.io/legal/eula/)
* [ Support ](/docs/support/)
* [ Contributing ](/docs/contributing/)
* Contributing code
* [ Code of Conduct ](/docs/contributing/code-of-conduct/)
* [ Questions ](https://docs.github.com/en/discussions/collaborating-with-your-community-using-discussions/participating-in-a-discussion#creating-a-discussion)
* [ Blog ](/blog/)
* Categories

* [ Configuration ](#configuration)
* [ Usage ](#usage)
* [ API ](#api)
* [ Enums ](#enums)
* [ FAQ ](#faq)
* [ Related Plugins ](#related-plugins)
* [ Newsletter ](#newsletter)
* [ Changelog ](#changelog)
* [ Breaking Changes ](#breaking-changes)
* [ License ](#license)

# Capacitor Media Session Plugin[¶](#capacitor-media-session-plugin "Permanent link")

Capacitor plugin to interact with media controllers, volume keys and media buttons.

[ ![Deliver Live Updates to your Capacitor app with Capawesome Cloud](../../../assets/external/cloud.capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.69628c3f.png) ](https://cloud.capawesome.io/) 

## Features[¶](#features "Permanent link")

The Capacitor Media Session plugin is one of the most complete media playback integration solutions for Capacitor apps. 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.
* 🎨 **Customizable Icon**: Configure the notification icon on Android to match your app's branding.
* ▶️ **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](https://capawesome.io/docs/sdks/capacitor/audio-player/) plugin.
* 📦 **CocoaPods & SPM**: Supports CocoaPods and 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](https://github.com/capawesome-team/capacitor-plugins/issues) and we'll take a look!

## Use Cases[¶](#use-cases "Permanent link")

The Media Session plugin is typically used in apps that play media and want to integrate with the operating system's media controls, for example:

* **Music streaming apps**: Display the current track's title, artist, album, and artwork on the lock screen and respond to play, pause, and track change actions.
* **Podcast and audiobook players**: Let users seek forward and backward with configurable seek offsets and display the current playback position and duration.
* **Video call apps**: Handle the microphone toggle, camera toggle, and hang up actions on the Web.
* **Presentation apps**: Respond to the previous and next slide actions on the Web.

## Compatibility[¶](#compatibility "Permanent link")

| Plugin Version | Capacitor Version | Status         |
| -------------- | ----------------- | -------------- |
| 8.x.x          | \>=8.x.x          | Active support |
| 0.1.x          | 7.x.x             | Deprecated     |

## Demo[¶](#demo "Permanent link")

| Android                                                                                            | iOS                                                                                        | Web                                                                                        |
| -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
| ![Android Demo](https://capawesome.io/docs/assets/images/gifs/capacitor-media-session-android.gif) | ![iOS Demo](https://capawesome.io/docs/assets/images/gifs/capacitor-media-session-ios.gif) | ![Web Demo](https://capawesome.io/docs/assets/images/gifs/capacitor-media-session-web.gif) |

## Installation[¶](#installation "Permanent link")

This plugin is only available to [Capawesome Insiders](https://capawesome.io/insiders/). First, make sure you have the Capawesome npm registry set up. You can do this by running the following commands:

`[](#%5F%5Fcodelineno-0-1)npm config set @capawesome-team:registry https://npm.registry.capawesome.io
[](#%5F%5Fcodelineno-0-2)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](https://capawesome.io/insiders/).

Next, you can use our **AI-Assisted Setup** to install the plugin. Add the [Capawesome Skills](https://github.com/capawesome-team/skills) to your AI tool using the following command:

`[](#%5F%5Fcodelineno-1-1)npx skills add capawesome-team/skills --skill capacitor-plugins
`

Then use the following prompt:

`` [](#%5F%5Fcodelineno-2-1)Use the `capacitor-plugins` skill from `capawesome-team/skills` to install the `@capawesome-team/capacitor-media-session` plugin in my project.
 ``

If you prefer **Manual Setup**, install the plugin by running the following commands and follow the platform-specific instructions below:

`[](#%5F%5Fcodelineno-3-1)npm install @capawesome-team/capacitor-media-session
[](#%5F%5Fcodelineno-3-2)npx cap sync
`

### Android[¶](#android "Permanent link")

#### Variables[¶](#variables "Permanent link")

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 of `androidx.media:media` (default: `1.7.1`)

## Configuration[¶](#configuration "Permanent link")

These configuration options are available:

| Prop          | Type   | Description                                                                                                                                                                                                                                             | Default           | Since |
| ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | ----- |
| **smallIcon** | string | The name of the drawable resource to use as the small icon in the media notification. Only available on Android. The resource name should not include the R.drawable. prefix or file extension. If the resource is not found, the default icon is used. | "ic\_media\_play" | 8.1.0 |

### Examples[¶](#examples "Permanent link")

In `capacitor.config.ts`:

`[](#%5F%5Fcodelineno-4-1)import type { CapacitorConfig } from '@capacitor/cli';
[](#%5F%5Fcodelineno-4-2)
[](#%5F%5Fcodelineno-4-3)const config: CapacitorConfig = {
[](#%5F%5Fcodelineno-4-4)  plugins: {
[](#%5F%5Fcodelineno-4-5)    MediaSession: {
[](#%5F%5Fcodelineno-4-6)      smallIcon: 'ic_notification',
[](#%5F%5Fcodelineno-4-7)    },
[](#%5F%5Fcodelineno-4-8)  },
[](#%5F%5Fcodelineno-4-9)};
[](#%5F%5Fcodelineno-4-10)
[](#%5F%5Fcodelineno-4-11)export default config;
`

In `capacitor.config.json`:

`[](#%5F%5Fcodelineno-5-1){
[](#%5F%5Fcodelineno-5-2)  "plugins": {
[](#%5F%5Fcodelineno-5-3)    "MediaSession": {
[](#%5F%5Fcodelineno-5-4)      "smallIcon": "ic_notification"
[](#%5F%5Fcodelineno-5-5)    }
[](#%5F%5Fcodelineno-5-6)  }
[](#%5F%5Fcodelineno-5-7)}
`

### Android Custom Icon Setup[¶](#android-custom-icon-setup "Permanent link")

To use a custom notification icon on Android:

1. Add your icon to `android/app/src/main/res/drawable/` (e.g., `ic_notification.png`)
2. Icon should be single-color white with transparent background for best display
3. Can use density-specific folders (`drawable-mdpi`, `drawable-hdpi`, etc.)
4. Configure the plugin in `capacitor.config.ts`:  
`[](#%5F%5Fcodelineno-6-1)const config: CapacitorConfig = {  
[](#%5F%5Fcodelineno-6-2)  plugins: {  
[](#%5F%5Fcodelineno-6-3)    MediaSession: {  
[](#%5F%5Fcodelineno-6-4)      smallIcon: 'ic_notification',  // Matches ic_notification.png  
[](#%5F%5Fcodelineno-6-5)    },  
[](#%5F%5Fcodelineno-6-6)  },  
[](#%5F%5Fcodelineno-6-7)};  
`
5. Run: `npx cap sync`

## Usage[¶](#usage "Permanent link")

The following examples show how to display track metadata, register handlers for media actions, update the playback and position state, listen for media session actions, and unregister handlers and remove listeners, using the [Audio Player](https://capawesome.io/docs/sdks/capacitor/audio-player/) plugin for the actual audio playback.

### Display metadata about the current track[¶](#display-metadata-about-the-current-track "Permanent link")

Set the title, artist, album, and artwork that the operating system displays on the lock screen and in notifications. Note that the `artwork` option is only available on iOS and Web:

`[](#%5F%5Fcodelineno-7-1)import { MediaSession } from '@capawesome-team/capacitor-media-session';
[](#%5F%5Fcodelineno-7-2)
[](#%5F%5Fcodelineno-7-3)const setMetadata = async () => {
[](#%5F%5Fcodelineno-7-4)  await MediaSession.setMetadata({
[](#%5F%5Fcodelineno-7-5)    title: 'Test Song',
[](#%5F%5Fcodelineno-7-6)    artist: 'My Awesome Artist',
[](#%5F%5Fcodelineno-7-7)    album: 'My Awesome Album',
[](#%5F%5Fcodelineno-7-8)    artwork: [
[](#%5F%5Fcodelineno-7-9)      {
[](#%5F%5Fcodelineno-7-10)        src: 'https://example.com/cover-96x96.png',
[](#%5F%5Fcodelineno-7-11)        sizes: '96x96',
[](#%5F%5Fcodelineno-7-12)        type: 'image/png',
[](#%5F%5Fcodelineno-7-13)      },
[](#%5F%5Fcodelineno-7-14)      {
[](#%5F%5Fcodelineno-7-15)        src: 'https://example.com/cover-512x512.png',
[](#%5F%5Fcodelineno-7-16)        sizes: '512x512',
[](#%5F%5Fcodelineno-7-17)        type: 'image/png',
[](#%5F%5Fcodelineno-7-18)      },
[](#%5F%5Fcodelineno-7-19)    ],
[](#%5F%5Fcodelineno-7-20)  });
[](#%5F%5Fcodelineno-7-21)};
`

### Register handlers for media actions[¶](#register-handlers-for-media-actions "Permanent link")

Register a handler for each media session action you want to support. The media session only responds to an action if a handler is registered for it:

`[](#%5F%5Fcodelineno-8-1)import { MediaSession, MediaSessionAction } from '@capawesome-team/capacitor-media-session';
[](#%5F%5Fcodelineno-8-2)
[](#%5F%5Fcodelineno-8-3)const registerActions = async () => {
[](#%5F%5Fcodelineno-8-4)  await MediaSession.registerActionHandler({
[](#%5F%5Fcodelineno-8-5)    action: MediaSessionAction.Play
[](#%5F%5Fcodelineno-8-6)  });
[](#%5F%5Fcodelineno-8-7)  await MediaSession.registerActionHandler({
[](#%5F%5Fcodelineno-8-8)    action: MediaSessionAction.Pause
[](#%5F%5Fcodelineno-8-9)  });
[](#%5F%5Fcodelineno-8-10)  await MediaSession.registerActionHandler({
[](#%5F%5Fcodelineno-8-11)    action: MediaSessionAction.SeekBackward
[](#%5F%5Fcodelineno-8-12)  });
[](#%5F%5Fcodelineno-8-13)  await MediaSession.registerActionHandler({
[](#%5F%5Fcodelineno-8-14)    action: MediaSessionAction.SeekForward
[](#%5F%5Fcodelineno-8-15)  });
[](#%5F%5Fcodelineno-8-16)  await MediaSession.registerActionHandler({
[](#%5F%5Fcodelineno-8-17)    action: MediaSessionAction.SeekTo
[](#%5F%5Fcodelineno-8-18)  });
[](#%5F%5Fcodelineno-8-19)  await MediaSession.registerActionHandler({
[](#%5F%5Fcodelineno-8-20)    action: MediaSessionAction.Stop
[](#%5F%5Fcodelineno-8-21)  });
[](#%5F%5Fcodelineno-8-22)};
`

### Update the playback state[¶](#update-the-playback-state "Permanent link")

Tell the operating system whether media is currently playing, paused, or stopped so that the media controls reflect the correct state:

`[](#%5F%5Fcodelineno-9-1)import { MediaSession, MediaSessionPlaybackState } from '@capawesome-team/capacitor-media-session';
[](#%5F%5Fcodelineno-9-2)
[](#%5F%5Fcodelineno-9-3)const setPlaybackState = async () => {
[](#%5F%5Fcodelineno-9-4)  await MediaSession.setPlaybackState({
[](#%5F%5Fcodelineno-9-5)    playbackState: MediaSessionPlaybackState.Playing,
[](#%5F%5Fcodelineno-9-6)  });
[](#%5F%5Fcodelineno-9-7)};
`

### Update the position state[¶](#update-the-position-state "Permanent link")

Report the duration, playback rate, and current position of the media in seconds so that the operating system can display a progress bar:

`[](#%5F%5Fcodelineno-10-1)import { MediaSession } from '@capawesome-team/capacitor-media-session';
[](#%5F%5Fcodelineno-10-2)
[](#%5F%5Fcodelineno-10-3)const setPositionState = async () => {
[](#%5F%5Fcodelineno-10-4)  await MediaSession.setPositionState({
[](#%5F%5Fcodelineno-10-5)    duration: 180,
[](#%5F%5Fcodelineno-10-6)    playbackRate: 1.0,
[](#%5F%5Fcodelineno-10-7)    position: 30,
[](#%5F%5Fcodelineno-10-8)  });
[](#%5F%5Fcodelineno-10-9)};
`

### Listen for media session actions[¶](#listen-for-media-session-actions "Permanent link")

Add an `action` event listener to react to the registered actions, for example when the user presses a hardware media key or a button on the lock screen:

`[](#%5F%5Fcodelineno-11-1)import { MediaSession, MediaSessionAction, MediaSessionPlaybackState } from '@capawesome-team/capacitor-media-session';
[](#%5F%5Fcodelineno-11-2)import { AudioPlayer } from '@capawesome-team/capacitor-audio-player';
[](#%5F%5Fcodelineno-11-3)
[](#%5F%5Fcodelineno-11-4)const addActionListener = () => {
[](#%5F%5Fcodelineno-11-5)  MediaSession.addListener('action', async (event) => {
[](#%5F%5Fcodelineno-11-6)    switch (event.action) {
[](#%5F%5Fcodelineno-11-7)      case MediaSessionAction.Play:
[](#%5F%5Fcodelineno-11-8)        await AudioPlayer.resume();
[](#%5F%5Fcodelineno-11-9)        await MediaSession.setPlaybackState({
[](#%5F%5Fcodelineno-11-10)          playbackState: MediaSessionPlaybackState.Playing,
[](#%5F%5Fcodelineno-11-11)        });
[](#%5F%5Fcodelineno-11-12)        break;
[](#%5F%5Fcodelineno-11-13)      case MediaSessionAction.Pause:
[](#%5F%5Fcodelineno-11-14)        await AudioPlayer.pause();
[](#%5F%5Fcodelineno-11-15)        await MediaSession.setPlaybackState({
[](#%5F%5Fcodelineno-11-16)          playbackState: MediaSessionPlaybackState.Paused,
[](#%5F%5Fcodelineno-11-17)        });
[](#%5F%5Fcodelineno-11-18)        break;
[](#%5F%5Fcodelineno-11-19)      case MediaSessionAction.SeekBackward:
[](#%5F%5Fcodelineno-11-20)        const { position: currentPos } = await AudioPlayer.getCurrentPosition();
[](#%5F%5Fcodelineno-11-21)        const offsetMs = event.seekOffset ? event.seekOffset * 1000 : 10000;
[](#%5F%5Fcodelineno-11-22)        await AudioPlayer.seekTo({
[](#%5F%5Fcodelineno-11-23)          position: Math.max(0, currentPos - offsetMs)
[](#%5F%5Fcodelineno-11-24)        });
[](#%5F%5Fcodelineno-11-25)        break;
[](#%5F%5Fcodelineno-11-26)      case MediaSessionAction.SeekForward:
[](#%5F%5Fcodelineno-11-27)        const { position: pos } = await AudioPlayer.getCurrentPosition();
[](#%5F%5Fcodelineno-11-28)        const { duration } = await AudioPlayer.getDuration();
[](#%5F%5Fcodelineno-11-29)        const offset = event.seekOffset ? event.seekOffset * 1000 : 10000;
[](#%5F%5Fcodelineno-11-30)        await AudioPlayer.seekTo({
[](#%5F%5Fcodelineno-11-31)          position: Math.min(duration, pos + offset)
[](#%5F%5Fcodelineno-11-32)        });
[](#%5F%5Fcodelineno-11-33)        break;
[](#%5F%5Fcodelineno-11-34)      case MediaSessionAction.SeekTo:
[](#%5F%5Fcodelineno-11-35)        if (event.seekTime !== undefined) {
[](#%5F%5Fcodelineno-11-36)          await AudioPlayer.seekTo({
[](#%5F%5Fcodelineno-11-37)            position: event.seekTime * 1000
[](#%5F%5Fcodelineno-11-38)          });
[](#%5F%5Fcodelineno-11-39)        }
[](#%5F%5Fcodelineno-11-40)        break;
[](#%5F%5Fcodelineno-11-41)      case MediaSessionAction.Stop:
[](#%5F%5Fcodelineno-11-42)        await AudioPlayer.stop();
[](#%5F%5Fcodelineno-11-43)        await MediaSession.setPlaybackState({
[](#%5F%5Fcodelineno-11-44)          playbackState: MediaSessionPlaybackState.None,
[](#%5F%5Fcodelineno-11-45)        });
[](#%5F%5Fcodelineno-11-46)        break;
[](#%5F%5Fcodelineno-11-47)    }
[](#%5F%5Fcodelineno-11-48)  });
[](#%5F%5Fcodelineno-11-49)};
`

### Unregister action handlers and remove listeners[¶](#unregister-action-handlers-and-remove-listeners "Permanent link")

Make sure to unregister action handlers when they are no longer needed and remove your event listeners:

`[](#%5F%5Fcodelineno-12-1)import { MediaSession, MediaSessionAction } from '@capawesome-team/capacitor-media-session';
[](#%5F%5Fcodelineno-12-2)
[](#%5F%5Fcodelineno-12-3)const removeActionListener = async () => {
[](#%5F%5Fcodelineno-12-4)  await MediaSession.unregisterActionHandler({
[](#%5F%5Fcodelineno-12-5)    action: MediaSessionAction.Play
[](#%5F%5Fcodelineno-12-6)  });
[](#%5F%5Fcodelineno-12-7)  await MediaSession.unregisterActionHandler({
[](#%5F%5Fcodelineno-12-8)    action: MediaSessionAction.Pause
[](#%5F%5Fcodelineno-12-9)  });
[](#%5F%5Fcodelineno-12-10)  await MediaSession.removeAllListeners();
[](#%5F%5Fcodelineno-12-11)};
`

## API[¶](#api "Permanent link")

* [registerActionHandler(...)](#registeractionhandler)
* [setCameraActive(...)](#setcameraactive)
* [setMetadata(...)](#setmetadata)
* [setMicrophoneActive(...)](#setmicrophoneactive)
* [setPlaybackState(...)](#setplaybackstate)
* [setPositionState(...)](#setpositionstate)
* [setSeekOffset(...)](#setseekoffset)
* [unregisterActionHandler(...)](#unregisteractionhandler)
* [addListener('action', ...)](#addlisteneraction-)
* [removeAllListeners()](#removealllisteners)
* [Interfaces](#interfaces)
* [Enums](#enums)

### registerActionHandler(...)[¶](#registeractionhandler "Permanent link")

`[](#%5F%5Fcodelineno-13-1)registerActionHandler(options: RegisterActionHandlerOptions) => Promise<void>
`

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](#registeractionhandleroptions) |

**Since:** 0.0.1

---

### setCameraActive(...)[¶](#setcameraactive "Permanent link")

`[](#%5F%5Fcodelineno-14-1)setCameraActive(options: SetCameraActiveOptions) => Promise<void>
`

Set the camera active state.

Only available on Web.

| Param       | Type                                              |
| ----------- | ------------------------------------------------- |
| **options** | [SetCameraActiveOptions](#setcameraactiveoptions) |

**Since:** 0.0.1

---

### setMetadata(...)[¶](#setmetadata "Permanent link")

`[](#%5F%5Fcodelineno-15-1)setMetadata(options: SetMetadataOptions) => Promise<void>
`

Set the metadata for the media session.

| Param       | Type                                      |
| ----------- | ----------------------------------------- |
| **options** | [SetMetadataOptions](#setmetadataoptions) |

**Since:** 0.0.1

---

### setMicrophoneActive(...)[¶](#setmicrophoneactive "Permanent link")

`[](#%5F%5Fcodelineno-16-1)setMicrophoneActive(options: SetMicrophoneActive) => Promise<void>
`

Set the microphone active state.

Only available on Web.

| Param       | Type                                        |
| ----------- | ------------------------------------------- |
| **options** | [SetMicrophoneActive](#setmicrophoneactive) |

**Since:** 0.0.1

---

### setPlaybackState(...)[¶](#setplaybackstate "Permanent link")

`[](#%5F%5Fcodelineno-17-1)setPlaybackState(options: SetPlaybackStateOptions) => Promise<void>
`

Set the playback state.

| Param       | Type                                                |
| ----------- | --------------------------------------------------- |
| **options** | [SetPlaybackStateOptions](#setplaybackstateoptions) |

**Since:** 0.0.1

---

### setPositionState(...)[¶](#setpositionstate "Permanent link")

`[](#%5F%5Fcodelineno-18-1)setPositionState(options: SetPositionStateOptions) => Promise<void>
`

Set the position state.

| Param       | Type                                                |
| ----------- | --------------------------------------------------- |
| **options** | [SetPositionStateOptions](#setpositionstateoptions) |

**Since:** 0.0.1

---

### setSeekOffset(...)[¶](#setseekoffset "Permanent link")

`[](#%5F%5Fcodelineno-19-1)setSeekOffset(options: SetSeekOffsetOptions) => Promise<void>
`

Set the seek offset for the `SeekForward` and `SeekBackward` actions.

The offset controls both the value emitted in the `action` event's `seekOffset` property and the offset displayed by the OS (e.g., the number badge on the iOS lock-screen skip button).

Can be called at any time; the new offset is applied immediately.

Only available on Android and iOS.

| Param       | Type                                          |
| ----------- | --------------------------------------------- |
| **options** | [SetSeekOffsetOptions](#setseekoffsetoptions) |

**Since:** 8.3.0

---

### unregisterActionHandler(...)[¶](#unregisteractionhandler "Permanent link")

`[](#%5F%5Fcodelineno-20-1)unregisterActionHandler(options: UnregisterActionHandlerOptions) => Promise<void>
`

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](#unregisteractionhandleroptions) |

**Since:** 0.0.1

---

### addListener('action', ...)[¶](#addlisteneraction "Permanent link")

`[](#%5F%5Fcodelineno-21-1)addListener(eventName: 'action', listenerFunc: (event: ActionEvent) => void) => Promise<PluginListenerHandle>
`

| Param            | Type                                         |
| ---------------- | -------------------------------------------- |
| **eventName**    | 'action'                                     |
| **listenerFunc** | (event: [ActionEvent](#actionevent)) => void |

**Returns:** `Promise<[PluginListenerHandle](#pluginlistenerhandle)>`

**Since:** 0.0.1

---

### removeAllListeners()[¶](#removealllisteners "Permanent link")

`[](#%5F%5Fcodelineno-22-1)removeAllListeners() => Promise<void>
`

Remove all listeners for this plugin.

**Since:** 0.0.1

---

### Interfaces[¶](#interfaces "Permanent link")

#### RegisterActionHandlerOptions[¶](#registeractionhandleroptions "Permanent link")

| Prop       | Type                                      | Description           | Since |
| ---------- | ----------------------------------------- | --------------------- | ----- |
| **action** | [MediaSessionAction](#mediasessionaction) | The action to handle. | 0.0.1 |

#### SetCameraActiveOptions[¶](#setcameraactiveoptions "Permanent link")

| Prop       | Type    | Description                          | Since |
| ---------- | ------- | ------------------------------------ | ----- |
| **active** | boolean | Whether or not the camera is active. | 0.0.1 |

#### SetMetadataOptions[¶](#setmetadataoptions "Permanent link")

| 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[¶](#mediametadataartwork "Permanent link")

| 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[¶](#setmicrophoneactive%5F1 "Permanent link")

| Prop       | Type    | Description                              | Since |
| ---------- | ------- | ---------------------------------------- | ----- |
| **active** | boolean | Whether or not the microphone is active. | 0.0.1 |

#### SetPlaybackStateOptions[¶](#setplaybackstateoptions "Permanent link")

| Prop              | Type                                                    | Description                | Since |
| ----------------- | ------------------------------------------------------- | -------------------------- | ----- |
| **playbackState** | [MediaSessionPlaybackState](#mediasessionplaybackstate) | The playback state to set. | 0.0.1 |

#### SetPositionStateOptions[¶](#setpositionstateoptions "Permanent link")

| 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 |

#### SetSeekOffsetOptions[¶](#setseekoffsetoptions "Permanent link")

| Prop                   | Type   | Description                                                                                                            | Default | Since |
| ---------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------- | ------- | ----- |
| **seekBackwardOffset** | number | The offset in seconds for the SeekBackward action. Must be greater than 0. If not provided, the current value is kept. | 10      | 8.3.0 |
| **seekForwardOffset**  | number | The offset in seconds for the SeekForward action. Must be greater than 0. If not provided, the current value is kept.  | 10      | 8.3.0 |

#### UnregisterActionHandlerOptions[¶](#unregisteractionhandleroptions "Permanent link")

| Prop       | Type                                      | Description               | Since |
| ---------- | ----------------------------------------- | ------------------------- | ----- |
| **action** | [MediaSessionAction](#mediasessionaction) | The action to unregister. | 0.0.1 |

#### PluginListenerHandle[¶](#pluginlistenerhandle "Permanent link")

| Prop       | Type                |
| ---------- | ------------------- |
| **remove** | () => Promise<void> |

#### ActionEvent[¶](#actionevent "Permanent link")

| Prop           | Type                                      | Description                                | Since |
| -------------- | ----------------------------------------- | ------------------------------------------ | ----- |
| **action**     | [MediaSessionAction](#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[¶](#enums "Permanent link")

#### MediaSessionAction[¶](#mediasessionaction "Permanent link")

| 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[¶](#mediasessionplaybackstate "Permanent link")

| Members     | Value     | Since |
| ----------- | --------- | ----- |
| **None**    | 'NONE'    | 0.0.1 |
| **Paused**  | 'PAUSED'  | 0.0.1 |
| **Playing** | 'PLAYING' | 0.0.1 |

## FAQ[¶](#faq "Permanent link")

### How do I show playback controls on the lock screen?[¶](#how-do-i-show-playback-controls-on-the-lock-screen "Permanent link")

Set the metadata for the current track using `setMetadata`, register handlers for the actions you want to support using `registerActionHandler`, and update the playback state using `setPlaybackState`. The plugin uses the MediaSession API on Android and MPNowPlayingInfoCenter on iOS, so the operating system takes care of displaying the controls on the lock screen and in notifications. See the [usage examples](#usage) above for details.

### Why is the artwork not displayed on Android?[¶](#why-is-the-artwork-not-displayed-on-android "Permanent link")

The `artwork` option of the `setMetadata` method is only available on iOS and Web. On Android, you can configure the notification icon instead using the `smallIcon` configuration option.

### Can I customize the notification icon on Android?[¶](#can-i-customize-the-notification-icon-on-android "Permanent link")

Yes, use the `smallIcon` configuration option to set the name of a drawable resource from your app's `res/drawable` directory. The icon should be single-color white with a transparent background for the best display. If the resource is not found, the default icon is used. See the [Configuration](#configuration) section for details.

### Can I use this plugin together with the Audio Player plugin?[¶](#can-i-use-this-plugin-together-with-the-audio-player-plugin "Permanent link")

Yes, the plugin is compatible with the [Audio Player](https://capawesome.io/docs/sdks/capacitor/audio-player/) plugin. A common setup is to play audio with the Audio Player plugin and use the Media Session plugin to display metadata and respond to media actions, as shown in the [usage examples](#usage) above.

### Why does the media session not respond to certain actions?[¶](#why-does-the-media-session-not-respond-to-certain-actions "Permanent link")

The media session only responds to an action if a handler was registered for it using `registerActionHandler`. Also note that some actions such as `SkipAd`, `ToggleMicrophone`, `ToggleCamera`, `ToggleScreenShare`, `HangUp`, `PreviousSlide`, `NextSlide`, `EnterPictureInPicture` and `VoiceActivity` are only available on the Web.

### Can I use this plugin with Ionic, React, Vue or Angular?[¶](#can-i-use-this-plugin-with-ionic-react-vue-or-angular "Permanent link")

Yes, the plugin is framework-agnostic. It works in any Capacitor app regardless of the web framework, including Ionic with Angular, React, or Vue, as well as plain JavaScript projects.

## Related Plugins[¶](#related-plugins "Permanent link")

* [Audio Player](https://capawesome.io/docs/sdks/capacitor/audio-player/): Play audio with background support.
* [Audio Session](https://capawesome.io/docs/sdks/capacitor/audio-session/): Configure and observe the iOS audio session.
* [Volume](https://capawesome.io/docs/sdks/capacitor/volume/): Control the volume and observe hardware volume button presses.
* [YouTube Player](https://capawesome.io/docs/sdks/capacitor/youtube-player/): Embed and control YouTube players, with lock-screen media controls via this plugin.

## Newsletter[¶](#newsletter "Permanent link")

Stay up to date with the latest news and updates about the Capawesome, Capacitor, and Ionic ecosystem by subscribing to our [Capawesome Newsletter](https://cloud.capawesome.io/newsletter/).

## Changelog[¶](#changelog "Permanent link")

See [CHANGELOG.md](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/media-session/CHANGELOG.md).

## Breaking Changes[¶](#breaking-changes "Permanent link")

See [BREAKING.md](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/media-session/BREAKING.md).

## License[¶](#license "Permanent link")

See [LICENSE](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/media-session/LICENSE).

July 8, 2026 

Back to top

```json
{"@context": "https://schema.org", "@graph": [{"@type": "TechArticle", "@id": "https://capawesome.io/docs/sdks/capacitor/media-session/#article", "headline": "Capacitor Media Session Plugin for Android, iOS & Web", "name": "Capacitor Media Session Plugin for Android, iOS & Web", "description": "Capacitor plugin to interact with media controls and metadata for a seamless media playback experience across platforms.", "inLanguage": "en", "url": "https://capawesome.io/docs/sdks/capacitor/media-session/", "mainEntityOfPage": "https://capawesome.io/docs/sdks/capacitor/media-session/", "author": {"@type": "Organization", "name": "Capawesome", "url": "https://capawesome.io", "logo": {"@type": "ImageObject", "url": "https://capawesome.io/assets/images/logo.svg"}}, "publisher": {"@type": "Organization", "name": "Capawesome", "url": "https://capawesome.io", "logo": {"@type": "ImageObject", "url": "https://capawesome.io/assets/images/logo.svg"}}, "about": {"@id": "https://capawesome.io/docs/sdks/capacitor/media-session/#software"}}, {"@type": "SoftwareSourceCode", "@id": "https://capawesome.io/docs/sdks/capacitor/media-session/#software", "name": "Capacitor Media Session Plugin for Android, iOS & Web", "description": "Capacitor plugin to interact with media controls and metadata for a seamless media playback experience across platforms.", "url": "https://capawesome.io/docs/sdks/capacitor/media-session/", "programmingLanguage": "TypeScript", "runtimePlatform": "Capacitor", "codeRepository": "https://github.com/capawesome-team", "author": {"@type": "Organization", "name": "Capawesome", "url": "https://capawesome.io", "logo": {"@type": "ImageObject", "url": "https://capawesome.io/assets/images/logo.svg"}}, "publisher": {"@type": "Organization", "name": "Capawesome", "url": "https://capawesome.io", "logo": {"@type": "ImageObject", "url": "https://capawesome.io/assets/images/logo.svg"}}}]}
{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "How do I show playback controls on the lock screen?", "acceptedAnswer": {"@type": "Answer", "text": "Set the metadata for the current track using setMetadata, register handlers for the actions you want to support using registerActionHandler, and update the playback state using setPlaybackState. The plugin uses the MediaSession API on Android and MPNowPlayingInfoCenter on iOS, so the operating system takes care of displaying the controls on the lock screen and in notifications. See the usage examples above for details."}}, {"@type": "Question", "name": "Why is the artwork not displayed on Android?", "acceptedAnswer": {"@type": "Answer", "text": "The artwork option of the setMetadata method is only available on iOS and Web. On Android, you can configure the notification icon instead using the smallIcon configuration option."}}, {"@type": "Question", "name": "Can I customize the notification icon on Android?", "acceptedAnswer": {"@type": "Answer", "text": "Yes, use the smallIcon configuration option to set the name of a drawable resource from your app's res/drawable directory. The icon should be single-color white with a transparent background for the best display. If the resource is not found, the default icon is used. See the Configuration section for details."}}, {"@type": "Question", "name": "Can I use this plugin together with the Audio Player plugin?", "acceptedAnswer": {"@type": "Answer", "text": "Yes, the plugin is compatible with the Audio Player plugin. A common setup is to play audio with the Audio Player plugin and use the Media Session plugin to display metadata and respond to media actions, as shown in the usage examples above."}}, {"@type": "Question", "name": "Why does the media session not respond to certain actions?", "acceptedAnswer": {"@type": "Answer", "text": "The media session only responds to an action if a handler was registered for it using registerActionHandler. Also note that some actions such as SkipAd, ToggleMicrophone, ToggleCamera, ToggleScreenShare, HangUp, PreviousSlide, NextSlide, EnterPictureInPicture and VoiceActivity are only available on the Web."}}, {"@type": "Question", "name": "Can I use this plugin with Ionic, React, Vue or Angular?", "acceptedAnswer": {"@type": "Answer", "text": "Yes, the plugin is framework-agnostic. It works in any Capacitor app regardless of the web framework, including Ionic with Angular, React, or Vue, as well as plain JavaScript projects."}}], "url": "https://capawesome.io/docs/sdks/capacitor/media-session/"}
```
