This commit is contained in:
Tuan Luong 2021-12-12 13:17:12 +07:00
commit 859a0b8447
6 changed files with 71 additions and 33 deletions

View File

@ -1,6 +1,12 @@
## Changelog ## Changelog
- Fix Android AudioFocus bug that could cause player to not respond to play/pause in some instances [#2311](https://github.com/react-native-video/react-native-video/pull/2311) ### Version 5.2.0
- Fix for tvOS native audio menu language selector
- Update ExoPlayer to allow pre-init and content clear [#2412] (https://github.com/react-native-video/react-native-video/pull/2412)
- iOS rate is reset to 1.0 after play/pause [#2167] (https://github.com/react-native-video/react-native-video/pull/2167)
- Upgrade ExoPlayer to 2.13.2 [#2317] (https://github.com/react-native-video/react-native-video/pull/2317)
- Fix AudioFocus pausing video when attempting to play [#2311] (https://github.com/react-native-video/react-native-video/pull/2311)
### Version 5.1.0-alpha9 ### Version 5.1.0-alpha9

View File

@ -770,6 +770,12 @@ Platforms: Android ExoPlayer
#### source #### source
Sets the media source. You can pass an asset loaded via require or an object with a uri. Sets the media source. You can pass an asset loaded via require or an object with a uri.
Setting the source will trigger the player to attempt to load the provided media with all other given props. Please be sure that all props are provided before/at the same time as setting the source.
Rendering the player component with a null source will init the player, and start playing once a source value is provided.
Providing a null source value after loading a previous source will stop playback, and clear out the previous source content.
The docs for this prop are incomplete and will be updated as each option is investigated and tested. The docs for this prop are incomplete and will be updated as each option is investigated and tested.

View File

@ -514,6 +514,7 @@ class ReactExoplayerView extends FrameLayout implements
player.prepare(mediaSource, !haveResumePosition, false); player.prepare(mediaSource, !haveResumePosition, false);
playerNeedsSource = false; playerNeedsSource = false;
reLayout(exoPlayerView);
eventEmitter.loadStart(); eventEmitter.loadStart();
loadVideoStarted = true; loadVideoStarted = true;
} }
@ -1058,7 +1059,6 @@ class ReactExoplayerView extends FrameLayout implements
public void setSrc(final Uri uri, final String extension, Map<String, String> headers) { public void setSrc(final Uri uri, final String extension, Map<String, String> headers) {
if (uri != null) { if (uri != null) {
boolean isOriginalSourceNull = srcUri == null;
boolean isSourceEqual = uri.equals(srcUri); boolean isSourceEqual = uri.equals(srcUri);
this.srcUri = uri; this.srcUri = uri;
@ -1068,12 +1068,23 @@ class ReactExoplayerView extends FrameLayout implements
DataSourceUtil.getDefaultDataSourceFactory(this.themedReactContext, bandwidthMeter, DataSourceUtil.getDefaultDataSourceFactory(this.themedReactContext, bandwidthMeter,
this.requestHeaders); this.requestHeaders);
if (!isOriginalSourceNull && !isSourceEqual) { if (!isSourceEqual) {
reloadSource(); reloadSource();
} }
} }
} }
public void clearSrc() {
if (srcUri != null) {
player.stop(true);
this.srcUri = null;
this.extension = null;
this.requestHeaders = null;
this.mediaDataSourceFactory = null;
clearResumePosition();
}
}
public void setProgressUpdateInterval(final float progressUpdateInterval) { public void setProgressUpdateInterval(final float progressUpdateInterval) {
mProgressUpdateInterval = progressUpdateInterval; mProgressUpdateInterval = progressUpdateInterval;
} }
@ -1084,14 +1095,13 @@ class ReactExoplayerView extends FrameLayout implements
public void setRawSrc(final Uri uri, final String extension) { public void setRawSrc(final Uri uri, final String extension) {
if (uri != null) { if (uri != null) {
boolean isOriginalSourceNull = srcUri == null;
boolean isSourceEqual = uri.equals(srcUri); boolean isSourceEqual = uri.equals(srcUri);
this.srcUri = uri; this.srcUri = uri;
this.extension = extension; this.extension = extension;
this.mediaDataSourceFactory = buildDataSourceFactory(true); this.mediaDataSourceFactory = buildDataSourceFactory(true);
if (!isOriginalSourceNull && !isSourceEqual) { if (!isSourceEqual) {
reloadSource(); reloadSource();
} }
} }

View File

@ -145,6 +145,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
Map<String, String> headers = src.hasKey(PROP_SRC_HEADERS) ? toStringMap(src.getMap(PROP_SRC_HEADERS)) : null; Map<String, String> headers = src.hasKey(PROP_SRC_HEADERS) ? toStringMap(src.getMap(PROP_SRC_HEADERS)) : null;
if (TextUtils.isEmpty(uriString)) { if (TextUtils.isEmpty(uriString)) {
videoView.clearSrc();
return; return;
} }

View File

@ -918,6 +918,7 @@ static int const RCTVideoUnset = -1;
- (void)setIgnoreSilentSwitch:(NSString *)ignoreSilentSwitch - (void)setIgnoreSilentSwitch:(NSString *)ignoreSilentSwitch
{ {
_ignoreSilentSwitch = ignoreSilentSwitch; _ignoreSilentSwitch = ignoreSilentSwitch;
[self configureAudio];
[self applyModifiers]; [self applyModifiers];
} }
@ -933,29 +934,8 @@ static int const RCTVideoUnset = -1;
[_player pause]; [_player pause];
[_player setRate:0.0]; [_player setRate:0.0];
} else { } else {
AVAudioSession *session = [AVAudioSession sharedInstance];
AVAudioSessionCategory category = nil;
AVAudioSessionCategoryOptions options = nil;
if([_ignoreSilentSwitch isEqualToString:@"ignore"]) { [self configureAudio];
category = AVAudioSessionCategoryPlayback;
} else if([_ignoreSilentSwitch isEqualToString:@"obey"]) {
category = AVAudioSessionCategoryAmbient;
}
if([_mixWithOthers isEqualToString:@"mix"]) {
options = AVAudioSessionCategoryOptionMixWithOthers;
} else if([_mixWithOthers isEqualToString:@"duck"]) {
options = AVAudioSessionCategoryOptionDuckOthers;
}
if (category != nil && options != nil) {
[session setCategory:category withOptions:options error:nil];
} else if (category != nil && options == nil) {
[session setCategory:category error:nil];
} else if (category == nil && options != nil) {
[session setCategory:session.category withOptions:options error:nil];
}
if (@available(iOS 10.0, *) && !_automaticallyWaitsToMinimizeStalling) { if (@available(iOS 10.0, *) && !_automaticallyWaitsToMinimizeStalling) {
[_player playImmediatelyAtRate:_rate]; [_player playImmediatelyAtRate:_rate];
@ -1089,6 +1069,33 @@ static int const RCTVideoUnset = -1;
[self setAllowsExternalPlayback:_allowsExternalPlayback]; [self setAllowsExternalPlayback:_allowsExternalPlayback];
} }
- (void)configureAudio
{
AVAudioSession *session = [AVAudioSession sharedInstance];
AVAudioSessionCategory category = nil;
AVAudioSessionCategoryOptions options = nil;
if([_ignoreSilentSwitch isEqualToString:@"ignore"]) {
category = AVAudioSessionCategoryPlayback;
} else if([_ignoreSilentSwitch isEqualToString:@"obey"]) {
category = AVAudioSessionCategoryAmbient;
}
if([_mixWithOthers isEqualToString:@"mix"]) {
options = AVAudioSessionCategoryOptionMixWithOthers;
} else if([_mixWithOthers isEqualToString:@"duck"]) {
options = AVAudioSessionCategoryOptionDuckOthers;
}
if (category != nil && options != nil) {
[session setCategory:category withOptions:options error:nil];
} else if (category != nil && options == nil) {
[session setCategory:category error:nil];
} else if (category == nil && options != nil) {
[session setCategory:session.category withOptions:options error:nil];
}
}
- (void)setRepeat:(BOOL)repeat { - (void)setRepeat:(BOOL)repeat {
_repeat = repeat; _repeat = repeat;
} }
@ -1130,12 +1137,20 @@ static int const RCTVideoUnset = -1;
} }
} }
} else { // default. invalid type or "system" } else { // default. invalid type or "system"
#if TARGET_OS_TV
// Do noting. Fix for tvOS native audio menu language selector
#else
[_player.currentItem selectMediaOptionAutomaticallyInMediaSelectionGroup:group]; [_player.currentItem selectMediaOptionAutomaticallyInMediaSelectionGroup:group];
return; return;
#endif
} }
#if TARGET_OS_TV
// Do noting. Fix for tvOS native audio menu language selector
#else
// If a match isn't found, option will be nil and text tracks will be disabled // If a match isn't found, option will be nil and text tracks will be disabled
[_player.currentItem selectMediaOption:mediaOption inMediaSelectionGroup:group]; [_player.currentItem selectMediaOption:mediaOption inMediaSelectionGroup:group];
#endif
} }
- (void)setSelectedAudioTrack:(NSDictionary *)selectedAudioTrack { - (void)setSelectedAudioTrack:(NSDictionary *)selectedAudioTrack {

View File

@ -1,6 +1,6 @@
{ {
"name": "react-native-video", "name": "react-native-video",
"version": "5.1.1", "version": "5.2.0",
"description": "A <Video /> element for react-native", "description": "A <Video /> element for react-native",
"main": "Video.js", "main": "Video.js",
"license": "MIT", "license": "MIT",