Technical

Integrating the Media Session API in Android TWAs

November 8, 2026 · 6 min read

When you convert a Progressive Web App into an Android app using a Trusted Web Activity, your application runs inside a native wrapper powered by the system browser engine. For applications that feature audio or video content, such as podcasts, music players, guided meditation services, or e-learning platforms, users expect a native media playback experience. This means playback should continue in the background, metadata should appear on the system lock screen, and physical hardware buttons or connected Bluetooth accessories should control the media stream.

By default, standard web playback lacks this integration. When the user closes the screen or switches to another application, the system may pause or terminate the browser context to save resources. To bridge this gap, developers must implement the Media Session API. This technical guide explains how to integrate the Media Session API within your PWA so that, once packaged via a Trusted Web Activity, it behaves like a native Android media player.

The Core Role of the Media Session API

The Media Session API provides a mechanism to customise media notifications and respond to system-level media events. It translates browser-based media state changes into Android system events managed by the native MediaSessionCompat framework. Without this API, Android treats your app as a generic web page playing audio, which leads to limited system control, lack of artwork on the notification tray, and an increased likelihood of the OS killing your background process during low-memory conditions.

By declaring a media session, you explicitly signal to the Android operating system that your app is performing active background work that is valuable to the user. This changes the application priority within the system task manager, reducing the chance of background termination.

Implementing Media Metadata

The first step in integrating the Media Session API is to provide the operating system with detailed metadata about the audio track currently playing. This metadata is rendered in the Android notification drawer, on the device lock screen, and on wearable devices such as smartwatches connected to the handset.

You must check if the media session interface is supported by the user-agent before attempting to write metadata. This ensures compatibility across different browser versions and web-to-app environments. The metadata object accepts a title, artist, album, and an array of artwork images of varying sizes.

Using a code structure to update this metadata is straightforward:

if ('mediaSession' in navigator) { navigator.mediaSession.metadata = new MediaMetadata({ title: 'Understanding Android Web Apps', artist: 'PWAtoApp Engineering', album: 'Developer Guides', artwork: [ { src: 'https://example.com/assets/icon-96.png', sizes: '96x96', type: 'image/png' }, { src: 'https://example.com/assets/icon-192.png', sizes: '192x192', type: 'image/png' }, { src: 'https://example.com/assets/icon-512.png', sizes: '512x512', type: 'image/png' } ] }); }

Always provide multiple sizes of your artwork. Android uses different resolutions depending on the display context. For example, a lock screen background requires a larger, higher-resolution image, whereas the notification tray uses a smaller thumbnail.

Handling System Playback Actions

Declaring metadata is only half of the implementation. You must also instruct the browser engine how to respond when a user interacts with native system controls, such as tapping the pause button on their lock screen or pressing a physical play/pause toggle on their headphones. This is achieved by setting action handlers.

Action handlers intercept system-level commands and map them to JavaScript functions that control your HTML5 audio or video element. If your application fails to declare these handlers, the buttons in the native Android notification drawer will remain greyed out or non-functional.

You should implement handlers for play, pause, seek, and track navigation:

if ('mediaSession' in navigator) { navigator.mediaSession.setActionHandler('play', () => { audioElement.play(); }); navigator.mediaSession.setActionHandler('pause', () => { audioElement.pause(); }); navigator.mediaSession.setActionHandler('seekto', (details) => { if (details.fastSeek && 'fastSeek' in audioElement) { audioElement.fastSeek(details.seekTime); } else { audioElement.currentTime = details.seekTime; } }); navigator.mediaSession.setActionHandler('previoustrack', () => { playPreviousTrack(); }); navigator.mediaSession.setActionHandler('nexttrack', () => { playNextTrack(); }); }

By handling these actions, you ensure that physical or virtual inputs are fed back directly into your web-based audio engine, creating a seamless feedback loop between Android and your web codebase.

Understanding Audio Focus and Interruptions

In the Android ecosystem, multiple applications might attempt to play audio at the same time. For instance, a user might be listening to a podcast in your app when a navigation notification speaks, or an incoming phone call occurs. Android manages these scenarios using a system called Audio Focus.

When your TWA uses the Media Session API combined with standard HTML5 audio elements, the underlying system browser handles standard audio focus negotiations automatically. When a phone call occurs, the browser intercepts the native focus loss, pausing your media element and triggering your configured pause action handler. Once the call finishes, focus is returned, and your play handler can resume playback if the user has configured the app to do so.

Native Integration Comparison

The following table outlines the behavioral differences between standard web audio, a raw TWA wrapper without configuration, and a TWA optimised with the Media Session API:

FeatureStandard PWARaw TWA WrapperOptimised TWA with Media Session
Background Audio LifecycleOften suspended when tab loses focusMay be killed by Android task managerProtected by native background priority
Lock Screen ControlsNone availableNone availableFull track info, artwork, and scrub seekbar
Notification Tray InterfaceNone or browser default notificationGeneric browser player notificationApp-branded media control interface
Hardware Button SupportIgnored by systemIgnored or controls global volume onlyControls track playback, skip, and pause
Audio Focus InterruptionsOverlaps with other audio or breaksCan result in sudden silence without pauseGraceful automatic pause and auto-resume

Server Configuration and Network Requirements

To guarantee that audio playback remains uninterrupted inside a Trusted Web Activity, your web server must be properly configured. The most common technical failure point is how your server delivers media assets.

Android's media framework relies on HTTP range requests to stream media efficiently and allow scrub seeking. If your server does not support the Range header or fails to respond with a 206 Partial Content status code, the media player inside the TWA may refuse to play the file, fail to seek, or break during background buffering. Ensure your CDN or host server is configured to handle byte-range requests correctly. Additionally, ensure your Service Worker is designed to bypass caching for large media assets, or uses a caching strategy that supports range request partitioning.

Ready to build for Android and iOS?

€49.99 once includes unlimited Android APK and AAB plus iOS IPA builds, all from one dashboard.

Build my app