Merge branch 'upstream-master'
This commit is contained in:
commit
5b3f08781e
@ -1,8 +1,17 @@
|
||||
## Changelog
|
||||
|
||||
### Next Version
|
||||
* Partial support for timed metadata on Android MediaPlayer [#707](https://github.com/react-native-community/react-native-video/pull/707)
|
||||
* Update to ExoPlayer 2.8.2. Android SDK 26 now required [#1170](https://github.com/react-native-community/react-native-video/pull/1170)
|
||||
|
||||
### Version 3.2.0
|
||||
* Basic fullscreen support for Android MediaPlayer [#1138](https://github.com/react-native-community/react-native-video/pull/1138)
|
||||
* Simplify default Android SDK code [#1145](https://github.com/react-native-community/react-native-video/pull/1145) [#1146](https://github.com/react-native-community/react-native-video/pull/1146)
|
||||
* Various iOS sideloaded text track fixes [#1157](https://github.com/react-native-community/react-native-video/pull/1157)
|
||||
* Fix #1150 where assets with bundled assets don't work on iOS in release mode [#1162](https://github.com/react-native-community/react-native-video/pull/1162)
|
||||
* Support configuring the buffer on Android ExoPlayer [#1160](https://github.com/react-native-community/react-native-video/pull/1160)
|
||||
* Prevent sleep from sleeping while videos are playing on Android MediaPlayer [#1117](https://github.com/react-native-community/react-native-video/pull/1117)
|
||||
* Update NewtonSoft JSON to match react-native-windows version [#1169](https://github.com/react-native-community/react-native-video/pull/1169)
|
||||
|
||||
### Version 3.1.0
|
||||
* Support sidecar text tracks on iOS [#1109](https://github.com/react-native-community/react-native-video/pull/1109)
|
||||
|
36
README.md
36
README.md
@ -3,9 +3,12 @@
|
||||
A `<Video>` component for react-native, as seen in
|
||||
[react-native-login](https://github.com/brentvatne/react-native-login)!
|
||||
|
||||
Requires react-native >= 0.40.0, for RN support of 0.19.0 - 0.39.0 please use a pre 1.0 version.
|
||||
Requires react-native >= 0.40.0
|
||||
|
||||
### Version 3.0 breaking changes
|
||||
### Version 4.0.0 breaking changes
|
||||
Version 4.0.0 now requires Android SDK 26 or higher to use ExoPlayer. This is the default version as of React Native 0.56 and will be required by Google for all apps in October 2018.
|
||||
|
||||
### Version 3.0.0 breaking changes
|
||||
Version 3.0 features a number of changes to existing behavior. See [Updating](#updating) for changes.
|
||||
|
||||
## TOC
|
||||
@ -210,6 +213,7 @@ var styles = StyleSheet.create({
|
||||
### Configurable props
|
||||
* [allowsExternalPlayback](#allowsexternalplayback)
|
||||
* [audioOnly](#audioonly)
|
||||
* [bufferConfig](#bufferconfig)
|
||||
* [ignoreSilentSwitch](#ignoresilentswitch)
|
||||
* [muted](#muted)
|
||||
* [paused](#paused)
|
||||
@ -262,6 +266,30 @@ For this to work, the poster prop must be set.
|
||||
|
||||
Platforms: all
|
||||
|
||||
#### bufferConfig
|
||||
Adjust the buffer settings. This prop takes an object with one or more of the properties listed below.
|
||||
|
||||
Property | Type | Description
|
||||
--- | --- | ---
|
||||
minBufferMs | number | The default minimum duration of media that the player will attempt to ensure is buffered at all times, in milliseconds.
|
||||
maxBufferMs | number | The default maximum duration of media that the player will attempt to buffer, in milliseconds.
|
||||
bufferForPlaybackMs | number | The default duration of media that must be buffered for playback to start or resume following a user action such as a seek, in milliseconds.
|
||||
playbackAfterRebufferMs | number | The default duration of media that must be buffered for playback to resume after a rebuffer, in milliseconds. A rebuffer is defined to be caused by buffer depletion rather than a user action.
|
||||
|
||||
This prop should only be set when you are setting the source, changing it after the media is loaded will cause it to be reloaded.
|
||||
|
||||
Example with default values:
|
||||
```
|
||||
bufferConfig={{
|
||||
minBufferMs: 15000,
|
||||
maxBufferMs: 50000,
|
||||
bufferForPlaybackMs: 2500,
|
||||
bufferForPlaybackAfterRebufferMs: 5000
|
||||
}}
|
||||
```
|
||||
|
||||
Platforms: Android ExoPlayer
|
||||
|
||||
#### ignoreSilentSwitch
|
||||
Controls the iOS silent switch behavior
|
||||
* **"inherit" (default)** - Use the default AVPlayer behavior
|
||||
@ -617,7 +645,9 @@ Example:
|
||||
}
|
||||
```
|
||||
|
||||
Platforms: Android ExoPlayer, iOS
|
||||
Support for timed metadata on Android MediaPlayer is limited at best and only compatible with some videos. It requires a target SDK of 23 or higher.
|
||||
|
||||
Platforms: Android ExoPlayer, Android MediaPlayer, iOS
|
||||
|
||||
### Methods
|
||||
Methods operate on a ref to the Video element. You can create a ref using code like:
|
||||
|
6
Video.js
6
Video.js
@ -350,6 +350,12 @@ Video.propTypes = {
|
||||
paused: PropTypes.bool,
|
||||
muted: PropTypes.bool,
|
||||
volume: PropTypes.number,
|
||||
bufferConfig: PropTypes.shape({
|
||||
minBufferMs: PropTypes.number,
|
||||
maxBufferMs: PropTypes.number,
|
||||
bufferForPlaybackMs: PropTypes.number,
|
||||
bufferForPlaybackAfterRebufferMs: PropTypes.number,
|
||||
}),
|
||||
stereoPan: PropTypes.number,
|
||||
rate: PropTypes.number,
|
||||
playInBackground: PropTypes.bool,
|
||||
|
@ -19,9 +19,18 @@ android {
|
||||
dependencies {
|
||||
//noinspection GradleDynamicVersion
|
||||
provided "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}"
|
||||
compile 'com.google.android.exoplayer:exoplayer:2.7.3'
|
||||
compile('com.google.android.exoplayer:extension-okhttp:2.7.3') {
|
||||
compile('com.google.android.exoplayer:exoplayer:2.8.2') {
|
||||
exclude group: 'com.android.support'
|
||||
}
|
||||
|
||||
// All support libs must use the same version
|
||||
compile "com.android.support:support-annotations:${safeExtGet('supportLibVersion', '+')}"
|
||||
compile "com.android.support:support-compat:${safeExtGet('supportLibVersion', '+')}"
|
||||
compile "com.android.support:support-media-compat:${safeExtGet('supportLibVersion', '+')}"
|
||||
|
||||
compile('com.google.android.exoplayer:extension-okhttp:2.8.2') {
|
||||
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
|
||||
}
|
||||
compile 'com.squareup.okhttp3:okhttp:3.9.1'
|
||||
compile 'com.squareup.okhttp3:okhttp:3.11.0'
|
||||
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultAllocator;
|
||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
@ -97,7 +98,7 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
|
||||
private DataSource.Factory mediaDataSourceFactory;
|
||||
private SimpleExoPlayer player;
|
||||
private MappingTrackSelector trackSelector;
|
||||
private DefaultTrackSelector trackSelector;
|
||||
private boolean playerNeedsSource;
|
||||
|
||||
private int resumeWindow;
|
||||
@ -109,6 +110,11 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
private boolean isBuffering;
|
||||
private float rate = 1f;
|
||||
|
||||
private int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
||||
private int maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||
private int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||
private int bufferForPlaybackAfterRebufferMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS;
|
||||
|
||||
// Props from React
|
||||
private Uri srcUri;
|
||||
private String extension;
|
||||
@ -234,7 +240,9 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
if (player == null) {
|
||||
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
|
||||
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
|
||||
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, new DefaultLoadControl());
|
||||
DefaultAllocator allocator = new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE);
|
||||
DefaultLoadControl defaultLoadControl = new DefaultLoadControl(allocator, minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, -1, true);
|
||||
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, defaultLoadControl);
|
||||
player.addListener(this);
|
||||
player.setMetadataOutput(this);
|
||||
exoPlayerView.setPlayer(player);
|
||||
@ -320,7 +328,6 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
|
||||
private void releasePlayer() {
|
||||
if (player != null) {
|
||||
isPaused = player.getPlayWhenReady();
|
||||
updateResumePosition();
|
||||
player.release();
|
||||
player.setMetadataOutput(null);
|
||||
@ -526,12 +533,12 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
TrackGroupArray groups = info.getTrackGroups(index);
|
||||
for (int i = 0; i < groups.length; ++i) {
|
||||
Format format = groups.get(i).getFormat(0);
|
||||
WritableMap textTrack = Arguments.createMap();
|
||||
textTrack.putInt("index", i);
|
||||
textTrack.putString("title", format.id != null ? format.id : "");
|
||||
textTrack.putString("type", format.sampleMimeType);
|
||||
textTrack.putString("language", format.language != null ? format.language : "");
|
||||
audioTracks.pushMap(textTrack);
|
||||
WritableMap audioTrack = Arguments.createMap();
|
||||
audioTrack.putInt("index", i);
|
||||
audioTrack.putString("title", format.id != null ? format.id : "");
|
||||
audioTrack.putString("type", format.sampleMimeType);
|
||||
audioTrack.putString("language", format.language != null ? format.language : "");
|
||||
audioTracks.pushMap(audioTrack);
|
||||
}
|
||||
return audioTracks;
|
||||
}
|
||||
@ -767,8 +774,13 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
type = "default";
|
||||
}
|
||||
|
||||
DefaultTrackSelector.Parameters disableParameters = trackSelector.getParameters()
|
||||
.buildUpon()
|
||||
.setRendererDisabled(rendererIndex, true)
|
||||
.build();
|
||||
|
||||
if (type.equals("disabled")) {
|
||||
trackSelector.setSelectionOverride(rendererIndex, groups, null);
|
||||
trackSelector.setParameters(disableParameters);
|
||||
return;
|
||||
} else if (type.equals("language")) {
|
||||
for (int i = 0; i < groups.length; ++i) {
|
||||
@ -791,17 +803,12 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
trackIndex = value.asInt();
|
||||
}
|
||||
} else { // default
|
||||
if (rendererIndex == C.TRACK_TYPE_TEXT) { // Use system settings if possible
|
||||
int sdk = android.os.Build.VERSION.SDK_INT;
|
||||
if (sdk > 18 && groups.length > 0) {
|
||||
CaptioningManager captioningManager
|
||||
= (CaptioningManager)themedReactContext.getSystemService(Context.CAPTIONING_SERVICE);
|
||||
if (captioningManager != null && captioningManager.isEnabled()) {
|
||||
trackIndex = getTrackIndexForDefaultLocale(groups);
|
||||
}
|
||||
} else {
|
||||
trackSelector.setSelectionOverride(rendererIndex, groups, null);
|
||||
return;
|
||||
if (rendererIndex == C.TRACK_TYPE_TEXT && Util.SDK_INT > 18 && groups.length > 0) {
|
||||
// Use system settings if possible
|
||||
CaptioningManager captioningManager
|
||||
= (CaptioningManager)themedReactContext.getSystemService(Context.CAPTIONING_SERVICE);
|
||||
if (captioningManager != null && captioningManager.isEnabled()) {
|
||||
trackIndex = getTrackIndexForDefaultLocale(groups);
|
||||
}
|
||||
} else if (rendererIndex == C.TRACK_TYPE_AUDIO) {
|
||||
trackIndex = getTrackIndexForDefaultLocale(groups);
|
||||
@ -809,14 +816,17 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
}
|
||||
|
||||
if (trackIndex == C.INDEX_UNSET) {
|
||||
trackSelector.clearSelectionOverrides(trackIndex);
|
||||
trackSelector.setParameters(disableParameters);
|
||||
return;
|
||||
}
|
||||
|
||||
MappingTrackSelector.SelectionOverride override
|
||||
= new MappingTrackSelector.SelectionOverride(
|
||||
new FixedTrackSelection.Factory(), trackIndex, 0);
|
||||
trackSelector.setSelectionOverride(rendererIndex, groups, override);
|
||||
DefaultTrackSelector.Parameters selectionParameters = trackSelector.getParameters()
|
||||
.buildUpon()
|
||||
.setRendererDisabled(rendererIndex, false)
|
||||
.setSelectionOverride(rendererIndex, groups,
|
||||
new DefaultTrackSelector.SelectionOverride(trackIndex, 0))
|
||||
.build();
|
||||
trackSelector.setParameters(selectionParameters);
|
||||
}
|
||||
|
||||
private int getTrackIndexForDefaultLocale(TrackGroupArray groups) {
|
||||
@ -931,4 +941,13 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
public void setUseTextureView(boolean useTextureView) {
|
||||
exoPlayerView.setUseTextureView(useTextureView);
|
||||
}
|
||||
|
||||
public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBufferForPlaybackMs, int newBufferForPlaybackAfterRebufferMs) {
|
||||
minBufferMs = newMinBufferMs;
|
||||
maxBufferMs = newMaxBufferMs;
|
||||
bufferForPlaybackMs = newBufferForPlaybackMs;
|
||||
bufferForPlaybackAfterRebufferMs = newBufferForPlaybackAfterRebufferMs;
|
||||
releasePlayer();
|
||||
initializePlayer();
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import com.facebook.react.common.MapBuilder;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.ViewGroupManager;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.google.android.exoplayer2.DefaultLoadControl;
|
||||
import com.google.android.exoplayer2.upstream.RawResourceDataSource;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -38,6 +39,11 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
private static final String PROP_PAUSED = "paused";
|
||||
private static final String PROP_MUTED = "muted";
|
||||
private static final String PROP_VOLUME = "volume";
|
||||
private static final String PROP_BUFFER_CONFIG = "bufferConfig";
|
||||
private static final String PROP_BUFFER_CONFIG_MIN_BUFFER_MS = "minBufferMs";
|
||||
private static final String PROP_BUFFER_CONFIG_MAX_BUFFER_MS = "maxBufferMs";
|
||||
private static final String PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS = "bufferForPlaybackMs";
|
||||
private static final String PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS = "bufferForPlaybackAfterRebufferMs";
|
||||
private static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval";
|
||||
private static final String PROP_SEEK = "seek";
|
||||
private static final String PROP_RATE = "rate";
|
||||
@ -214,6 +220,25 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
videoView.setUseTextureView(useTextureView);
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_BUFFER_CONFIG)
|
||||
public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) {
|
||||
int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
||||
int maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||
int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||
int bufferForPlaybackAfterRebufferMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS;
|
||||
if (bufferConfig != null) {
|
||||
minBufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MIN_BUFFER_MS)
|
||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_MIN_BUFFER_MS) : minBufferMs;
|
||||
maxBufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MAX_BUFFER_MS)
|
||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_MAX_BUFFER_MS) : maxBufferMs;
|
||||
bufferForPlaybackMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS)
|
||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS) : bufferForPlaybackMs;
|
||||
bufferForPlaybackAfterRebufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS)
|
||||
? bufferConfig.getInt(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS) : bufferForPlaybackAfterRebufferMs;
|
||||
videoView.setBufferConfig(minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean startsWithValidScheme(String uriString) {
|
||||
return uriString.startsWith("http://")
|
||||
|| uriString.startsWith("https://")
|
||||
|
@ -5,11 +5,13 @@ import android.app.Activity;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.graphics.Matrix;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.TimedMetaData;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.WindowManager;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.webkit.CookieManager;
|
||||
@ -21,6 +23,8 @@ import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.LifecycleEventListener;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableNativeArray;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
import com.yqritc.scalablevideoview.ScalableType;
|
||||
@ -29,6 +33,7 @@ import com.yqritc.scalablevideoview.ScaleManager;
|
||||
import com.yqritc.scalablevideoview.Size;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.lang.Math;
|
||||
@ -37,14 +42,21 @@ import java.math.BigDecimal;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnPreparedListener, MediaPlayer
|
||||
.OnErrorListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnInfoListener, LifecycleEventListener, MediaController.MediaPlayerControl {
|
||||
public class ReactVideoView extends ScalableVideoView implements
|
||||
MediaPlayer.OnPreparedListener,
|
||||
MediaPlayer.OnErrorListener,
|
||||
MediaPlayer.OnBufferingUpdateListener,
|
||||
MediaPlayer.OnCompletionListener,
|
||||
MediaPlayer.OnInfoListener,
|
||||
LifecycleEventListener,
|
||||
MediaController.MediaPlayerControl {
|
||||
|
||||
public enum Events {
|
||||
EVENT_LOAD_START("onVideoLoadStart"),
|
||||
EVENT_LOAD("onVideoLoad"),
|
||||
EVENT_ERROR("onVideoError"),
|
||||
EVENT_PROGRESS("onVideoProgress"),
|
||||
EVENT_TIMED_METADATA("onTimedMetadata"),
|
||||
EVENT_SEEK("onVideoSeek"),
|
||||
EVENT_END("onVideoEnd"),
|
||||
EVENT_STALLED("onPlaybackStalled"),
|
||||
@ -83,6 +95,10 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
public static final String EVENT_PROP_WIDTH = "width";
|
||||
public static final String EVENT_PROP_HEIGHT = "height";
|
||||
public static final String EVENT_PROP_ORIENTATION = "orientation";
|
||||
public static final String EVENT_PROP_METADATA = "metadata";
|
||||
public static final String EVENT_PROP_TARGET = "target";
|
||||
public static final String EVENT_PROP_METADATA_IDENTIFIER = "identifier";
|
||||
public static final String EVENT_PROP_METADATA_VALUE = "value";
|
||||
|
||||
public static final String EVENT_PROP_ERROR = "error";
|
||||
public static final String EVENT_PROP_WHAT = "what";
|
||||
@ -96,7 +112,6 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
private Handler videoControlHandler = new Handler();
|
||||
private MediaController mediaController;
|
||||
|
||||
|
||||
private String mSrcUriString = null;
|
||||
private String mSrcType = "mp4";
|
||||
private ReadableMap mRequestHeaders = null;
|
||||
@ -199,6 +214,9 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
mMediaPlayer.setOnBufferingUpdateListener(this);
|
||||
mMediaPlayer.setOnCompletionListener(this);
|
||||
mMediaPlayer.setOnInfoListener(this);
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
mMediaPlayer.setOnTimedMetaDataAvailableListener(new TimedMetaDataAvailableListener());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -359,7 +377,6 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
}
|
||||
|
||||
public void setPausedModifier(final boolean paused) {
|
||||
|
||||
mPaused = paused;
|
||||
|
||||
if (!mMediaPlayerValid) {
|
||||
@ -382,6 +399,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
mProgressUpdateHandler.post(mProgressUpdateRunnable);
|
||||
}
|
||||
}
|
||||
setKeepScreenOn(!mPaused);
|
||||
}
|
||||
|
||||
// reduces the volume based on stereoPan
|
||||
@ -501,7 +519,6 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
this.mUseNativeControls = controls;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPrepared(MediaPlayer mp) {
|
||||
|
||||
@ -545,6 +562,9 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Select track (so we can use it to listen to timed meta data updates)
|
||||
mp.selectTrack(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -579,6 +599,9 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
|
||||
@Override
|
||||
public void onBufferingUpdate(MediaPlayer mp, int percent) {
|
||||
// Select track (so we can use it to listen to timed meta data updates)
|
||||
mp.selectTrack(0);
|
||||
|
||||
mVideoBufferedDuration = (int) Math.round((double) (mVideoDuration * percent) / 100.0);
|
||||
}
|
||||
|
||||
@ -625,21 +648,51 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
|
||||
@Override
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
|
||||
isCompleted = true;
|
||||
mEventEmitter.receiveEvent(getId(), Events.EVENT_END.toString(), null);
|
||||
if (!mRepeat) {
|
||||
setKeepScreenOn(false);
|
||||
}
|
||||
}
|
||||
|
||||
// This is not fully tested and does not work for all forms of timed metadata
|
||||
@TargetApi(23) // 6.0
|
||||
public class TimedMetaDataAvailableListener
|
||||
implements MediaPlayer.OnTimedMetaDataAvailableListener
|
||||
{
|
||||
public void onTimedMetaDataAvailable(MediaPlayer mp, TimedMetaData data) {
|
||||
WritableMap event = Arguments.createMap();
|
||||
|
||||
try {
|
||||
String rawMeta = new String(data.getMetaData(), "UTF-8");
|
||||
WritableMap id3 = Arguments.createMap();
|
||||
|
||||
id3.putString(EVENT_PROP_METADATA_VALUE, rawMeta.substring(rawMeta.lastIndexOf("\u0003") + 1));
|
||||
id3.putString(EVENT_PROP_METADATA_IDENTIFIER, "id3/TDEN");
|
||||
|
||||
WritableArray metadata = new WritableNativeArray();
|
||||
|
||||
metadata.pushMap(id3);
|
||||
|
||||
event.putArray(EVENT_PROP_METADATA, metadata);
|
||||
event.putDouble(EVENT_PROP_TARGET, getId());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
mEventEmitter.receiveEvent(getId(), Events.EVENT_TIMED_METADATA.toString(), event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
|
||||
mMediaPlayerValid = false;
|
||||
super.onDetachedFromWindow();
|
||||
setKeepScreenOn(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
|
||||
super.onAttachedToWindow();
|
||||
|
||||
if(mMainVer>0) {
|
||||
@ -648,7 +701,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
||||
else {
|
||||
setSrc(mSrcUriString, mSrcType, mSrcIsNetwork, mSrcIsAsset, mRequestHeaders);
|
||||
}
|
||||
|
||||
setKeepScreenOn(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-video",
|
||||
"version": "3.1.0",
|
||||
"version": "3.2.0",
|
||||
"description": "A <Video /> element for react-native",
|
||||
"main": "Video.js",
|
||||
"license": "MIT",
|
||||
|
@ -29,8 +29,8 @@
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PresentationCore" />
|
||||
@ -71,4 +71,4 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net46" />
|
||||
</packages>
|
||||
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net46" />
|
||||
</packages>
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2",
|
||||
"Newtonsoft.Json": "9.0.1"
|
||||
"Newtonsoft.Json": "10.0.3"
|
||||
},
|
||||
"frameworks": {
|
||||
"uap10.0": {}
|
||||
@ -14,4 +14,4 @@
|
||||
"win10-x64": {},
|
||||
"win10-x64-aot": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user