Software
Applications
Audio Player

The native app's headless audio player

When playing audio in the web audio-player, the native app is actually playing the audio, while the web-view keeps on rendering the UI. In order to the web-views UI in sync with the native app's audio player, the native app sends frequent updates to the web-view about the current playing state.

In addition, when interacting with the lock-screen UI of the phone where the native-app is playing the audio, the native-app forwords these interactions to the web-view, so that the web-view can update its UI accordingly.

Events sent from the web-view to the native app

The web-view uses postMessage to send events to the native app. The function notifyApp is used to send the events.

Example:

notifyApp(AudioEvent.SETUP_TRACK, {
  item,
  autoPlay,
  initialTime,
  playbackRate,
  coverImage: item.document.meta.coverForNativeApp,
})

Events

Event nameDescription
audio:playThe user pressed the play button
audio:pauseThe user pressed the pause button
audio:seekThe user seeked to a new position in the audio
audio:stopThe user has closed the audio-player, the playback should be stopped
audio:fowardSkip ahead x seconds
audio:backwardSkip back x seconds
audio:playbackRateChange the playback rate
audio:setupTrackPrepare the audio player for playing the given track

Events received in the webview, sent from the native-app

In order to receive events from the native app, the react-hook useNativeAppEvent is used.

Example:

useNativeAppEvent<string>(
  AudioEvent.QUEUE_ADVANCE,
  async (itemId) => {
    const isHeadOfQueue =
      audioQueue && audioQueue.length > 0 && audioQueue[0].id === itemId
    const isActiveItem = activePlayerItem && activePlayerItem.id === itemId
    if (isHeadOfQueue || isActiveItem) {
      // HasOptedOutFromAutoPlay might be null, which should then result in 'true'
      await onQueueAdvance(isAutoPlayEnabled)
    }
  },
  [initialized, activePlayerItem, isAutoPlayEnabled],
)

Most of the communication received by the web-view is handled in the AudioPlayerController (opens in a new tab) component.

Events

Event nameDescription
audio:syncSent every frequently, contains the current playing state used to keep the web-view in sync with the native app
audio:queueAdvanceThe native app reports that the playback has finished and a next track should be sent if in the queue
audio:errorThe native app reports an error
audio:trackThe native app reports the current track
audio:minimizePlayerThe native app reports that the audio player should be minimized

Example message flow

References