Zum Hauptinhalt springen

Audio im Hintergrund in Capacitor abspielen

Hintergrundmusik in Capacitor: iOS-Hintergrundmodus, Android-Vordergrunddienst, Bildschirm-Steuerung, Wiedergabelisten und Unterbrechungen.

Artikelcredits

Martin Donadieu

Schreiber

Valeria

Reviewer

Jordan

Editor

Wie man Audio im Hintergrund in Capacitor abspielt

Um Hintergrundmusik in Capacitor abzuspielen, benötigen Sie zwei native Komponenten: die audio Hintergrundmodus auf iOS, und ein mediaPlayback foreground service on Android. Add lock screen controls through a media session, and your music, podcast or meditation app keeps playing when the user locks the phone or switches apps. This guide shows both setups on Capacitor 8, with @capgo/capacitor-native-audio für Systemsteuerungen. @capgo/capacitor-media-session Weshalb Audio im Hintergrund anhält

Warum hört die Audio in Hintergrund auf

Ein Capacitor-App ist eine native Hülle um einen WebView, daher folgt sie jeder Plattform’s Lebenszyklus-Regeln:

iOS Android
Was passiert im Hintergrund? Die App wird innerhalb von Sekunden ausgesetzt. Die Aktivität wird pausiert, die WebView-Timer werden gedrosselt, der Prozess kann beendet werden.
Was hält das Audio am Leben? UIBackgroundModes enthält audio, die Audio-Sitzungskategorie playback Ein Vordergrunddienst vom Typ mediaPlayback mit einer Benachrichtigung
Stummschalter playback Kategorie ignoriert es. ambient respektiert es Keine Entsprechung
Schaltflächen auf dem Bildschirm MPNowPlayingInfoCenter und MPRemoteCommandCenter MediaSession mit einer Medien-Style-Benachrichtigung
Speicherregel Musik muss den Benutzer erwarten, der sie hören möchte (Richtlinie 2.5.4) Diensttyp muss dem tatsächlichen Gebrauch entsprechen, wie er im Google Play Console deklariert ist.

Keine Plattform gibt Ihnen Hintergrundmusik standardmäßig, und das Fixieren nur einer Seite ist der häufigste Grund für 'funktioniert auf iPhone, hört auf Android' Fehlermeldungen.

Wählen Sie Ihren Wiedergabeansatz

Es gibt zwei gute Architekturen:

  1. Native Wiedergabe mit @capgo/capacitor-native-audio: Audio wird von AVFoundation auf iOS und Media3 ExoPlayer auf Android decodiert. Ideal für Musikplayer, Hörbücher, Meditation-Apps und alles, wo der WebView möglicherweise eingeschränkt ist. Es unterstützt lokale Dateien, remote URLs, HLS-Streams, Fades, Rate und Now Playing-Metadaten.
  2. HTML <audio> plus @capgo/capacitor-media-session: Halten Sie Ihren bestehenden Web-Player und lassen Sie das Plugin Metadaten und Steuerungen an das Betriebssystem weitergeben. Auf Android läuft es auch den Vordergrunddienst während der Sitzung läuft. Ideal, wenn Sie bereits einen Web-Player haben oder einen einzigen code Pfad für Web und Native benötigen.
@capgo/capacitor-native-audio <audio> + Mediensitzung
Abspielmotor Native WebView
Webunterstützung Ja (HTML-Audio-Fallback) Ja
Schirmmetadaten showNotification + notificationMetadata setMetadata
Android-Hintergrunddienst Sie starten einen Das Plugin startet ihn, während man spielt oder pausiert
Remote-Control-Ereignisse playbackState Hörer setActionHandler
Genauere, niedrigschwellige SFX Ja Beschränkt

Konfigurieren Sie iOS für Hintergrundaudio

Öffnen ios/App/App/Info.plist und fügen Sie die Hintergrundfunktion hinzu. Sie können auch das Kontrollkästchen "Audio, AirPlay und Bild in Bild" unter Signieren und Fähigkeiten, Hintergrundfunktionen in Xcode anwählen, was denselben Schlüssel schreibt:

