diff --git a/README.md b/README.md index 19b4371d..cac87ad2 100644 --- a/README.md +++ b/README.md @@ -239,6 +239,7 @@ var styles = StyleSheet.create({ * [volume](#volume) ### Event props +* [onAudioBecomingNoisy](#onaudiobecomingnoisy) * [onLoad](#onload) * [onLoadStart](#onloadstart) * [onProgress](#onprogress) @@ -452,6 +453,13 @@ Platforms: all ### Event props +#### onAudioBecomingNoisy +Callback function that is called when the audio is about to become 'noisy' due to a change in audio outputs. Typically this is called when audio output is being switched from an external source like headphones back to the internal speaker. It's a good idea to pause the media when this happens so the speaker doesn't start blasting sound. + +Payload: none + +Platforms: Android ExoPlayer, iOS + #### onLoad Callback function that is called when the media is loaded and ready to play. diff --git a/Video.js b/Video.js index 7a0d7a39..dda530d3 100644 --- a/Video.js +++ b/Video.js @@ -235,6 +235,7 @@ export default class Video extends Component { onVideoEnd: this._onEnd, onVideoBuffer: this._onBuffer, onTimedMetadata: this._onTimedMetadata, + onVideoAudioBecomingNoisy: this._onAudioBecomingNoisy, onVideoFullscreenPlayerWillPresent: this._onFullscreenPlayerWillPresent, onVideoFullscreenPlayerDidPresent: this._onFullscreenPlayerDidPresent, onVideoFullscreenPlayerWillDismiss: this._onFullscreenPlayerWillDismiss, @@ -296,6 +297,7 @@ Video.propTypes = { onVideoSeek: PropTypes.func, onVideoEnd: PropTypes.func, onTimedMetadata: PropTypes.func, + onVideoAudioBecomingNoisy: PropTypes.func, onVideoFullscreenPlayerWillPresent: PropTypes.func, onVideoFullscreenPlayerDidPresent: PropTypes.func, onVideoFullscreenPlayerWillDismiss: PropTypes.func, diff --git a/ios/RCTVideo.m b/ios/RCTVideo.m index e155e7d2..c1bf66dd 100644 --- a/ios/RCTVideo.m +++ b/ios/RCTVideo.m @@ -91,6 +91,11 @@ static NSString *const timedMetadata = @"timedMetadata"; selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(audioRouteChanged:) + name:AVAudioSessionRouteChangeNotification + object:nil]; } return self; @@ -190,6 +195,17 @@ static NSString *const timedMetadata = @"timedMetadata"; } } +#pragma mark - Audio events + +- (void)audioRouteChanged:(NSNotification *)notification +{ + NSNumber *reason = [[notification userInfo] objectForKey:AVAudioSessionRouteChangeReasonKey]; + NSNumber *previousRoute = [[notification userInfo] objectForKey:AVAudioSessionRouteChangePreviousRouteKey]; + if (reason.unsignedIntValue == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) { + self.onVideoAudioBecomingNoisy(@{@"target": self.reactTag}); + } +} + #pragma mark - Progress - (void)sendProgressUpdate diff --git a/ios/RCTVideoManager.m b/ios/RCTVideoManager.m index 308d49e8..8e566602 100644 --- a/ios/RCTVideoManager.m +++ b/ios/RCTVideoManager.m @@ -46,6 +46,7 @@ RCT_EXPORT_VIEW_PROPERTY(onVideoProgress, 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);