From 739a6362bfad44fd4caebf00a782acef3a7169e8 Mon Sep 17 00:00:00 2001 From: Kurt Johnson Date: Thu, 7 Feb 2019 11:02:10 -0500 Subject: [PATCH 01/37] Fix so background audio from other apps can play when disableFocus is true. requestAudioFocus was being run regardless of there being a src, so I made it so that only gets requested when a src exists. --- .../main/java/com/brentvatne/exoplayer/ReactExoplayerView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 64c8a404..87113dbe 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -366,7 +366,7 @@ class ReactExoplayerView extends FrameLayout implements } private boolean requestAudioFocus() { - if (disableFocus) { + if (disableFocus || srcUri == null) { return true; } int result = audioManager.requestAudioFocus(this, From a55b7e5a24371b30c382cf0d5d24498ad2928c30 Mon Sep 17 00:00:00 2001 From: Kurt Johnson Date: Thu, 7 Feb 2019 11:14:27 -0500 Subject: [PATCH 02/37] Added details to readme and changelog --- CHANGELOG.md | 2 +- README.md | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 280ada24..723c186a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ## Changelog ### next - +* Fix Android videos being able to play with background music/audio from other apps. * Fix loading package resolved videos when using video-caching [#1438](https://github.com/react-native-community/react-native-video/pull/1438) ### Version 4.3.0 diff --git a/README.md b/README.md index 8af2d371..20ea61c9 100644 --- a/README.md +++ b/README.md @@ -363,6 +363,13 @@ Controls are not available Android because the system does not provide a stock s Platforms: iOS, react-native-dom +#### disableFocus +Determines whether video audio should override background music/audio in Android devices. +* ** false (default)** - Override background audio/music +* **true** - Let background audio/music from other apps play + +Platforms: Android Exoplayer + #### filter Add video filter * **FilterType.NONE (default)** - No Filter From 3989d73063e30cf55fb0fecc2266fb5051c04b49 Mon Sep 17 00:00:00 2001 From: JB Paul Date: Fri, 24 May 2019 16:32:05 +0900 Subject: [PATCH 03/37] react-native 0.59 support --- android/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/android/build.gradle b/android/build.gradle index ff05f873..f7049f33 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -21,6 +21,7 @@ android { dependencies { //noinspection GradleDynamicVersion + compile 'com.facebook.react:react-native:+' compileOnly "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" implementation 'com.yqritc:android-scalablevideoview:1.0.4' } From 327d8625a1988dcd56582528d37cefb51c160667 Mon Sep 17 00:00:00 2001 From: JB Paul Date: Fri, 24 May 2019 17:53:13 +0900 Subject: [PATCH 04/37] simplified logic --- android/build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index f7049f33..df1bb2c8 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -21,7 +21,6 @@ android { dependencies { //noinspection GradleDynamicVersion - compile 'com.facebook.react:react-native:+' - compileOnly "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" + implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" implementation 'com.yqritc:android-scalablevideoview:1.0.4' } From d61a0d7983399bc7e18d64a47240099523e52d77 Mon Sep 17 00:00:00 2001 From: JB Paul Date: Fri, 24 May 2019 18:03:38 +0900 Subject: [PATCH 05/37] update other vulnerable --- android-exoplayer/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android-exoplayer/build.gradle b/android-exoplayer/build.gradle index 717d04ad..7fccb220 100644 --- a/android-exoplayer/build.gradle +++ b/android-exoplayer/build.gradle @@ -22,7 +22,7 @@ android { } dependencies { - compileOnly "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" + implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}" implementation('com.google.android.exoplayer:exoplayer:2.9.3') { exclude group: 'com.android.support' } From a0bb083064e22cd7363a6321f4973de5442a9c43 Mon Sep 17 00:00:00 2001 From: Jens Andersson Date: Mon, 10 Jun 2019 18:00:03 +0100 Subject: [PATCH 06/37] Remove video layer when entering background correctly, both if using controls or not --- ios/Video/RCTVideo.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index dcadee85..271433b3 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -223,6 +223,7 @@ static int const RCTVideoUnset = -1; if (_playInBackground) { // Needed to play sound in background. See https://developer.apple.com/library/ios/qa/qa1668/_index.html [_playerLayer setPlayer:nil]; + [_playerViewController setPlayer:nil]; } } @@ -231,6 +232,7 @@ static int const RCTVideoUnset = -1; [self applyModifiers]; if (_playInBackground) { [_playerLayer setPlayer:_player]; + [_playerViewController setPlayer:_player]; } } From 0a1557984e8920de49d372415016c8c4f5e46861 Mon Sep 17 00:00:00 2001 From: Jens Andersson Date: Mon, 17 Jun 2019 09:20:13 +0100 Subject: [PATCH 07/37] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a91fd638..3ebcc088 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### next * Added `onPlaybackRateChange` to README [#1578](https://github.com/react-native-community/react-native-video/pull/1578) +* Fix background audio stopping on iOS when using `controls` [#1614](https://github.com/react-native-community/react-native-video/pull/1614) ### Version 4.4.1 * Fix tvOS picture-in-picture compilation regression [#1518](https://github.com/react-native-community/react-native-video/pull/1518) From 112608cbaf80547843521a6549e45d44ca083448 Mon Sep 17 00:00:00 2001 From: CHaNGeTe <> Date: Tue, 18 Jun 2019 07:31:17 +0200 Subject: [PATCH 08/37] RCTDirectEventBlock --- ios/Video/RCTVideoManager.m | 42 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/ios/Video/RCTVideoManager.m b/ios/Video/RCTVideoManager.m index a608f32e..1614eab1 100644 --- a/ios/Video/RCTVideoManager.m +++ b/ios/Video/RCTVideoManager.m @@ -45,25 +45,25 @@ RCT_EXPORT_VIEW_PROPERTY(filterEnabled, BOOL); RCT_EXPORT_VIEW_PROPERTY(progressUpdateInterval, float); RCT_EXPORT_VIEW_PROPERTY(restoreUserInterfaceForPIPStopCompletionHandler, BOOL); /* Should support: onLoadStart, onLoad, and onError to stay consistent with Image */ -RCT_EXPORT_VIEW_PROPERTY(onVideoLoadStart, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onVideoLoad, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onVideoBuffer, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onVideoError, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onVideoProgress, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onBandwidthUpdate, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onVideoSeek, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onVideoEnd, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onTimedMetadata, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onVideoAudioBecomingNoisy, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerWillPresent, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerDidPresent, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerWillDismiss, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerDidDismiss, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onReadyForDisplay, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onPlaybackStalled, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onPlaybackResume, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onPlaybackRateChange, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onVideoExternalPlaybackChange, RCTBubblingEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoLoadStart, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoLoad, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoBuffer, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoError, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoProgress, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onBandwidthUpdate, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoSeek, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoEnd, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onTimedMetadata, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoAudioBecomingNoisy, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerWillPresent, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerDidPresent, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerWillDismiss, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerDidDismiss, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onReadyForDisplay, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onPlaybackStalled, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onPlaybackResume, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onPlaybackRateChange, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onVideoExternalPlaybackChange, RCTDirectEventBlock); RCT_REMAP_METHOD(save, options:(NSDictionary *)options reactTag:(nonnull NSNumber *)reactTag @@ -79,8 +79,8 @@ RCT_REMAP_METHOD(save, } }]; } -RCT_EXPORT_VIEW_PROPERTY(onPictureInPictureStatusChanged, RCTBubblingEventBlock); -RCT_EXPORT_VIEW_PROPERTY(onRestoreUserInterfaceForPictureInPictureStop, RCTBubblingEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onPictureInPictureStatusChanged, RCTDirectEventBlock); +RCT_EXPORT_VIEW_PROPERTY(onRestoreUserInterfaceForPictureInPictureStop, RCTDirectEventBlock); - (NSDictionary *)constantsToExport { From 32796e9a54566a9f812b825303966adec7abf3b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marin=CC=83o?= Date: Wed, 19 Jun 2019 09:22:10 +0200 Subject: [PATCH 09/37] Change also RCTVideo.h --- ios/Video/RCTVideo.h | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/ios/Video/RCTVideo.h b/ios/Video/RCTVideo.h index 19d5d19f..26d436c2 100644 --- a/ios/Video/RCTVideo.h +++ b/ios/Video/RCTVideo.h @@ -21,27 +21,27 @@ @interface RCTVideo : UIView #endif -@property (nonatomic, copy) RCTBubblingEventBlock onVideoLoadStart; -@property (nonatomic, copy) RCTBubblingEventBlock onVideoLoad; -@property (nonatomic, copy) RCTBubblingEventBlock onVideoBuffer; -@property (nonatomic, copy) RCTBubblingEventBlock onVideoError; -@property (nonatomic, copy) RCTBubblingEventBlock onVideoProgress; -@property (nonatomic, copy) RCTBubblingEventBlock onBandwidthUpdate; -@property (nonatomic, copy) RCTBubblingEventBlock onVideoSeek; -@property (nonatomic, copy) RCTBubblingEventBlock onVideoEnd; -@property (nonatomic, copy) RCTBubblingEventBlock onTimedMetadata; -@property (nonatomic, copy) RCTBubblingEventBlock onVideoAudioBecomingNoisy; -@property (nonatomic, copy) RCTBubblingEventBlock onVideoFullscreenPlayerWillPresent; -@property (nonatomic, copy) RCTBubblingEventBlock onVideoFullscreenPlayerDidPresent; -@property (nonatomic, copy) RCTBubblingEventBlock onVideoFullscreenPlayerWillDismiss; -@property (nonatomic, copy) RCTBubblingEventBlock onVideoFullscreenPlayerDidDismiss; -@property (nonatomic, copy) RCTBubblingEventBlock onReadyForDisplay; -@property (nonatomic, copy) RCTBubblingEventBlock onPlaybackStalled; -@property (nonatomic, copy) RCTBubblingEventBlock onPlaybackResume; -@property (nonatomic, copy) RCTBubblingEventBlock onPlaybackRateChange; -@property (nonatomic, copy) RCTBubblingEventBlock onVideoExternalPlaybackChange; -@property (nonatomic, copy) RCTBubblingEventBlock onPictureInPictureStatusChanged; -@property (nonatomic, copy) RCTBubblingEventBlock onRestoreUserInterfaceForPictureInPictureStop; +@property (nonatomic, copy) RCTDirectEventBlock onVideoLoadStart; +@property (nonatomic, copy) RCTDirectEventBlock onVideoLoad; +@property (nonatomic, copy) RCTDirectEventBlock onVideoBuffer; +@property (nonatomic, copy) RCTDirectEventBlock onVideoError; +@property (nonatomic, copy) RCTDirectEventBlock onVideoProgress; +@property (nonatomic, copy) RCTDirectEventBlock onBandwidthUpdate; +@property (nonatomic, copy) RCTDirectEventBlock onVideoSeek; +@property (nonatomic, copy) RCTDirectEventBlock onVideoEnd; +@property (nonatomic, copy) RCTDirectEventBlock onTimedMetadata; +@property (nonatomic, copy) RCTDirectEventBlock onVideoAudioBecomingNoisy; +@property (nonatomic, copy) RCTDirectEventBlock onVideoFullscreenPlayerWillPresent; +@property (nonatomic, copy) RCTDirectEventBlock onVideoFullscreenPlayerDidPresent; +@property (nonatomic, copy) RCTDirectEventBlock onVideoFullscreenPlayerWillDismiss; +@property (nonatomic, copy) RCTDirectEventBlock onVideoFullscreenPlayerDidDismiss; +@property (nonatomic, copy) RCTDirectEventBlock onReadyForDisplay; +@property (nonatomic, copy) RCTDirectEventBlock onPlaybackStalled; +@property (nonatomic, copy) RCTDirectEventBlock onPlaybackResume; +@property (nonatomic, copy) RCTDirectEventBlock onPlaybackRateChange; +@property (nonatomic, copy) RCTDirectEventBlock onVideoExternalPlaybackChange; +@property (nonatomic, copy) RCTDirectEventBlock onPictureInPictureStatusChanged; +@property (nonatomic, copy) RCTDirectEventBlock onRestoreUserInterfaceForPictureInPictureStop; - (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER; From 9c04bd23fe18af6cfd6607061bc05743cdf4150b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marin=CC=83o?= Date: Wed, 19 Jun 2019 09:24:51 +0200 Subject: [PATCH 10/37] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a91fd638..f888c691 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Changelog ### next +* Replaced RCTBubblingEventBlock events by RCTDirectEventBlock to avoid event name collisions [#1625](https://github.com/react-native-community/react-native-video/pull/1625) * Added `onPlaybackRateChange` to README [#1578](https://github.com/react-native-community/react-native-video/pull/1578) ### Version 4.4.1 From 6d3936de0bfe877e0918adceaddba120d5917cba Mon Sep 17 00:00:00 2001 From: Jens Andersson Date: Wed, 19 Jun 2019 10:39:35 +0100 Subject: [PATCH 11/37] Fixes bug where poster and video was displayed simultaneously --- Video.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Video.js b/Video.js index 81c1b802..d7bd51f6 100644 --- a/Video.js +++ b/Video.js @@ -308,15 +308,16 @@ export default class Video extends Component { }; return ( - - - {this.props.poster && - this.state.showPoster && ( - - - - )} - + + + {this.props.poster && this.state.showPoster && ( + + )} + ); } } From cc7db9149097090a99c1d9579cb661f864375b08 Mon Sep 17 00:00:00 2001 From: Jens Andersson Date: Wed, 19 Jun 2019 12:00:57 +0100 Subject: [PATCH 12/37] Improved handling of poster, fading it out on load --- Video.js | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/Video.js b/Video.js index d7bd51f6..890d4ba2 100644 --- a/Video.js +++ b/Video.js @@ -1,6 +1,6 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; -import {StyleSheet, requireNativeComponent, NativeModules, View, ViewPropTypes, Image, Platform, findNodeHandle} from 'react-native'; +import {StyleSheet, requireNativeComponent, NativeModules, View, ViewPropTypes, Image, Platform, findNodeHandle,Animated} from 'react-native'; import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource'; import TextTrackType from './TextTrackType'; import FilterType from './FilterType'; @@ -20,7 +20,8 @@ export default class Video extends Component { super(props); this.state = { - showPoster: true, + showPoster: !!props.poster, + posterFadeAnim: new Animated.Value(1), }; } @@ -86,6 +87,18 @@ export default class Video extends Component { this._root = component; }; + _hidePoster = () => { + Animated.timing( + this.state.posterFadeAnim, + { + toValue: 0, + delay: 200, // Not ideal but need to wait for the first frame to be rendered + duration: 100, + useNativeDriver: true + } + ).start(() => this.setState({showPoster: false})); + } + _onLoadStart = (event) => { if (this.props.onLoadStart) { this.props.onLoadStart(event.nativeEvent); @@ -93,6 +106,9 @@ export default class Video extends Component { }; _onLoad = (event) => { + if (this.state.showPoster) { + this._hidePoster(); + } if (this.props.onLoad) { this.props.onLoad(event.nativeEvent); } @@ -117,10 +133,6 @@ export default class Video extends Component { }; _onSeek = (event) => { - if (this.state.showPoster && !this.props.audioOnly) { - this.setState({showPoster: false}); - } - if (this.props.onSeek) { this.props.onSeek(event.nativeEvent); } @@ -181,10 +193,6 @@ export default class Video extends Component { }; _onPlaybackRateChange = (event) => { - if (this.state.showPoster && event.nativeEvent.playbackRate !== 0 && !this.props.audioOnly) { - this.setState({showPoster: false}); - } - if (this.props.onPlaybackRateChange) { this.props.onPlaybackRateChange(event.nativeEvent); } @@ -314,8 +322,8 @@ export default class Video extends Component { {...nativeProps} style={StyleSheet.absoluteFill} /> - {this.props.poster && this.state.showPoster && ( - + {this.state.showPoster && ( + )} ); From 420332e0780de3028fa04c4117fdeb2c0c2ed7a6 Mon Sep 17 00:00:00 2001 From: Jens Andersson Date: Wed, 19 Jun 2019 14:18:25 +0100 Subject: [PATCH 13/37] Implemented onReadyForDisplay for iOS when using controls --- ios/Video/RCTVideo.m | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index dcadee85..e7f4b557 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -354,8 +354,6 @@ static int const RCTVideoUnset = -1; [self setMaxBitRate:_maxBitRate]; [_player pause]; - [_playerViewController.view removeFromSuperview]; - _playerViewController = nil; if (_playbackRateObserverRegistered) { [_player removeObserver:self forKeyPath:playbackRate context:nil]; @@ -598,7 +596,10 @@ static int const RCTVideoUnset = -1; } else return [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } - + if([keyPath isEqualToString:readyForDisplayKeyPath] && [change objectForKey:NSKeyValueChangeNewKey] && self.onReadyForDisplay) { + self.onReadyForDisplay(@{@"target": self.reactTag}); + return; + } if (object == _playerItem) { // When timeMetadata is read the event onTimedMetadata is triggered if ([keyPath isEqualToString:timedMetadata]) { @@ -690,12 +691,6 @@ static int const RCTVideoUnset = -1; _playerBufferEmpty = NO; self.onVideoBuffer(@{@"isBuffering": @(NO), @"target": self.reactTag}); } - } else if (object == _playerLayer) { - if([keyPath isEqualToString:readyForDisplayKeyPath] && [change objectForKey:NSKeyValueChangeNewKey]) { - if([change objectForKey:NSKeyValueChangeNewKey] && self.onReadyForDisplay) { - self.onReadyForDisplay(@{@"target": self.reactTag}); - } - } } else if (object == _player) { if([keyPath isEqualToString:playbackRate]) { if(self.onPlaybackRateChange) { @@ -1283,7 +1278,9 @@ static int const RCTVideoUnset = -1; { if( _player ) { - _playerViewController = [self createPlayerViewController:_player withPlayerItem:_playerItem]; + if (!_playerViewController) { + _playerViewController = [self createPlayerViewController:_player withPlayerItem:_playerItem]; + } // to prevent video from being animated when resizeMode is 'cover' // resize mode must be set before subview is added [self setResizeMode:_resizeMode]; @@ -1293,6 +1290,8 @@ static int const RCTVideoUnset = -1; [viewController addChildViewController:_playerViewController]; [self addSubview:_playerViewController.view]; } + + [_playerViewController addObserver:self forKeyPath:readyForDisplayKeyPath options:NSKeyValueObservingOptionNew context:nil]; [_playerViewController.contentOverlayView addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:NULL]; } @@ -1488,6 +1487,7 @@ static int const RCTVideoUnset = -1; [self removePlayerLayer]; [_playerViewController.contentOverlayView removeObserver:self forKeyPath:@"frame"]; + [_playerViewController removeObserver:self forKeyPath:readyForDisplayKeyPath]; [_playerViewController.view removeFromSuperview]; _playerViewController = nil; From b193baa8024fde08fa165c3bb66d89bd03c2a07c Mon Sep 17 00:00:00 2001 From: Jens Andersson Date: Wed, 19 Jun 2019 14:19:06 +0100 Subject: [PATCH 14/37] Hide poster at the right time ie in onReadyForDisplay --- Video.js | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/Video.js b/Video.js index 890d4ba2..d9e91cd0 100644 --- a/Video.js +++ b/Video.js @@ -1,6 +1,6 @@ import React, {Component} from 'react'; import PropTypes from 'prop-types'; -import {StyleSheet, requireNativeComponent, NativeModules, View, ViewPropTypes, Image, Platform, findNodeHandle,Animated} from 'react-native'; +import {StyleSheet, requireNativeComponent, NativeModules, View, ViewPropTypes, Image, Platform, findNodeHandle} from 'react-native'; import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource'; import TextTrackType from './TextTrackType'; import FilterType from './FilterType'; @@ -20,8 +20,7 @@ export default class Video extends Component { super(props); this.state = { - showPoster: !!props.poster, - posterFadeAnim: new Animated.Value(1), + showPoster: !!props.poster }; } @@ -88,15 +87,7 @@ export default class Video extends Component { }; _hidePoster = () => { - Animated.timing( - this.state.posterFadeAnim, - { - toValue: 0, - delay: 200, // Not ideal but need to wait for the first frame to be rendered - duration: 100, - useNativeDriver: true - } - ).start(() => this.setState({showPoster: false})); + this.setState({showPoster: false}); } _onLoadStart = (event) => { @@ -106,9 +97,6 @@ export default class Video extends Component { }; _onLoad = (event) => { - if (this.state.showPoster) { - this._hidePoster(); - } if (this.props.onLoad) { this.props.onLoad(event.nativeEvent); } @@ -175,6 +163,9 @@ export default class Video extends Component { }; _onReadyForDisplay = (event) => { + if (this.state.showPoster) { + this._hidePoster(); + } if (this.props.onReadyForDisplay) { this.props.onReadyForDisplay(event.nativeEvent); } @@ -323,7 +314,7 @@ export default class Video extends Component { style={StyleSheet.absoluteFill} /> {this.state.showPoster && ( - + )} ); From e5b5bbee7f1005875b049ff52cec512ead2e55e1 Mon Sep 17 00:00:00 2001 From: Jens Andersson Date: Wed, 19 Jun 2019 14:32:44 +0100 Subject: [PATCH 15/37] Updated changelog and readme --- CHANGELOG.md | 2 ++ README.md | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a91fd638..04567483 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### next * Added `onPlaybackRateChange` to README [#1578](https://github.com/react-native-community/react-native-video/pull/1578) +* Added `onReadyForDisplay` to README [#1627](https://github.com/react-native-community/react-native-video/pull/1627) +* Improved handling of poster image. Fixes bug with displaying video and poster simultaneously. [#1627](https://github.com/react-native-community/react-native-video/pull/1627) ### Version 4.4.1 * Fix tvOS picture-in-picture compilation regression [#1518](https://github.com/react-native-community/react-native-video/pull/1518) diff --git a/README.md b/README.md index b5f99f21..0f0762b0 100644 --- a/README.md +++ b/README.md @@ -302,6 +302,7 @@ var styles = StyleSheet.create({ * [onFullscreenPlayerDidDismiss](#onfullscreenplayerdiddismiss) * [onLoad](#onload) * [onLoadStart](#onloadstart) +* [onReadyForDisplay](#onreadyfordisplay) * [onPictureInPictureStatusChanged](#onpictureinpicturestatuschanged) * [onPlaybackRateChange](#onplaybackratechange) * [onProgress](#onprogress) @@ -954,6 +955,16 @@ Example: Platforms: all +#### onReadyForDisplay +Callback function that is called when the first video frame is ready for display. This is when the poster is removed. + +Payload: none + +* iOS: [readyForDisplay](https://developer.apple.com/documentation/avkit/avplayerviewcontroller/1615830-readyfordisplay?language=objc) +* Android: [MEDIA_INFO_VIDEO_RENDERING_START](https://developer.android.com/reference/android/media/MediaPlayer#MEDIA_INFO_VIDEO_RENDERING_START) + +Platforms: all + #### onPictureInPictureStatusChanged Callback function that is called when picture in picture becomes active or inactive. From fcef441369c1840fe46a3ed0326694c7cd76dd40 Mon Sep 17 00:00:00 2001 From: Jens Andersson Date: Wed, 19 Jun 2019 15:35:49 +0100 Subject: [PATCH 16/37] Added onReadyForDisplay to web/dom --- README.md | 3 ++- dom/RCTVideo.js | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0f0762b0..c8242d5a 100644 --- a/README.md +++ b/README.md @@ -962,8 +962,9 @@ Payload: none * iOS: [readyForDisplay](https://developer.apple.com/documentation/avkit/avplayerviewcontroller/1615830-readyfordisplay?language=objc) * Android: [MEDIA_INFO_VIDEO_RENDERING_START](https://developer.android.com/reference/android/media/MediaPlayer#MEDIA_INFO_VIDEO_RENDERING_START) +* Android ExoPlayer [STATE_READY](https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/Player.html#STATE_READY) -Platforms: all +Platforms: Android ExoPlayer, Android MediaPlayer, iOS, Web #### onPictureInPictureStatusChanged Callback function that is called when picture in picture becomes active or inactive. diff --git a/dom/RCTVideo.js b/dom/RCTVideo.js index 9831b61d..32128973 100644 --- a/dom/RCTVideo.js +++ b/dom/RCTVideo.js @@ -37,6 +37,7 @@ class RCTVideo extends RCTView { this.videoElement = this.initializeVideoElement(); this.videoElement.addEventListener("ended", this.onEnd); this.videoElement.addEventListener("loadeddata", this.onLoad); + this.videoElement.addEventListener("canplay", this.onReadyForDisplay); this.videoElement.addEventListener("loadstart", this.onLoadStart); this.videoElement.addEventListener("pause", this.onPause); this.videoElement.addEventListener("play", this.onPlay); @@ -51,6 +52,7 @@ class RCTVideo extends RCTView { detachFromView(view: UIView) { this.videoElement.removeEventListener("ended", this.onEnd); this.videoElement.removeEventListener("loadeddata", this.onLoad); + this.videoElement.removeEventListener("canplay", this.onReadyForDisplay); this.videoElement.removeEventListener("loadstart", this.onLoadStart); this.videoElement.removeEventListener("pause", this.onPause); this.videoElement.removeEventListener("play", this.onPlay); @@ -203,6 +205,10 @@ class RCTVideo extends RCTView { this.sendEvent("topVideoLoad", payload); } + onReadyForDisplay = () => { + this.sendEvent("onReadyForDisplay"); + } + onLoadStart = () => { const src = this.videoElement.currentSrc; const payload = { From e033fc4666a896b57810645ef164af646454a0ac Mon Sep 17 00:00:00 2001 From: CHaNGeTe <> Date: Thu, 20 Jun 2019 07:29:46 +0200 Subject: [PATCH 17/37] update changelog for #1592 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9ed1c5e..47a9b218 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Changelog ### next +* Change compileOnly to implementation on gradle (for newer gradle versions and react-native 0.59 support) [#1592](https://github.com/react-native-community/react-native-video/pull/1592) * Replaced RCTBubblingEventBlock events by RCTDirectEventBlock to avoid event name collisions [#1625](https://github.com/react-native-community/react-native-video/pull/1625) * Added `onPlaybackRateChange` to README [#1578](https://github.com/react-native-community/react-native-video/pull/1578) * Fix background audio stopping on iOS when using `controls` [#1614](https://github.com/react-native-community/react-native-video/pull/1614) From 88d2aed832f42ccb7cba1c0fb141cff6cc21ac90 Mon Sep 17 00:00:00 2001 From: CHaNGeTe <> Date: Thu, 20 Jun 2019 07:30:51 +0200 Subject: [PATCH 18/37] bump version --- CHANGELOG.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47a9b218..e1704a35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## Changelog -### next +### Version 4.4.2 * Change compileOnly to implementation on gradle (for newer gradle versions and react-native 0.59 support) [#1592](https://github.com/react-native-community/react-native-video/pull/1592) * Replaced RCTBubblingEventBlock events by RCTDirectEventBlock to avoid event name collisions [#1625](https://github.com/react-native-community/react-native-video/pull/1625) * Added `onPlaybackRateChange` to README [#1578](https://github.com/react-native-community/react-native-video/pull/1578) diff --git a/package.json b/package.json index 08b0dafc..d86ed89f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-video", - "version": "4.4.1", + "version": "4.4.2", "description": "A