<key>UIBackgroundModes</key>
<array>
  <string>audio</string>
</array>

Die Audio-Sitzungskategorie spielt auch eine Rolle. @capgo/capacitor-native-audio setzt es für Sie ein: mit showNotification: true es verwendet .playback mit der Standardmodus, der andere Apps unterbricht (Spotify pausiert) und macht Ihre App zum Now Playing-App. Mit showNotification: false es verwendet .playback mit mixWithOthers, was für Soundeffekte richtig ist, zeigt aber keine Steuerung auf dem Bildschirm an. Wählen Sie eine pro App, nicht pro Track.

Wenn Sie durch <audio>spielen, aktiviert WebKit die Wiedergabe-Sitzung, wenn das Medium startet. Stellen Sie sicher, dass die Wiedergabe von einem Benutzerinteraktion zum ersten Mal gestartet wird, oder iOS wird es blockieren.

Mit Xcode 26 oder später bauen, bevor Sie es auf App Store Connect hochladen, was seit April 2026 erforderlich ist. Capgo Bauen Kann das auch im Cloud tun, wenn Sie auf Windows oder Linux arbeiten.

Konfigurieren Sie Android für Hintergrundaudio

Fügen Sie den Berechtigungen zu android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

FOREGROUND_SERVICE_MEDIA_PLAYBACK ist für Apps, die sich auf Android 14 (API 34) oder höher richten, und Capacitor 8 API 36. Ohne es wird das Starten des Dienstes einen SecurityException. Wenn Sie veröffentlichen, fragt das Play Console Sie nach, den Vordergrunddiensttyp zu deklarieren und zu rechtfertigen. „Medienwiedergabe, die der Benutzer gestartet hat“, ist der akzeptierte Gebrauch.

POST_NOTIFICATIONS ist eine Laufzeitberechtigung auf Android 13+. Mediensitzungsbenachrichtigungen sind von der Benachrichtigungserechtigung befreit und zeigen sich immer noch im Schatten, aber jede andere Benachrichtigung, die Ihr Dienst postet, benötigt sie.

Android 12+ blockiert das Starten eines Vordergrunddienstes, während die App im Hintergrund ist. Starten Sie es, wenn der Benutzer auf 'Abspielen' klickt, während Ihre Aktivität sichtbar ist.

Option A: Lassen Sie den Mediensitzungs-Plugin den Dienst laufen

@capgo/capacitor-media-session deklariert einen mediaPlayback dienst in seinem eigenen Manifest und startet ihn, wenn Sie den Abspielzustand auf playing oder pausedEs hält es an, wenn der Zustand zurück geht zu none und die App ist im Hintergrund. Wenn Sie die Dienstleistung für die gesamte App-Sitzung ausführen möchten, legen Sie die Plugin-Konfiguration in capacitor.config.ts:

plugins: {
  MediaSession: {
    foregroundService: 'always',
  },
},

The default, starting only during playback, is what most apps want.

Option B: starten Sie Ihren eigenen Vordergrunddienst

@capgo/capacitor-native-audio verwaltet die Wiedergabe, den Fokus und die Medienbenachrichtigung, schafft aber keinen Vordergrunddienst. Wenn Sie es ohne den Medien-Session-Plugin verwenden, fügen Sie einen kleinen Dienst und einen lokalen Plugin zu Ihrem Android-Projekt hinzu.

android/app/src/main/java/com/example/app/PlaybackService.java:

package com.example.app;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.os.Build;
import android.os.IBinder;
import androidx.core.app.NotificationCompat;

public class PlaybackService extends Service {
    private static final String CHANNEL_ID = "playback";

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                CHANNEL_ID, "Playback", NotificationManager.IMPORTANCE_LOW);
            getSystemService(NotificationManager.class).createNotificationChannel(channel);
        }
        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Playing audio")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setOngoing(true)
            .build();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            startForeground(1, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
        } else {
            startForeground(1, notification);
        }
        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

