mirror of
https://github.com/zoriya/react-native-video.git
synced 2025-12-06 07:16:12 +00:00
feat: add media session support on android
This commit is contained in:
@@ -158,6 +158,9 @@ dependencies {
|
|||||||
// For media playback using ExoPlayer
|
// For media playback using ExoPlayer
|
||||||
implementation "androidx.media3:media3-exoplayer:$media3_version"
|
implementation "androidx.media3:media3-exoplayer:$media3_version"
|
||||||
|
|
||||||
|
// For exposing and controlling media sessions
|
||||||
|
implementation "androidx.media3:media3-session:$media3_version"
|
||||||
|
|
||||||
// For Smooth Streaming playback support with ExoPlayer
|
// For Smooth Streaming playback support with ExoPlayer
|
||||||
implementation "androidx.media3:media3-exoplayer-smoothstreaming:$media3_version"
|
implementation "androidx.media3:media3-exoplayer-smoothstreaming:$media3_version"
|
||||||
// For DASH playback support with ExoPlayer
|
// For DASH playback support with ExoPlayer
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import android.media.AudioManager;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.support.v4.media.MediaDescriptionCompat;
|
||||||
|
import android.support.v4.media.session.MediaSessionCompat;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -112,6 +114,8 @@ import com.google.ads.interactivemedia.v3.api.AdError;
|
|||||||
import com.google.ads.interactivemedia.v3.api.AdEvent;
|
import com.google.ads.interactivemedia.v3.api.AdEvent;
|
||||||
import com.google.ads.interactivemedia.v3.api.AdErrorEvent;
|
import com.google.ads.interactivemedia.v3.api.AdErrorEvent;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
|
||||||
|
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator;
|
||||||
|
|
||||||
import java.net.CookieHandler;
|
import java.net.CookieHandler;
|
||||||
import java.net.CookieManager;
|
import java.net.CookieManager;
|
||||||
@@ -163,6 +167,10 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
private FullScreenPlayerView fullScreenPlayerView;
|
private FullScreenPlayerView fullScreenPlayerView;
|
||||||
private ImaAdsLoader adsLoader;
|
private ImaAdsLoader adsLoader;
|
||||||
|
|
||||||
|
private MediaSessionCompat mediaSession;
|
||||||
|
private MediaSessionConnector mediaSessionConnector;
|
||||||
|
private MediaDescriptionCompat.Builder mediaSessionMetadata = new MediaDescriptionCompat.Builder();
|
||||||
|
|
||||||
private DataSource.Factory mediaDataSourceFactory;
|
private DataSource.Factory mediaDataSourceFactory;
|
||||||
private ExoPlayer player;
|
private ExoPlayer player;
|
||||||
private DefaultTrackSelector trackSelector;
|
private DefaultTrackSelector trackSelector;
|
||||||
@@ -663,6 +671,16 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
PlaybackParameters params = new PlaybackParameters(rate, 1f);
|
PlaybackParameters params = new PlaybackParameters(rate, 1f);
|
||||||
player.setPlaybackParameters(params);
|
player.setPlaybackParameters(params);
|
||||||
changeAudioOutput(this.audioOutput);
|
changeAudioOutput(this.audioOutput);
|
||||||
|
|
||||||
|
mediaSession = new MediaSessionCompat(this, "sample");
|
||||||
|
mediaSessionConnector = new MediaSessionConnector(mediaSession);
|
||||||
|
mediaSessionConnector.setPlayer(player);
|
||||||
|
mediaSessionConnector.setQueueNavigator(new TimelineQueueNavigator(mediaSession) {
|
||||||
|
@Override
|
||||||
|
public MediaDescriptionCompat getMediaDescription(Player player, int windowIndex) {
|
||||||
|
return mediaSessionMetadata.build();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private DrmSessionManager initializePlayerDrm(ReactExoplayerView self) {
|
private DrmSessionManager initializePlayerDrm(ReactExoplayerView self) {
|
||||||
@@ -733,6 +751,10 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
player.prepare();
|
player.prepare();
|
||||||
playerNeedsSource = false;
|
playerNeedsSource = false;
|
||||||
|
|
||||||
|
if (mediaSession != null) {
|
||||||
|
mediaSession.setActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
reLayoutControls();
|
reLayoutControls();
|
||||||
|
|
||||||
eventEmitter.loadStart();
|
eventEmitter.loadStart();
|
||||||
@@ -909,6 +931,10 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
adsLoader.release();
|
adsLoader.release();
|
||||||
}
|
}
|
||||||
adsLoader = null;
|
adsLoader = null;
|
||||||
|
if (mediaSession != null) {
|
||||||
|
mediaSession.release();
|
||||||
|
mediaSession = null;
|
||||||
|
}
|
||||||
progressHandler.removeMessages(SHOW_PROGRESS);
|
progressHandler.removeMessages(SHOW_PROGRESS);
|
||||||
audioBecomingNoisyReceiver.removeListener();
|
audioBecomingNoisyReceiver.removeListener();
|
||||||
bandwidthMeter.removeEventListener(this);
|
bandwidthMeter.removeEventListener(this);
|
||||||
@@ -1038,6 +1064,9 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
if (isFullscreen) {
|
if (isFullscreen) {
|
||||||
setFullscreen(false);
|
setFullscreen(false);
|
||||||
}
|
}
|
||||||
|
if (mediaSession != null) {
|
||||||
|
mediaSession.setActive(false);
|
||||||
|
}
|
||||||
audioManager.abandonAudioFocus(audioFocusChangeListener);
|
audioManager.abandonAudioFocus(audioFocusChangeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2098,6 +2127,11 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
DebugLog.d("DRM Info", "onDrmKeysRemoved");
|
DebugLog.d("DRM Info", "onDrmKeysRemoved");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMediaSessionTitle(String title) { this.mediaSessionMetadata.setTitle((title)); }
|
||||||
|
public void setMediaSessionSubtitle(String subtitle) { this.mediaSessionMetadata.setSubtitle((subtitle)); }
|
||||||
|
public void setMediaSessionDescription(String description) { this.mediaSessionMetadata.setDescription((description)); }
|
||||||
|
public void setMediaSessionImage(String uri) { this.mediaSessionMetadata.setMediaUri((Uri.parse(uri))); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handling controls prop
|
* Handling controls prop
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
private static final String PROP_CONTROLS = "controls";
|
private static final String PROP_CONTROLS = "controls";
|
||||||
private static final String PROP_SUBTITLE_STYLE = "subtitleStyle";
|
private static final String PROP_SUBTITLE_STYLE = "subtitleStyle";
|
||||||
private static final String PROP_SHUTTER_COLOR = "shutterColor";
|
private static final String PROP_SHUTTER_COLOR = "shutterColor";
|
||||||
|
private static final String PROP_MEDIA_SESSION = "mediaSession";
|
||||||
private static final String PROP_DEBUG = "debug";
|
private static final String PROP_DEBUG = "debug";
|
||||||
|
|
||||||
private ReactExoplayerConfig config;
|
private ReactExoplayerConfig config;
|
||||||
@@ -433,6 +434,21 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = PROP_MEDIA_SESSION)
|
||||||
|
public void setMediaSession(final ReactExoplayerView videoView, @Nullable ReadableMap mediaSessionMetadata) {
|
||||||
|
if (mediaSessionMetadata == null) return;
|
||||||
|
|
||||||
|
String title = mediaSessionMetadata.getString("title");
|
||||||
|
String subtitle = mediaSessionMetadata.getString("subtitle");
|
||||||
|
String description = mediaSessionMetadata.getString("description");
|
||||||
|
String imageUri = mediaSessionMetadata.getString("imageUri");
|
||||||
|
|
||||||
|
if (title != null) { videoView.setMediaSessionTitle(title); }
|
||||||
|
if (subtitle != null) { videoView.setMediaSessionSubtitle(subtitle); }
|
||||||
|
if (description != null) { videoView.setMediaSessionDescription(description); }
|
||||||
|
if (imageUri != null) { videoView.setMediaSessionImage(imageUri); }
|
||||||
|
}
|
||||||
|
|
||||||
@ReactProp(name = PROP_DEBUG, defaultBoolean = false)
|
@ReactProp(name = PROP_DEBUG, defaultBoolean = false)
|
||||||
public void setDebug(final ReactExoplayerView videoView,
|
public void setDebug(final ReactExoplayerView videoView,
|
||||||
@Nullable final ReadableMap debugConfig) {
|
@Nullable final ReadableMap debugConfig) {
|
||||||
|
|||||||
@@ -5,5 +5,7 @@
|
|||||||
nodePackages.yarn
|
nodePackages.yarn
|
||||||
eslint_d
|
eslint_d
|
||||||
prettierd
|
prettierd
|
||||||
|
jdk11
|
||||||
|
(jdt-language-server.override { jdk = jdk11; })
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
|||||||
selectedVideoTrack,
|
selectedVideoTrack,
|
||||||
selectedAudioTrack,
|
selectedAudioTrack,
|
||||||
selectedTextTrack,
|
selectedTextTrack,
|
||||||
|
mediaSession,
|
||||||
onLoadStart,
|
onLoadStart,
|
||||||
onLoad,
|
onLoad,
|
||||||
onError,
|
onError,
|
||||||
|
|||||||
@@ -180,6 +180,13 @@ export enum PosterResizeModeType {
|
|||||||
|
|
||||||
export type AudioOutput = 'speaker' | 'earpiece';
|
export type AudioOutput = 'speaker' | 'earpiece';
|
||||||
|
|
||||||
|
export type MediaSession = {
|
||||||
|
title: string;
|
||||||
|
subtitle: string;
|
||||||
|
description: string;
|
||||||
|
imageUri: string;
|
||||||
|
};
|
||||||
|
|
||||||
export interface ReactVideoProps extends ReactVideoEvents, ViewProps {
|
export interface ReactVideoProps extends ReactVideoEvents, ViewProps {
|
||||||
source?: ReactVideoSource;
|
source?: ReactVideoSource;
|
||||||
drm?: Drm;
|
drm?: Drm;
|
||||||
@@ -235,4 +242,5 @@ export interface ReactVideoProps extends ReactVideoEvents, ViewProps {
|
|||||||
localSourceEncryptionKeyScheme?: string;
|
localSourceEncryptionKeyScheme?: string;
|
||||||
debug?: DebugConfig;
|
debug?: DebugConfig;
|
||||||
allowsExternalPlayback?: boolean; // iOS
|
allowsExternalPlayback?: boolean; // iOS
|
||||||
|
mediaSession?: MediaSession;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user