Merge branch 'master' into AndroidRangePlayback
This commit is contained in:
commit
afcde3e335
13
API.md
13
API.md
@ -74,6 +74,17 @@ Video with caching ([more info](docs/caching.md)):
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Enable custom feature in podfile file
|
||||||
|
|
||||||
|
##### Google IMA
|
||||||
|
|
||||||
|
Google IMA is the google SDK to support Client Side Ads Integration (CSAI), see [google documentation](https://developers.google.com/interactive-media-ads/docs/sdks/ios/client-side) for more informations.
|
||||||
|
|
||||||
|
To enable google IMA usage define add following line in your podfile:
|
||||||
|
```podfile
|
||||||
|
$RNVideoUseGoogleIMA=true
|
||||||
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### tvOS installation
|
### tvOS installation
|
||||||
@ -935,7 +946,7 @@ Platforms: iOS, Android
|
|||||||
|
|
||||||
Property | Description | Platforms
|
Property | Description | Platforms
|
||||||
--- | --- | ---
|
--- | --- | ---
|
||||||
fontSizeTrack | Adjust the font size of the subtitles. Default: font size of the device | Android
|
fontSize | Adjust the font size of the subtitles. Default: font size of the device | Android
|
||||||
paddingTop | Adjust the top padding of the subtitles. Default: 0| Android
|
paddingTop | Adjust the top padding of the subtitles. Default: 0| Android
|
||||||
paddingBottom | Adjust the bottom padding of the subtitles. Default: 0| Android
|
paddingBottom | Adjust the bottom padding of the subtitles. Default: 0| Android
|
||||||
paddingLeft | Adjust the left padding of the subtitles. Default: 0| Android
|
paddingLeft | Adjust the left padding of the subtitles. Default: 0| Android
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
### Version 6.0.0-alpha.6
|
### Version 6.0.0-alpha.6
|
||||||
- Feature: Video range support [#3030](https://github.com/react-native-video/react-native-video/pull/3030)
|
- Feature: Video range support [#3030](https://github.com/react-native-video/react-native-video/pull/3030)
|
||||||
|
- iOS: remove undocumented `currentTime` property [#3064](https://github.com/react-native-video/react-native-video/pull/3064)
|
||||||
|
- iOS: make sure that the audio in ads is muted when the player is muted. [#3068](https://github.com/react-native-video/react-native-video/pull/3077)
|
||||||
|
- iOS: make IMA build optionnal
|
||||||
|
|
||||||
### Version 6.0.0-alpha.5
|
### Version 6.0.0-alpha.5
|
||||||
|
|
||||||
|
7
Video.js
7
Video.js
@ -522,7 +522,6 @@ Video.propTypes = {
|
|||||||
disableBuffering: PropTypes.bool,
|
disableBuffering: PropTypes.bool,
|
||||||
controls: PropTypes.bool,
|
controls: PropTypes.bool,
|
||||||
audioOnly: PropTypes.bool,
|
audioOnly: PropTypes.bool,
|
||||||
currentTime: PropTypes.number,
|
|
||||||
fullscreenAutorotate: PropTypes.bool,
|
fullscreenAutorotate: PropTypes.bool,
|
||||||
fullscreenOrientation: PropTypes.oneOf(['all', 'landscape', 'portrait']),
|
fullscreenOrientation: PropTypes.oneOf(['all', 'landscape', 'portrait']),
|
||||||
progressUpdateInterval: PropTypes.number,
|
progressUpdateInterval: PropTypes.number,
|
||||||
@ -559,17 +558,11 @@ Video.propTypes = {
|
|||||||
onAudioFocusChanged: PropTypes.func,
|
onAudioFocusChanged: PropTypes.func,
|
||||||
onAudioBecomingNoisy: PropTypes.func,
|
onAudioBecomingNoisy: PropTypes.func,
|
||||||
onPictureInPictureStatusChanged: PropTypes.func,
|
onPictureInPictureStatusChanged: PropTypes.func,
|
||||||
needsToRestoreUserInterfaceForPictureInPictureStop: PropTypes.func,
|
|
||||||
onExternalPlaybackChange: PropTypes.func,
|
onExternalPlaybackChange: PropTypes.func,
|
||||||
adTagUrl: PropTypes.string,
|
adTagUrl: PropTypes.string,
|
||||||
onReceiveAdEvent: PropTypes.func,
|
onReceiveAdEvent: PropTypes.func,
|
||||||
|
|
||||||
/* Required by react-native */
|
/* Required by react-native */
|
||||||
scaleX: PropTypes.number,
|
|
||||||
scaleY: PropTypes.number,
|
|
||||||
translateX: PropTypes.number,
|
|
||||||
translateY: PropTypes.number,
|
|
||||||
rotation: PropTypes.number,
|
|
||||||
...ViewPropTypes,
|
...ViewPropTypes,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ install! 'cocoapods', :deterministic_uuids => false
|
|||||||
target 'videoplayer' do
|
target 'videoplayer' do
|
||||||
config = use_native_modules!
|
config = use_native_modules!
|
||||||
|
|
||||||
|
# $RNVideoUseGoogleIMA = true
|
||||||
|
|
||||||
# Flags change depending on the env values.
|
# Flags change depending on the env values.
|
||||||
flags = get_default_flags()
|
flags = get_default_flags()
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot";
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
NSDictionary *initProps = [self prepareInitialProps];
|
NSDictionary *initProps = [self prepareInitialProps];
|
||||||
UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"videoplayer", initProps);
|
UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"VideoPlayer", initProps);
|
||||||
|
|
||||||
if (@available(iOS 13.0, *)) {
|
if (@available(iOS 13.0, *)) {
|
||||||
rootView.backgroundColor = [UIColor systemBackgroundColor];
|
rootView.backgroundColor = [UIColor systemBackgroundColor];
|
||||||
@ -85,7 +85,7 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot";
|
|||||||
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
|
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
|
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"src/index"];
|
||||||
#else
|
#else
|
||||||
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#if USE_GOOGLE_IMA
|
||||||
import Foundation
|
import Foundation
|
||||||
import GoogleInteractiveMediaAds
|
import GoogleInteractiveMediaAds
|
||||||
|
|
||||||
@ -76,6 +77,10 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
|||||||
// MARK: - IMAAdsManagerDelegate
|
// MARK: - IMAAdsManagerDelegate
|
||||||
|
|
||||||
func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) {
|
func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) {
|
||||||
|
// Mute ad if the main player is muted
|
||||||
|
if (_video.isMuted()) {
|
||||||
|
adsManager.volume = 0;
|
||||||
|
}
|
||||||
// Play each ad once it has been loaded
|
// Play each ad once it has been loaded
|
||||||
if event.type == IMAAdEventType.LOADED {
|
if event.type == IMAAdEventType.LOADED {
|
||||||
adsManager.start()
|
adsManager.start()
|
||||||
@ -185,3 +190,4 @@ class RCTIMAAdsManager: NSObject, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import AVFoundation
|
import AVFoundation
|
||||||
import AVKit
|
import AVKit
|
||||||
import Foundation
|
import Foundation
|
||||||
|
#if USE_GOOGLE_IMA
|
||||||
import GoogleInteractiveMediaAds
|
import GoogleInteractiveMediaAds
|
||||||
|
#endif
|
||||||
import React
|
import React
|
||||||
import Promises
|
import Promises
|
||||||
|
|
||||||
@ -63,11 +65,13 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
|
|
||||||
/* IMA Ads */
|
/* IMA Ads */
|
||||||
private var _adTagUrl:String?
|
private var _adTagUrl:String?
|
||||||
|
#if USE_GOOGLE_IMA
|
||||||
private var _imaAdsManager: RCTIMAAdsManager!
|
private var _imaAdsManager: RCTIMAAdsManager!
|
||||||
private var _didRequestAds:Bool = false
|
|
||||||
private var _adPlaying:Bool = false
|
|
||||||
/* Playhead used by the SDK to track content video progress and insert mid-rolls. */
|
/* Playhead used by the SDK to track content video progress and insert mid-rolls. */
|
||||||
private var _contentPlayhead: IMAAVPlayerContentPlayhead?
|
private var _contentPlayhead: IMAAVPlayerContentPlayhead?
|
||||||
|
#endif
|
||||||
|
private var _didRequestAds:Bool = false
|
||||||
|
private var _adPlaying:Bool = false
|
||||||
|
|
||||||
private var _resouceLoaderDelegate: RCTResourceLoaderDelegate?
|
private var _resouceLoaderDelegate: RCTResourceLoaderDelegate?
|
||||||
private var _playerObserver: RCTPlayerObserver = RCTPlayerObserver()
|
private var _playerObserver: RCTPlayerObserver = RCTPlayerObserver()
|
||||||
@ -107,8 +111,9 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
|
|
||||||
init(eventDispatcher:RCTEventDispatcher!) {
|
init(eventDispatcher:RCTEventDispatcher!) {
|
||||||
super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
|
super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
|
||||||
|
#if USE_GOOGLE_IMA
|
||||||
_imaAdsManager = RCTIMAAdsManager(video: self)
|
_imaAdsManager = RCTIMAAdsManager(video: self)
|
||||||
|
#endif
|
||||||
|
|
||||||
_eventDispatcher = eventDispatcher
|
_eventDispatcher = eventDispatcher
|
||||||
|
|
||||||
@ -147,8 +152,9 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
|
|
||||||
required init?(coder aDecoder: NSCoder) {
|
required init?(coder aDecoder: NSCoder) {
|
||||||
super.init(coder: aDecoder)
|
super.init(coder: aDecoder)
|
||||||
|
#if USE_GOOGLE_IMA
|
||||||
_imaAdsManager = RCTIMAAdsManager(video: self)
|
_imaAdsManager = RCTIMAAdsManager(video: self)
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
@ -220,10 +226,12 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
])
|
])
|
||||||
|
|
||||||
if currentTimeSecs >= 0 {
|
if currentTimeSecs >= 0 {
|
||||||
|
#if USE_GOOGLE_IMA
|
||||||
if !_didRequestAds && currentTimeSecs >= 0.0001 && _adTagUrl != nil {
|
if !_didRequestAds && currentTimeSecs >= 0.0001 && _adTagUrl != nil {
|
||||||
_imaAdsManager.requestAds()
|
_imaAdsManager.requestAds()
|
||||||
_didRequestAds = true
|
_didRequestAds = true
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
onVideoProgress?([
|
onVideoProgress?([
|
||||||
"currentTime": NSNumber(value: Float(currentTimeSecs)),
|
"currentTime": NSNumber(value: Float(currentTimeSecs)),
|
||||||
"playableDuration": RCTVideoUtils.calculatePlayableDuration(_player, withSource: _source),
|
"playableDuration": RCTVideoUtils.calculatePlayableDuration(_player, withSource: _source),
|
||||||
@ -311,13 +319,14 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
self.setAutomaticallyWaitsToMinimizeStalling(self._automaticallyWaitsToMinimizeStalling)
|
self.setAutomaticallyWaitsToMinimizeStalling(self._automaticallyWaitsToMinimizeStalling)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_GOOGLE_IMA
|
||||||
if self._adTagUrl != nil {
|
if self._adTagUrl != nil {
|
||||||
// Set up your content playhead and contentComplete callback.
|
// Set up your content playhead and contentComplete callback.
|
||||||
self._contentPlayhead = IMAAVPlayerContentPlayhead(avPlayer: self._player!)
|
self._contentPlayhead = IMAAVPlayerContentPlayhead(avPlayer: self._player!)
|
||||||
|
|
||||||
self._imaAdsManager.setUpAdsLoader()
|
self._imaAdsManager.setUpAdsLoader()
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
//Perform on next run loop, otherwise onVideoLoadStart is nil
|
//Perform on next run loop, otherwise onVideoLoadStart is nil
|
||||||
self.onVideoLoadStart?([
|
self.onVideoLoadStart?([
|
||||||
"src": [
|
"src": [
|
||||||
@ -428,7 +437,9 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
func setPaused(_ paused:Bool) {
|
func setPaused(_ paused:Bool) {
|
||||||
if paused {
|
if paused {
|
||||||
if _adPlaying {
|
if _adPlaying {
|
||||||
|
#if USE_GOOGLE_IMA
|
||||||
_imaAdsManager.getAdsManager()?.pause()
|
_imaAdsManager.getAdsManager()?.pause()
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
_player?.pause()
|
_player?.pause()
|
||||||
_player?.rate = 0.0
|
_player?.rate = 0.0
|
||||||
@ -437,7 +448,9 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
RCTPlayerOperations.configureAudio(ignoreSilentSwitch:_ignoreSilentSwitch, mixWithOthers:_mixWithOthers)
|
RCTPlayerOperations.configureAudio(ignoreSilentSwitch:_ignoreSilentSwitch, mixWithOthers:_mixWithOthers)
|
||||||
|
|
||||||
if _adPlaying {
|
if _adPlaying {
|
||||||
|
#if USE_GOOGLE_IMA
|
||||||
_imaAdsManager.getAdsManager()?.resume()
|
_imaAdsManager.getAdsManager()?.resume()
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if #available(iOS 10.0, *), !_automaticallyWaitsToMinimizeStalling {
|
if #available(iOS 10.0, *), !_automaticallyWaitsToMinimizeStalling {
|
||||||
_player?.playImmediately(atRate: _rate)
|
_player?.playImmediately(atRate: _rate)
|
||||||
@ -452,15 +465,6 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
_paused = paused
|
_paused = paused
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
|
||||||
func setCurrentTime(_ currentTime:Float) {
|
|
||||||
let info:NSDictionary = [
|
|
||||||
"time": NSNumber(value: currentTime),
|
|
||||||
"tolerance": NSNumber(value: 100)
|
|
||||||
]
|
|
||||||
setSeek(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
func setSeek(_ info:NSDictionary!) {
|
func setSeek(_ info:NSDictionary!) {
|
||||||
let seekTime:NSNumber! = info["time"] as! NSNumber
|
let seekTime:NSNumber! = info["time"] as! NSNumber
|
||||||
@ -500,6 +504,11 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
applyModifiers()
|
applyModifiers()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
func isMuted() -> Bool {
|
||||||
|
return _muted
|
||||||
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
func setMuted(_ muted:Bool) {
|
func setMuted(_ muted:Bool) {
|
||||||
_muted = muted
|
_muted = muted
|
||||||
@ -840,11 +849,11 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
func setAdTagUrl(_ adTagUrl:String!) {
|
func setAdTagUrl(_ adTagUrl:String!) {
|
||||||
_adTagUrl = adTagUrl
|
_adTagUrl = adTagUrl
|
||||||
}
|
}
|
||||||
|
#if USE_GOOGLE_IMA
|
||||||
func getContentPlayhead() -> IMAAVPlayerContentPlayhead? {
|
func getContentPlayhead() -> IMAAVPlayerContentPlayhead? {
|
||||||
return _contentPlayhead
|
return _contentPlayhead
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
func setAdPlaying(_ adPlaying:Bool) {
|
func setAdPlaying(_ adPlaying:Bool) {
|
||||||
_adPlaying = adPlaying
|
_adPlaying = adPlaying
|
||||||
}
|
}
|
||||||
@ -1012,7 +1021,10 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _pendingSeek {
|
if _pendingSeek {
|
||||||
setCurrentTime(_pendingSeekTime)
|
setSeek([
|
||||||
|
"time": NSNumber(value: _pendingSeekTime),
|
||||||
|
"tolerance": NSNumber(value: 100)
|
||||||
|
])
|
||||||
_pendingSeek = false
|
_pendingSeek = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1122,11 +1134,11 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
|
|
||||||
@objc func handlePlayerItemDidReachEnd(notification:NSNotification!) {
|
@objc func handlePlayerItemDidReachEnd(notification:NSNotification!) {
|
||||||
onVideoEnd?(["target": reactTag as Any])
|
onVideoEnd?(["target": reactTag as Any])
|
||||||
|
#if USE_GOOGLE_IMA
|
||||||
if notification.object as? AVPlayerItem == _player?.currentItem {
|
if notification.object as? AVPlayerItem == _player?.currentItem {
|
||||||
_imaAdsManager.getAdsLoader()?.contentComplete()
|
_imaAdsManager.getAdsLoader()?.contentComplete()
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if _repeat {
|
if _repeat {
|
||||||
let item:AVPlayerItem! = notification.object as? AVPlayerItem
|
let item:AVPlayerItem! = notification.object as? AVPlayerItem
|
||||||
item.seek(to: CMTime.zero, completionHandler: nil)
|
item.seek(to: CMTime.zero, completionHandler: nil)
|
||||||
|
@ -27,7 +27,6 @@ RCT_EXPORT_VIEW_PROPERTY(ignoreSilentSwitch, NSString);
|
|||||||
RCT_EXPORT_VIEW_PROPERTY(mixWithOthers, NSString);
|
RCT_EXPORT_VIEW_PROPERTY(mixWithOthers, NSString);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(rate, float);
|
RCT_EXPORT_VIEW_PROPERTY(rate, float);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(seek, NSDictionary);
|
RCT_EXPORT_VIEW_PROPERTY(seek, NSDictionary);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(currentTime, float);
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(fullscreen, BOOL);
|
RCT_EXPORT_VIEW_PROPERTY(fullscreen, BOOL);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(fullscreenAutorotate, BOOL);
|
RCT_EXPORT_VIEW_PROPERTY(fullscreenAutorotate, BOOL);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(fullscreenOrientation, NSString);
|
RCT_EXPORT_VIEW_PROPERTY(fullscreenOrientation, NSString);
|
||||||
|
@ -19,8 +19,15 @@ Pod::Spec.new do |s|
|
|||||||
ss.source_files = "ios/Video/**/*.{h,m,swift}"
|
ss.source_files = "ios/Video/**/*.{h,m,swift}"
|
||||||
ss.dependency "PromisesSwift"
|
ss.dependency "PromisesSwift"
|
||||||
|
|
||||||
|
if defined?($RNVideoUseGoogleIMA)
|
||||||
|
Pod::UI.puts "RNVideo: enable IMA SDK"
|
||||||
|
|
||||||
ss.ios.dependency 'GoogleAds-IMA-iOS-SDK', '~> 3.18.1'
|
ss.ios.dependency 'GoogleAds-IMA-iOS-SDK', '~> 3.18.1'
|
||||||
ss.tvos.dependency 'GoogleAds-IMA-tvOS-SDK', '~> 4.2'
|
ss.tvos.dependency 'GoogleAds-IMA-tvOS-SDK', '~> 4.2'
|
||||||
|
ss.pod_target_xcconfig = {
|
||||||
|
'OTHER_SWIFT_FLAGS' => '$(inherited) -D USE_GOOGLE_IMA'
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
s.subspec "VideoCaching" do |ss|
|
s.subspec "VideoCaching" do |ss|
|
||||||
|
Loading…
Reference in New Issue
Block a user