PlaybackServicePlugin.java im gleichen Paket:

package com.example.app;

import android.content.Intent;
import androidx.core.content.ContextCompat;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;

@CapacitorPlugin(name = "PlaybackService")
public class PlaybackServicePlugin extends Plugin {
    @PluginMethod
    public void start(PluginCall call) {
        ContextCompat.startForegroundService(getContext(), new Intent(getContext(), PlaybackService.class));
        call.resolve();
    }

    @PluginMethod
    public void stop(PluginCall call) {
        getContext().stopService(new Intent(getContext(), PlaybackService.class));
        call.resolve();
    }
}

Registrieren Sie es in MainActivity.java vorher super.onCreateund erklären Sie den Dienst im Manifest:

public class MainActivity extends BridgeActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        registerPlugin(PlaybackServicePlugin.class);
        super.onCreate(savedInstanceState);
    }
}
<service
    android:name=".PlaybackService"
    android:exported="false"
    android:foregroundServiceType="mediaPlayback" />

Von TypeScript:

import { Capacitor, registerPlugin } from '@capacitor/core';

interface PlaybackServicePlugin {
  start(): Promise<void>;
  stop(): Promise<void>;
}

export const PlaybackService = registerPlugin<PlaybackServicePlugin>('PlaybackService');

export const isAndroid = Capacitor.getPlatform() === 'android';

Audio natively mit @capgo/capacitor-native-audio spielen

bun add @capgo/capacitor-native-audio
bunx cap sync

Configure einmal bei Start, dann laden und abspielen:

import { NativeAudio } from '@capgo/capacitor-native-audio';
import { PlaybackService, isAndroid } from './playback-service';

await NativeAudio.configure({
  focus: true,               // request audio focus, pause others
  background: true,          // keep playing in the background
  backgroundPlayback: true,  // Android: skip auto pause on background
  showNotification: true,    // lock screen and notification controls
});

export async function playEpisode(id: string, url: string, title: string, artwork: string) {
  await NativeAudio.preload({
    assetId: id,
    assetPath: url,
    isUrl: true,
    notificationMetadata: {
      title,
      artist: 'My Podcast',
      artworkUrl: artwork,
    },
  });

  if (isAndroid) await PlaybackService.start();
  await NativeAudio.play({ assetId: id });
}

export async function stopEpisode(id: string) {
  await NativeAudio.stop({ assetId: id });
  await NativeAudio.unload({ assetId: id });
  if (isAndroid) await PlaybackService.stop();
}

