Merge pull request #236 from thoblr/master
Added possibility to play video in background and when app is inactive.
This commit is contained in:
commit
24c24cd962
32
RCTVideo.m
32
RCTVideo.m
@ -40,6 +40,8 @@ static NSString *const playbackRate = @"rate";
|
||||
BOOL _paused;
|
||||
BOOL _repeat;
|
||||
BOOL _playbackStalled;
|
||||
BOOL _playInBackground;
|
||||
BOOL _playWhenInactive;
|
||||
NSString * _resizeMode;
|
||||
BOOL _fullscreenPlayerPresented;
|
||||
UIViewController * _presentingViewController;
|
||||
@ -61,12 +63,19 @@ static NSString *const playbackRate = @"rate";
|
||||
_progressUpdateInterval = 250;
|
||||
_controls = NO;
|
||||
_playerBufferEmpty = YES;
|
||||
_playInBackground = false;
|
||||
_playWhenInactive = false;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(applicationWillResignActive:)
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(applicationDidEnterBackground:)
|
||||
name:UIApplicationDidEnterBackgroundNotification
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(applicationWillEnterForeground:)
|
||||
name:UIApplicationWillEnterForegroundNotification
|
||||
@ -123,15 +132,26 @@ static NSString *const playbackRate = @"rate";
|
||||
|
||||
- (void)applicationWillResignActive:(NSNotification *)notification
|
||||
{
|
||||
if (!_paused) {
|
||||
if (_playInBackground || _playWhenInactive || _paused) return;
|
||||
|
||||
[_player pause];
|
||||
[_player setRate:0.0];
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(NSNotification *)notification
|
||||
{
|
||||
if (_playInBackground) {
|
||||
// Needed to play sound in background. See https://developer.apple.com/library/ios/qa/qa1668/_index.html
|
||||
[_playerLayer setPlayer:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(NSNotification *)notification
|
||||
{
|
||||
[self applyModifiers];
|
||||
if (_playInBackground) {
|
||||
[_playerLayer setPlayer:_player];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Progress
|
||||
@ -403,6 +423,16 @@ static NSString *const playbackRate = @"rate";
|
||||
_resizeMode = mode;
|
||||
}
|
||||
|
||||
- (void)setPlayInBackground:(BOOL)playInBackground
|
||||
{
|
||||
_playInBackground = playInBackground;
|
||||
}
|
||||
|
||||
- (void)setPlayWhenInactive:(BOOL)playWhenInactive
|
||||
{
|
||||
_playWhenInactive = playWhenInactive;
|
||||
}
|
||||
|
||||
- (void)setPaused:(BOOL)paused
|
||||
{
|
||||
if (paused) {
|
||||
|
@ -48,6 +48,8 @@ RCT_EXPORT_VIEW_PROPERTY(paused, BOOL);
|
||||
RCT_EXPORT_VIEW_PROPERTY(muted, BOOL);
|
||||
RCT_EXPORT_VIEW_PROPERTY(controls, BOOL);
|
||||
RCT_EXPORT_VIEW_PROPERTY(volume, float);
|
||||
RCT_EXPORT_VIEW_PROPERTY(playInBackground, BOOL);
|
||||
RCT_EXPORT_VIEW_PROPERTY(playWhenInactive, BOOL);
|
||||
RCT_EXPORT_VIEW_PROPERTY(rate, float);
|
||||
RCT_EXPORT_VIEW_PROPERTY(seek, float);
|
||||
RCT_EXPORT_VIEW_PROPERTY(currentTime, float);
|
||||
|
@ -71,6 +71,8 @@ Under `.addPackage(new MainReactPackage())`:
|
||||
paused={false} // Pauses playback entirely.
|
||||
resizeMode="cover" // Fill the whole screen at aspect ratio.
|
||||
repeat={true} // Repeat forever.
|
||||
playInBackground={false} // Audio continues to play when app entering background.
|
||||
playWhenInactive={false} // [iOS] Video continues to play when control or notification center are shown.
|
||||
onLoadStart={this.loadStart} // Callback when video starts to load
|
||||
onLoad={this.setDuration} // Callback when video loads
|
||||
onProgress={this.setTime} // Callback every ~250ms with currentTime
|
||||
@ -90,6 +92,10 @@ var styles = StyleSheet.create({
|
||||
});
|
||||
```
|
||||
|
||||
### Play in background on iOS
|
||||
|
||||
To enable audio to play in background on iOS the audio session needs to be set to `AVAudioSessionCategoryPlayback`. See [Apple documentation][3].
|
||||
|
||||
## Static Methods
|
||||
|
||||
`seek(seconds)`
|
||||
@ -120,6 +126,7 @@ Seeks the video to the specified time (in seconds). Access using a ref to the co
|
||||
|
||||
[1]: https://github.com/brentvatne/react-native-login/blob/56c47a5d1e23781e86e19b27e10427fd6391f666/App/Screens/UserInfoScreen.js#L32-L35
|
||||
[2]: https://github.com/brentvatne/react-native-video/tree/master/Examples/VideoPlayer
|
||||
[3]: https://developer.apple.com/library/ios/qa/qa1668/_index.html
|
||||
|
||||
---
|
||||
|
||||
|
2
Video.js
2
Video.js
@ -222,6 +222,8 @@ Video.propTypes = {
|
||||
muted: PropTypes.bool,
|
||||
volume: PropTypes.number,
|
||||
rate: PropTypes.number,
|
||||
playInBackground: PropTypes.bool,
|
||||
playWhenInactive: PropTypes.bool,
|
||||
controls: PropTypes.bool,
|
||||
currentTime: PropTypes.number,
|
||||
onLoadStart: PropTypes.func,
|
||||
|
@ -9,13 +9,14 @@ import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.bridge.LifecycleEventListener;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
import com.yqritc.scalablevideoview.ScalableType;
|
||||
import com.yqritc.scalablevideoview.ScalableVideoView;
|
||||
|
||||
public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnPreparedListener, MediaPlayer
|
||||
.OnErrorListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener {
|
||||
.OnErrorListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener, LifecycleEventListener {
|
||||
|
||||
public enum Events {
|
||||
EVENT_LOAD_START("onVideoLoadStart"),
|
||||
@ -73,6 +74,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
private boolean mMuted = false;
|
||||
private float mVolume = 1.0f;
|
||||
private float mRate = 1.0f;
|
||||
private boolean mPlayInBackground = false;
|
||||
|
||||
private boolean mMediaPlayerValid = false; // True if mMediaPlayer is in prepared, started, or paused state.
|
||||
private int mVideoDuration = 0;
|
||||
@ -83,6 +85,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
|
||||
mThemedReactContext = themedReactContext;
|
||||
mEventEmitter = themedReactContext.getJSModule(RCTEventEmitter.class);
|
||||
themedReactContext.addLifecycleEventListener(this);
|
||||
|
||||
initializeMediaPlayerIfNeeded();
|
||||
setSurfaceTextureListener(this);
|
||||
@ -248,6 +251,10 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
// setRateModifier(mRate);
|
||||
}
|
||||
|
||||
public void setPlayInBackground(final boolean playInBackground) {
|
||||
mPlayInBackground = playInBackground;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepared(MediaPlayer mp) {
|
||||
mMediaPlayerValid = true;
|
||||
@ -324,4 +331,19 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
super.onAttachedToWindow();
|
||||
setSrc(mSrcUriString, mSrcType, mSrcIsNetwork, mSrcIsAsset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHostPause() {
|
||||
if (mMediaPlayer != null && !mPlayInBackground) {
|
||||
mMediaPlayer.pause();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHostResume() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHostDestroy() {
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ public class ReactVideoViewManager extends SimpleViewManager<ReactVideoView> {
|
||||
public static final String PROP_VOLUME = "volume";
|
||||
public static final String PROP_SEEK = "seek";
|
||||
public static final String PROP_RATE = "rate";
|
||||
public static final String PROP_PLAY_IN_BACKGROUND = "playInBackground";
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@ -106,4 +107,9 @@ public class ReactVideoViewManager extends SimpleViewManager<ReactVideoView> {
|
||||
public void setRate(final ReactVideoView videoView, final float rate) {
|
||||
videoView.setRateModifier(rate);
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_PLAY_IN_BACKGROUND, defaultBoolean = false)
|
||||
public void setPlayInBackground(final ReactVideoView videoView, final boolean playInBackground) {
|
||||
videoView.setPlayInBackground(playInBackground);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user