VEX-3245: Buffer Progress UI While Paused (#7)

Add support for onBufferProgress prop on Android to get buffer data even when the player is paused.
This commit is contained in:
Armands Malejev 2021-07-07 18:59:55 +03:00 committed by GitHub
parent cba88fa9d8
commit 93604b2c25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 0 deletions

View File

@ -1,5 +1,7 @@
## Changelog ## Changelog
- Add support for `onBufferProgress` on Android for getting buffer data even when the player is paused
- Fix Android AudioFocus bug that could cause player to not respond to play/pause in some instances [#2311](https://github.com/react-native-video/react-native-video/pull/2311) - Fix Android AudioFocus bug that could cause player to not respond to play/pause in some instances [#2311](https://github.com/react-native-video/react-native-video/pull/2311)
### Version 5.1.0-alpha9 ### Version 5.1.0-alpha9

View File

@ -321,6 +321,7 @@ var styles = StyleSheet.create({
### Event props ### Event props
* [onAudioBecomingNoisy](#onaudiobecomingnoisy) * [onAudioBecomingNoisy](#onaudiobecomingnoisy)
* [onBandwidthUpdate](#onbandwidthupdate) * [onBandwidthUpdate](#onbandwidthupdate)
* [onBufferProgress](#onbufferprogress)
* [onEnd](#onend) * [onEnd](#onend)
* [onExternalPlaybackChange](#onexternalplaybackchange) * [onExternalPlaybackChange](#onexternalplaybackchange)
* [onFullscreenPlayerWillPresent](#onfullscreenplayerwillpresent) * [onFullscreenPlayerWillPresent](#onfullscreenplayerwillpresent)
@ -944,6 +945,18 @@ Note: On Android ExoPlayer, you must set the [reportBandwidth](#reportbandwidth)
Platforms: Android ExoPlayer Platforms: Android ExoPlayer
#### onBufferProgress
Callback function that is called on a set interval which contains the buffer start and end position in ms.
Payload:
Property | Type | Description
--- | --- | ---
start | number | The buffer start (ms)
end | number | The buffer end (ms)
Platforms: Android ExoPlayer
#### onEnd #### onEnd
Callback function that is called when the player reaches the end of the media. Callback function that is called when the player reaches the end of the media.

View File

@ -233,6 +233,12 @@ export default class Video extends Component {
} }
}; };
_onBufferProgress = (event) => {
if (this.props.onBufferProgress) {
this.props.onBufferProgress(event.nativeEvent);
}
};
_onGetLicense = (event) => { _onGetLicense = (event) => {
if (this.props.drm && this.props.drm.getLicense instanceof Function) { if (this.props.drm && this.props.drm.getLicense instanceof Function) {
const data = event.nativeEvent; const data = event.nativeEvent;
@ -311,6 +317,7 @@ export default class Video extends Component {
onVideoSeek: this._onSeek, onVideoSeek: this._onSeek,
onVideoEnd: this._onEnd, onVideoEnd: this._onEnd,
onVideoBuffer: this._onBuffer, onVideoBuffer: this._onBuffer,
onVideoBufferProgress: this._onBufferProgress,
onVideoBandwidthUpdate: this._onBandwidthUpdate, onVideoBandwidthUpdate: this._onBandwidthUpdate,
onTimedMetadata: this._onTimedMetadata, onTimedMetadata: this._onTimedMetadata,
onVideoAudioBecomingNoisy: this._onAudioBecomingNoisy, onVideoAudioBecomingNoisy: this._onAudioBecomingNoisy,

View File

@ -81,6 +81,8 @@ import java.util.ArrayList;
import java.util.Locale; import java.util.Locale;
import java.util.UUID; import java.util.UUID;
import java.util.Map; import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
class ReactExoplayerView extends FrameLayout implements class ReactExoplayerView extends FrameLayout implements
@ -137,6 +139,7 @@ class ReactExoplayerView extends FrameLayout implements
private int bufferForPlaybackAfterRebufferMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS; private int bufferForPlaybackAfterRebufferMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS;
private Handler mainHandler; private Handler mainHandler;
private Timer bufferCheckTimer;
// Props from React // Props from React
private int backBufferDurationMs = DefaultLoadControl.DEFAULT_BACK_BUFFER_DURATION_MS; private int backBufferDurationMs = DefaultLoadControl.DEFAULT_BACK_BUFFER_DURATION_MS;
@ -415,6 +418,40 @@ class ReactExoplayerView extends FrameLayout implements
} }
} }
private void startBufferCheckTimer() {
SimpleExoPlayer player = this.player;
VideoEventEmitter eventEmitter = this.eventEmitter;
Handler mainHandler = this.mainHandler;
if (this.bufferCheckTimer != null) {
this.stopBufferCheckTimer();
}
this.bufferCheckTimer = new Timer();
TimerTask bufferCheckTimerTask = new TimerTask() {
@Override
public void run() {
if (mainHandler != null) {
mainHandler.post(new Runnable() {
public void run() {
if (player != null) {
double bufferedDuration = (double) (player.getBufferedPercentage() * player.getDuration() / 100);
eventEmitter.bufferProgress(0d, bufferedDuration);
}
}
});
}
};
};
this.bufferCheckTimer.scheduleAtFixedRate(bufferCheckTimerTask, 500, 1000);
}
private void stopBufferCheckTimer() {
this.bufferCheckTimer.cancel();
this.bufferCheckTimer = null;
}
private void initializePlayer() { private void initializePlayer() {
ReactExoplayerView self = this; ReactExoplayerView self = this;
// This ensures all props have been settled, to avoid async racing conditions. // This ensures all props have been settled, to avoid async racing conditions.
@ -506,6 +543,7 @@ class ReactExoplayerView extends FrameLayout implements
initializePlayerControl(); initializePlayerControl();
setControls(controls); setControls(controls);
applyModifiers(); applyModifiers();
startBufferCheckTimer();
} }
}, 1); }, 1);
} }
@ -597,6 +635,7 @@ class ReactExoplayerView extends FrameLayout implements
private void releasePlayer() { private void releasePlayer() {
if (player != null) { if (player != null) {
stopBufferCheckTimer();
updateResumePosition(); updateResumePosition();
player.release(); player.release();
player.removeMetadataOutput(this); player.removeMetadataOutput(this);

View File

@ -42,6 +42,7 @@ class VideoEventEmitter {
private static final String EVENT_RESUME = "onPlaybackResume"; private static final String EVENT_RESUME = "onPlaybackResume";
private static final String EVENT_READY = "onReadyForDisplay"; private static final String EVENT_READY = "onReadyForDisplay";
private static final String EVENT_BUFFER = "onVideoBuffer"; private static final String EVENT_BUFFER = "onVideoBuffer";
private static final String EVENT_BUFFER_PROGRESS = "onVideoBufferProgress";
private static final String EVENT_IDLE = "onVideoIdle"; private static final String EVENT_IDLE = "onVideoIdle";
private static final String EVENT_TIMED_METADATA = "onTimedMetadata"; private static final String EVENT_TIMED_METADATA = "onTimedMetadata";
private static final String EVENT_AUDIO_BECOMING_NOISY = "onVideoAudioBecomingNoisy"; private static final String EVENT_AUDIO_BECOMING_NOISY = "onVideoAudioBecomingNoisy";
@ -63,6 +64,7 @@ class VideoEventEmitter {
EVENT_RESUME, EVENT_RESUME,
EVENT_READY, EVENT_READY,
EVENT_BUFFER, EVENT_BUFFER,
EVENT_BUFFER_PROGRESS,
EVENT_IDLE, EVENT_IDLE,
EVENT_TIMED_METADATA, EVENT_TIMED_METADATA,
EVENT_AUDIO_BECOMING_NOISY, EVENT_AUDIO_BECOMING_NOISY,
@ -87,6 +89,7 @@ class VideoEventEmitter {
EVENT_RESUME, EVENT_RESUME,
EVENT_READY, EVENT_READY,
EVENT_BUFFER, EVENT_BUFFER,
EVENT_BUFFER_PROGRESS,
EVENT_IDLE, EVENT_IDLE,
EVENT_TIMED_METADATA, EVENT_TIMED_METADATA,
EVENT_AUDIO_BECOMING_NOISY, EVENT_AUDIO_BECOMING_NOISY,
@ -104,6 +107,8 @@ class VideoEventEmitter {
private static final String EVENT_PROP_STEP_FORWARD = "canStepForward"; private static final String EVENT_PROP_STEP_FORWARD = "canStepForward";
private static final String EVENT_PROP_STEP_BACKWARD = "canStepBackward"; private static final String EVENT_PROP_STEP_BACKWARD = "canStepBackward";
private static final String EVENT_PROP_BUFFER_START = "bufferStart";
private static final String EVENT_PROP_BUFFER_END = "bufferEnd";
private static final String EVENT_PROP_DURATION = "duration"; private static final String EVENT_PROP_DURATION = "duration";
private static final String EVENT_PROP_PLAYABLE_DURATION = "playableDuration"; private static final String EVENT_PROP_PLAYABLE_DURATION = "playableDuration";
private static final String EVENT_PROP_SEEKABLE_DURATION = "seekableDuration"; private static final String EVENT_PROP_SEEKABLE_DURATION = "seekableDuration";
@ -206,6 +211,13 @@ class VideoEventEmitter {
receiveEvent(EVENT_BUFFER, map); receiveEvent(EVENT_BUFFER, map);
} }
void bufferProgress(double start, double end) {
WritableMap map = Arguments.createMap();
map.putDouble(EVENT_PROP_BUFFER_START, start);
map.putDouble(EVENT_PROP_BUFFER_END, end);
receiveEvent(EVENT_BUFFER_PROGRESS, map);
}
void idle() { void idle() {
receiveEvent(EVENT_IDLE, null); receiveEvent(EVENT_IDLE, null);
} }