Merge pull request #1414 from IbrahimSulai/master

Support for displaying controls in Android Exoplayer
This commit is contained in:
Hampton Maxwell 2019-02-10 18:20:01 -08:00 committed by GitHub
commit e0fd69e9f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 178 additions and 2 deletions

View File

@ -359,9 +359,9 @@ Determines whether to show player controls.
Note on iOS, controls are always shown when in fullscreen mode. Note on iOS, controls are always shown when in fullscreen mode.
Controls are not available Android because the system does not provide a stock set of controls. You will need to build your own or use a package like [react-native-video-controls](https://github.com/itsnubix/react-native-video-controls) or [react-native-video-player](https://github.com/cornedor/react-native-video-player). For Android MediaPlayer, you will need to build your own controls or use a package like [react-native-video-controls](https://github.com/itsnubix/react-native-video-controls) or [react-native-video-player](https://github.com/cornedor/react-native-video-player).
Platforms: iOS, react-native-dom Platforms: Android ExoPlayer, iOS, react-native-dom
#### filter #### filter
Add video filter Add video filter

View File

@ -64,6 +64,7 @@ import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.ui.PlayerControlView;
import java.net.CookieHandler; import java.net.CookieHandler;
import java.net.CookieManager; import java.net.CookieManager;
@ -96,6 +97,9 @@ class ReactExoplayerView extends FrameLayout implements
} }
private final VideoEventEmitter eventEmitter; private final VideoEventEmitter eventEmitter;
private PlayerControlView playerControlView;
private View playPauseControlContainer;
private Player.EventListener eventListener;
private Handler mainHandler; private Handler mainHandler;
private ExoPlayerView exoPlayerView; private ExoPlayerView exoPlayerView;
@ -257,6 +261,76 @@ class ReactExoplayerView extends FrameLayout implements
} }
// Internal methods // Internal methods
/**
* Toggling the visibility of the player control view
*/
private void togglePlayerControlVisibility() {
reLayout(playerControlView);
if (playerControlView.isVisible()) {
playerControlView.hide();
} else {
playerControlView.show();
}
}
/**
* Initializing Player control
*/
private void initializePlayerControl() {
if (playerControlView == null) {
playerControlView = new PlayerControlView(getContext());
}
// Setting the player for the playerControlView
playerControlView.setPlayer(player);
playerControlView.show();
playPauseControlContainer = playerControlView.findViewById(R.id.exo_play_pause_container);
// Invoking onClick event for exoplayerView
exoPlayerView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
togglePlayerControlVisibility();
}
});
// Invoking onPlayerStateChanged event for Player
eventListener = new Player.EventListener() {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
reLayout(playPauseControlContainer);
//Remove this eventListener once its executed. since UI will work fine once after the reLayout is done
player.removeListener(eventListener);
}
};
player.addListener(eventListener);
}
/**
* Adding Player control to the frame layout
*/
private void addPlayerControl() {
LayoutParams layoutParams = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
playerControlView.setLayoutParams(layoutParams);
addView(playerControlView, 1, layoutParams);
}
/**
* Update the layout
* @param view view needs to update layout
*
* This is a workaround for the open bug in react-native: https://github.com/facebook/react-native/issues/17968
*/
private void reLayout(View view) {
if (view == null) return;
view.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
view.layout(view.getLeft(), view.getTop(), view.getMeasuredWidth(), view.getMeasuredHeight());
}
private void initializePlayer() { private void initializePlayer() {
if (player == null) { if (player == null) {
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER); TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
@ -302,6 +376,9 @@ class ReactExoplayerView extends FrameLayout implements
eventEmitter.loadStart(); eventEmitter.loadStart();
loadVideoStarted = true; loadVideoStarted = true;
} }
// Initializing the playerControlView
initializePlayerControl();
} }
private MediaSource buildMediaSource(Uri uri, String overrideExtension) { private MediaSource buildMediaSource(Uri uri, String overrideExtension) {
@ -517,6 +594,10 @@ class ReactExoplayerView extends FrameLayout implements
onBuffering(false); onBuffering(false);
startProgressHandler(); startProgressHandler();
videoLoaded(); videoLoaded();
//Setting the visibility for the playerControlView
if(playerControlView != null) {
playerControlView.show();
}
break; break;
case ExoPlayer.STATE_ENDED: case ExoPlayer.STATE_ENDED:
text += "ended"; text += "ended";
@ -1056,4 +1137,17 @@ class ReactExoplayerView extends FrameLayout implements
releasePlayer(); releasePlayer();
initializePlayer(); initializePlayer();
} }
/**
* Handling controls prop
*
* @param controls Controls prop, if true enable controls, if false disable them
*/
public void setControls(boolean controls) {
if (controls && exoPlayerView != null) {
addPlayerControl();
} else if (getChildAt(1) instanceof PlayerControlView && exoPlayerView != null) {
removeViewAt(1);
}
}
} }

View File

@ -57,6 +57,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
private static final String PROP_SELECTED_VIDEO_TRACK_TYPE = "type"; private static final String PROP_SELECTED_VIDEO_TRACK_TYPE = "type";
private static final String PROP_SELECTED_VIDEO_TRACK_VALUE = "value"; private static final String PROP_SELECTED_VIDEO_TRACK_VALUE = "value";
private static final String PROP_HIDE_SHUTTER_VIEW = "hideShutterView"; private static final String PROP_HIDE_SHUTTER_VIEW = "hideShutterView";
private static final String PROP_CONTROLS = "controls";
@Override @Override
public String getName() { public String getName() {
@ -255,6 +256,11 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
videoView.setHideShutterView(hideShutterView); videoView.setHideShutterView(hideShutterView);
} }
@ReactProp(name = PROP_CONTROLS, defaultBoolean = false)
public void setControls(final ReactExoplayerView videoView, final boolean controls) {
videoView.setControls(controls);
}
@ReactProp(name = PROP_BUFFER_CONFIG) @ReactProp(name = PROP_BUFFER_CONFIG)
public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) { public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) {
int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS; int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layoutDirection="ltr"
android:background="#CC000000"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingTop="4dp"
android:orientation="horizontal">
<ImageButton android:id="@id/exo_prev"
style="@style/ExoMediaButton.Previous"/>
<ImageButton android:id="@id/exo_rew"
style="@style/ExoMediaButton.Rewind"/>
<FrameLayout
android:id="@+id/exo_play_pause_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<ImageButton android:id="@id/exo_play"
style="@style/ExoMediaButton.Play"/>
<ImageButton android:id="@id/exo_pause"
style="@style/ExoMediaButton.Pause"/>
</FrameLayout>
<ImageButton android:id="@id/exo_ffwd"
style="@style/ExoMediaButton.FastForward"/>
<ImageButton android:id="@id/exo_next"
style="@style/ExoMediaButton.Next"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView android:id="@id/exo_position"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textStyle="bold"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:includeFontPadding="false"
android:textColor="#FFBEBEBE"/>
<com.google.android.exoplayer2.ui.DefaultTimeBar
android:id="@id/exo_progress"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="26dp"/>
<TextView android:id="@id/exo_duration"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textStyle="bold"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:includeFontPadding="false"
android:textColor="#FFBEBEBE"/>
</LinearLayout>
</LinearLayout>