assetPath nimmt einen Pfad relativ zu Ihren Web-Ressourcen (audio/intro.mp3eine file:// eine URL https:// URL oder HLS-Stream. .m3u8 Für alles außer einem gebündelten Asset setzen Sie isUrl: true. If your audio host requires auth, pass headers.

Bauen Sie eine Playlist, die von selbst voranschreitet

Die complete Das Ereignis wird ausgelöst, wenn ein Track endet, selbst wenn das Bildschirm gesperrt ist, weil der native Player weiterläuft:

const queue = [
  { id: 'ep1', url: 'https://cdn.example.com/ep1.mp3', title: 'Episode 1' },
  { id: 'ep2', url: 'https://cdn.example.com/ep2.mp3', title: 'Episode 2' },
];
let index = 0;

await NativeAudio.addListener('complete', async ({ assetId }) => {
  await NativeAudio.unload({ assetId });
  index += 1;
  if (index < queue.length) {
    const next = queue[index];
    await NativeAudio.preload({
      assetId: next.id,
      assetPath: next.url,
      isUrl: true,
      notificationMetadata: { title: next.title, artist: 'My Podcast' },
    });
    await NativeAudio.play({ assetId: next.id });
  } else if (isAndroid) {
    await PlaybackService.stop();
  }
});

Halten Sie den Hintergrunddienst zwischen den Tracks laufend. Wenn Sie ihn nach einem Track beenden und versuchen, ihn wieder zu starten, während er im Hintergrund läuft, werfen Android 12+ ForegroundServiceStartNotAllowedException.

Halten Sie Ihre UI im Einklang mit dem Bildschirmschutz

Benutzer werden auf dem Bildschirmschutz, auf Kopfhörern oder in der Benachrichtigung auf Pause drücken. Hören Sie zu playbackState Behandeln Sie den native Player als Quelle der Wahrheit:

await NativeAudio.addListener('playbackState', (event) => {
  // event.state: 'playing' | 'paused' | 'stopped'
  // event.reason: 'play', 'pause', 'remotePlay', 'complete', ...
  store.setPlaying(event.isPlaying);
  if (event.currentTime !== undefined) store.setPosition(event.currentTime);
});

await NativeAudio.addListener('currentTime', ({ currentTime }) => {
  store.setPosition(currentTime); // every 100 ms while playing
});

Aktualisieren Sie auch den Zustand, wenn die App wieder in den Vordergrund kommt, mit isPlaying Und getCurrentTimeDa der WebView möglicherweise während der Ereignisemission pausiert wurde.

Verwenden Sie ein HTML-Audio-Element mit Medien-Sitzungssteuerungen.

If you already have a web player, keep it and add the plugin:

bun add @capgo/capacitor-media-session
bunx cap sync
import { MediaSession } from '@capgo/capacitor-media-session';

const audio = new Audio();
audio.preload = 'auto';

export async function play(track: { url: string; title: string; artist: string; cover: string }) {
  audio.src = track.url;
  await audio.play();

  await MediaSession.setMetadata({
    title: track.title,
    artist: track.artist,
    artwork: [{ src: track.cover, sizes: '512x512', type: 'image/jpeg' }],
  });
  await MediaSession.setPlaybackState({ playbackState: 'playing' });
}

await MediaSession.setActionHandler({ action: 'play' }, async () => {
  await audio.play();
  await MediaSession.setPlaybackState({ playbackState: 'playing' });
});
await MediaSession.setActionHandler({ action: 'pause' }, async () => {
  audio.pause();
  await MediaSession.setPlaybackState({ playbackState: 'paused' });
});
await MediaSession.setActionHandler({ action: 'seekto' }, (details) => {
  if (details.seekTime != null) audio.currentTime = details.seekTime;
});
await MediaSession.setActionHandler({ action: 'nexttrack' }, () => playNext());

audio.addEventListener('timeupdate', () => {
  MediaSession.setPositionState({
    duration: audio.duration || 0,
    position: audio.currentTime,
    playbackRate: audio.playbackRate,
  });
});

Aufrufen setPositionState mindestens einmal pro Sekunde in der Produktion. Die Bildschirmsperre interpoliert zwischen den Updates und überschwemmt den Brückenkopf mit timeupdate Ereignisse verbrauchen die Batterie.

Ereignissen, was die Batterie verschwendet.

Phone calls, Siri, alarms and other apps interrupt playback. Native audio pauses on interruption and, on iOS, resumes when the system says it should. Two more cases need your attention:

  • Kopfhörer nicht angeschlossenBenutzer erwarten, dass das Abspielen angehalten wird. Bei Android registrieren Sie einen Empfänger für AudioManager.ACTION_AUDIO_BECOMING_NOISY : Benutzer erwarten, dass das Abspielen pausiert wird. Auf Android registrieren Sie einen Empfänger für @capgo/capacitor-audio-session:
import { AudioSession, RouteChangeReasons } from '@capgo/capacitor-audio-session';

await AudioSession.addListener('routeChanged', (reason) => {
  if (reason === RouteChangeReasons.OLD_DEVICE_UNAVAILABLE) {
    pausePlayback();
  }
});

await AudioSession.addListener('interruption', (type) => {
  // 'began' or 'ended'
});
  • Ducking vs. Pausieren: Navigation-Anfragen sperren Ihr Audio. Apps mit gesprochenem Wort sollten anhalten, da gedämpfte Sprache schwer zu folgen ist.

Testen Sie den Hintergrundabspiel

Simulatoren liegen über Hintergrundverhalten. Testen Sie auf echten Geräten:

  1. Starte die Wiedergabe, sperre das Gerät, warte zwei Minuten. Der Audio muss weiterlaufen.
  2. Use the lock screen play, pause, next and seek controls, then unlock and check your UI matches.
  3. Play, switch to another app that plays audio, then come back.
  4. Starten Sie einen Anruf oder FaceTime-Audio während des Abspielens.
  5. Bei Android aktivieren Sie die Energieeinsparfunktion und testen Sie auf einem Samsung- oder Xiaomi-Gerät. Einige OEMs töten Hintergrundanwendungen aggressiv. Ein Vordergrunddienst überlebt, eine einfache Hintergrundaufgabe nicht.
  6. Auf Android 13+, die Benachrichtigungs-Erlaubnis ablehnen und bestätigen, dass das Abspielen weiterhin funktioniert.
  7. Lasen Sie eine Wiedergabeliste mehrere Tracks mit dem Bildschirm aus laufen.

adb shell dumpsys activity services | grep -A3 PlaybackService zeigt an, ob Ihr Dienst im Vordergrund läuft.

Hilfe bei Problemen

Audio hört nach etwa 30 Sekunden auf, wenn man iOS verwendet: UIBackgroundModes mangelt audio, oder die Sitzungs-Kategorie ist ambient oder soloAmbient. Check Info.plist im gebauten App, nicht nur in Ihrer Quelle.

Keine Steuerung auf dem Lockscreen bei iOSKein Hintergrunddienst, oder der Dienst ist nicht vom Typ mediaPlayback: kein Vordergrunddienst, oder der Dienst ist nicht vom Typ

SecurityException: Starting FGS with type mediaPlayback ... requires permissions: add FOREGROUND_SERVICE_MEDIA_PLAYBACK.

ForegroundServiceStartNotAllowedExceptionSie haben den Dienst gestartet, während die App im Hintergrund war. Starten Sie ihn beim Anhalten des Spieltons.

Überprüfen Sie auch die OEM-Batterie-Optimierungseinstellungen.: showNotification is falsch (mixbare Sitzung), oder wurde kein Metadaten gesetzt. Nur die App, die eine nicht-mixbare Sitzung besitzt, wird zum Now Playing App.

Zwei Benachrichtigungen auf Android: Sie haben es aktiviert showNotification in native Audio und haben auch Ihre eigene Dienstbenachrichtigung gepostet. Halten Sie die Dienstbenachrichtigung minimal, oder verwenden Sie nur die Mediensitzung-Plugin’s Dienst.

Die anderen Musik-Apps spielen weiterhin über Ihre: Sie haben eine mixbare Sitzung konfiguriert. Setzen Sie focus: true und showNotification: true.

Schiffe Spieleränderungen schneller

Die Logik, die Benutzeroberfläche, die Metadaten und die Analytik Ihres Spielers laufen in JavaScript. Sobald die native Einrichtung oben in einem Build-Store ist. Capgo Live-Updates lassen Sie Fixes auf das code pushen, ohne dass ein neuer Review-Zyklus erforderlich ist. Capacitor native Audio-Dokumentation und Mediadokumentation Alle Optionen abdecken, und wenn Ihre App auch Audio aufnimmt, sehen Sie sich bitte die Capacitor Audioaufnahmeproxy.

Live Updates für Capacitor-Apps

Wenn ein Bug im Weblayer lebt, schicken Sie die Reparatur über Capgo anstatt Tage für die Genehmigung im App Store zu warten. Die Benutzer erhalten die Aktualisierung im Hintergrund, während native Änderungen im normalen Review-Prozess bleiben.

Unterstützung durch Menschen von Martin

Get Started Now

Neueste von unserem Blog

Capgo gibt Ihnen die besten Einblicke, die Sie benötigen, um eine wirklich professionelle mobile App zu erstellen.