UNPKG

expo-video

Version:

A cross-platform, performant video component for React Native and Expo with Web support

104 lines (90 loc) 3.25 kB
import { AndroidConfig, type ConfigPlugin, withInfoPlist, withAndroidManifest, } from 'expo/config-plugins'; export type WithExpoVideoOptions = { /** Whether to enable background playback support. */ supportsBackgroundPlayback?: boolean; /** Whether to enable Picture-in-Picture on Android and iOS. */ supportsPictureInPicture?: boolean; }; const withExpoVideo: ConfigPlugin<WithExpoVideoOptions> = ( config, { supportsBackgroundPlayback, supportsPictureInPicture } = {} ) => { withInfoPlist(config, (config) => { const currentBackgroundModes = config.modResults.UIBackgroundModes ?? []; const shouldEnableBackgroundAudio = supportsBackgroundPlayback || supportsPictureInPicture; // No-op if the values are not defined if ( typeof supportsBackgroundPlayback === 'undefined' && typeof supportsPictureInPicture === 'undefined' ) { return config; } if (shouldEnableBackgroundAudio && !currentBackgroundModes.includes('audio')) { config.modResults.UIBackgroundModes = [...currentBackgroundModes, 'audio']; } else if (!shouldEnableBackgroundAudio) { config.modResults.UIBackgroundModes = currentBackgroundModes.filter( (mode: string) => mode !== 'audio' ); } return config; }); withAndroidManifest(config, (config) => { const activity = AndroidConfig.Manifest.getMainActivityOrThrow(config.modResults); // Handle Picture in Picture configuration if (typeof supportsPictureInPicture !== 'undefined') { if (supportsPictureInPicture) { activity.$['android:supportsPictureInPicture'] = 'true'; } else { delete activity.$['android:supportsPictureInPicture']; } } // Handle background playback configuration if (supportsBackgroundPlayback) { // Add required permissions for foreground service AndroidConfig.Permissions.ensurePermissions(config.modResults, [ 'android.permission.FOREGROUND_SERVICE', 'android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK', ]); // Add the foreground service to the manifest const application = AndroidConfig.Manifest.getMainApplicationOrThrow(config.modResults); // Check if the service already exists const existingService = application.service?.find( (service: any) => service.$?.['android:name'] === 'expo.modules.video.playbackService.ExpoVideoPlaybackService' ); if (!existingService) { // Add the service if it doesn't exist if (!application.service) { application.service = []; } application.service.push({ $: { 'android:name': 'expo.modules.video.playbackService.ExpoVideoPlaybackService', 'android:exported': 'false', 'android:foregroundServiceType': 'mediaPlayback', }, 'intent-filter': [ { action: [ { $: { 'android:name': 'androidx.media3.session.MediaSessionService', }, }, ], }, ], }); } } return config; }); return config; }; export default withExpoVideo;