From 4cc9a4d3748aa7b7bcf76bf53c3ab93388d2b86f Mon Sep 17 00:00:00 2001 From: Ibrahim Sulaiman Date: Fri, 4 Jan 2019 14:58:32 +0530 Subject: [PATCH 1/9] Support for controls in android exoplayer --- .../exoplayer/ReactExoplayerView.java | 55 +++++++++++++++++++ .../exoplayer/ReactExoplayerViewManager.java | 6 ++ 2 files changed, 61 insertions(+) diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 64c8a4043f..1c80c90945 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -64,6 +64,8 @@ import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; +//Import PlayerControlView +import com.google.android.exoplayer2.ui.PlayerControlView; import java.net.CookieHandler; import java.net.CookieManager; @@ -96,6 +98,8 @@ class ReactExoplayerView extends FrameLayout implements } private final VideoEventEmitter eventEmitter; + //Create playerControlView instance + private PlayerControlView playerControlView; private Handler mainHandler; private ExoPlayerView exoPlayerView; @@ -257,6 +261,41 @@ public void onBandwidthSample(int elapsedMs, long bytes, long bitrate) { } // Internal methods + + /** + * Toggling the visibility of the player control view + */ + private void togglePlayerControlVisibility() { + if(playerControlView.isVisible()) { + playerControlView.setVisibility(INVISIBLE); + } else { + playerControlView.setVisibility(VISIBLE); + } + } + + /** + * Initialising Player control + */ + private void initialisePlayerControl() { + playerControlView = new PlayerControlView(getContext()); + LayoutParams layoutParams = new LayoutParams( + LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT); + playerControlView.setLayoutParams(layoutParams); + addView(playerControlView, 1, layoutParams); + + //Setting the player for the playerControlView + playerControlView.setPlayer(player); + + //Invoking onClick event for exoplayerView + exoPlayerView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + togglePlayerControlVisibility(); + } + }); + } + private void initializePlayer() { if (player == null) { TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER); @@ -517,6 +556,10 @@ public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { onBuffering(false); startProgressHandler(); videoLoaded(); + //Setting the visibility for the playerControlView + if(playerControlView != null) { + playerControlView.setVisibility(VISIBLE); + } break; case ExoPlayer.STATE_ENDED: text += "ended"; @@ -1056,4 +1099,16 @@ public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBuffe releasePlayer(); initializePlayer(); } + + /** + * Handling controls prop + * + * @param controls value of the controls prop passed from react-native + */ + public void setControls(boolean controls) { + if(controls && (exoPlayerView != null)) { + //Initialise playerControlView + initialisePlayerControl(); + } + } } diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java index 31bd8e08be..b3c6ad12f5 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java @@ -57,6 +57,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager Date: Fri, 4 Jan 2019 15:31:49 +0530 Subject: [PATCH 2/9] Updated README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ee34399ce..708afab454 100644 --- a/README.md +++ b/README.md @@ -361,7 +361,7 @@ 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). -Platforms: iOS, react-native-dom +Platforms: iOS, Android, react-native-dom #### filter Add video filter From e05c1c3c64c547439dc23f4c233e8ac537e2d8ac Mon Sep 17 00:00:00 2001 From: Ibrahim Sulaiman Date: Wed, 16 Jan 2019 23:47:32 +0530 Subject: [PATCH 3/9] Resolved the review comments --- README.md | 2 +- .../com/brentvatne/exoplayer/ReactExoplayerView.java | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 708afab454..546244cd45 100644 --- a/README.md +++ b/README.md @@ -361,7 +361,7 @@ 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). -Platforms: iOS, Android, react-native-dom +Platforms: iOS, Android ExoPlayer, react-native-dom #### filter Add video filter diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 1c80c90945..3d500d1726 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -64,7 +64,6 @@ import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; -//Import PlayerControlView import com.google.android.exoplayer2.ui.PlayerControlView; import java.net.CookieHandler; @@ -98,7 +97,6 @@ class ReactExoplayerView extends FrameLayout implements } private final VideoEventEmitter eventEmitter; - //Create playerControlView instance private PlayerControlView playerControlView; private Handler mainHandler; @@ -274,9 +272,9 @@ private void togglePlayerControlVisibility() { } /** - * Initialising Player control + * Initializing Player control */ - private void initialisePlayerControl() { + private void initializePlayerControl() { playerControlView = new PlayerControlView(getContext()); LayoutParams layoutParams = new LayoutParams( LayoutParams.MATCH_PARENT, @@ -1107,8 +1105,8 @@ public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBuffe */ public void setControls(boolean controls) { if(controls && (exoPlayerView != null)) { - //Initialise playerControlView - initialisePlayerControl(); + //Initialize playerControlView + initializePlayerControl(); } } } From debc0cb3c60d1ac54218093dc06a92a7417ff3d0 Mon Sep 17 00:00:00 2001 From: Ibrahim Sulaiman Date: Fri, 25 Jan 2019 15:54:53 +0530 Subject: [PATCH 4/9] Resolved the playercontrol UI issue and also handled the controls prop state --- .../exoplayer/ReactExoplayerView.java | 11 ++- .../res/layout/exo_player_control_view.xml | 75 +++++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 android-exoplayer/src/main/res/layout/exo_player_control_view.xml diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 3d500d1726..e491ccb4c7 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -275,7 +275,9 @@ private void togglePlayerControlVisibility() { * Initializing Player control */ private void initializePlayerControl() { - playerControlView = new PlayerControlView(getContext()); + if(playerControlView == null) { + playerControlView = new PlayerControlView(getContext()); + } LayoutParams layoutParams = new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); @@ -284,6 +286,7 @@ private void initializePlayerControl() { //Setting the player for the playerControlView playerControlView.setPlayer(player); + playerControlView.setVisibility(VISIBLE); //Invoking onClick event for exoplayerView exoPlayerView.setOnClickListener(new OnClickListener() { @@ -1104,9 +1107,13 @@ public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBuffe * @param controls value of the controls prop passed from react-native */ public void setControls(boolean controls) { - if(controls && (exoPlayerView != null)) { + if(controls && (exoPlayerView != null)) { //Initialize playerControlView initializePlayerControl(); + } else { + if(getChildAt(1) instanceof PlayerControlView && (exoPlayerView != null)){ + removeViewAt(1); + } } } } diff --git a/android-exoplayer/src/main/res/layout/exo_player_control_view.xml b/android-exoplayer/src/main/res/layout/exo_player_control_view.xml new file mode 100644 index 0000000000..54b38ad7e7 --- /dev/null +++ b/android-exoplayer/src/main/res/layout/exo_player_control_view.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From c156550518a50d6c3dca77487dfdb02bb59cb494 Mon Sep 17 00:00:00 2001 From: Ibrahim Sulaiman Date: Mon, 28 Jan 2019 14:50:51 +0530 Subject: [PATCH 5/9] Used default playerControlView's API to show and hide controls --- .../java/com/brentvatne/exoplayer/ReactExoplayerView.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index e491ccb4c7..484265f6b7 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -265,9 +265,9 @@ public void onBandwidthSample(int elapsedMs, long bytes, long bitrate) { */ private void togglePlayerControlVisibility() { if(playerControlView.isVisible()) { - playerControlView.setVisibility(INVISIBLE); + playerControlView.hide(); } else { - playerControlView.setVisibility(VISIBLE); + playerControlView.show(); } } @@ -286,7 +286,7 @@ private void initializePlayerControl() { //Setting the player for the playerControlView playerControlView.setPlayer(player); - playerControlView.setVisibility(VISIBLE); + playerControlView.show(); //Invoking onClick event for exoplayerView exoPlayerView.setOnClickListener(new OnClickListener() { @@ -559,7 +559,7 @@ public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { videoLoaded(); //Setting the visibility for the playerControlView if(playerControlView != null) { - playerControlView.setVisibility(VISIBLE); + playerControlView.show(); } break; case ExoPlayer.STATE_ENDED: From 1430dc7fea624dd42b8779c278fec152f42b70d3 Mon Sep 17 00:00:00 2001 From: Ibrahim Sulaiman Date: Mon, 4 Feb 2019 19:18:29 +0530 Subject: [PATCH 6/9] Fix for play and pause button UI issue --- .../exoplayer/ReactExoplayerView.java | 27 +++++++++++++++++++ .../res/layout/exo_player_control_view.xml | 1 + 2 files changed, 28 insertions(+) diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 484265f6b7..f72e4304ff 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -98,6 +98,8 @@ class ReactExoplayerView extends FrameLayout implements private final VideoEventEmitter eventEmitter; private PlayerControlView playerControlView; + private View playPauseControlContainer; + private Player.EventListener eventListener; private Handler mainHandler; private ExoPlayerView exoPlayerView; @@ -264,6 +266,7 @@ public void onBandwidthSample(int elapsedMs, long bytes, long bitrate) { * Toggling the visibility of the player control view */ private void togglePlayerControlVisibility() { + reLayout(playerControlView); if(playerControlView.isVisible()) { playerControlView.hide(); } else { @@ -287,6 +290,7 @@ private void initializePlayerControl() { //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() { @@ -295,6 +299,29 @@ 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); + player.removeListener(eventListener); + } + }; + player.addListener(eventListener); + } + + /** + * Update the layout + * + * This is a workaround for the open bug in react-native: https://github.com/facebook/react-native/issues/17968 + * @param view view needs to update layout + */ + 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() { diff --git a/android-exoplayer/src/main/res/layout/exo_player_control_view.xml b/android-exoplayer/src/main/res/layout/exo_player_control_view.xml index 54b38ad7e7..becee6a901 100644 --- a/android-exoplayer/src/main/res/layout/exo_player_control_view.xml +++ b/android-exoplayer/src/main/res/layout/exo_player_control_view.xml @@ -20,6 +20,7 @@ From bd8aa99645b758871ffacefb524122b086e5eb12 Mon Sep 17 00:00:00 2001 From: Ibrahim Sulaiman Date: Wed, 6 Feb 2019 03:22:06 +0530 Subject: [PATCH 7/9] Changed the execution order of initializePlayerControl method in order to align with player state --- .../exoplayer/ReactExoplayerView.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index f72e4304ff..4a396a2b32 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -281,11 +281,6 @@ private void initializePlayerControl() { if(playerControlView == null) { playerControlView = new PlayerControlView(getContext()); } - LayoutParams layoutParams = new LayoutParams( - LayoutParams.MATCH_PARENT, - LayoutParams.MATCH_PARENT); - playerControlView.setLayoutParams(layoutParams); - addView(playerControlView, 1, layoutParams); //Setting the player for the playerControlView playerControlView.setPlayer(player); @@ -305,12 +300,24 @@ public void onClick(View v) { @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 * @@ -369,6 +376,9 @@ private void initializePlayer() { eventEmitter.loadStart(); loadVideoStarted = true; } + + //Initializing the playerControlView + initializePlayerControl(); } private MediaSource buildMediaSource(Uri uri, String overrideExtension) { @@ -1135,8 +1145,8 @@ public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBuffe */ public void setControls(boolean controls) { if(controls && (exoPlayerView != null)) { - //Initialize playerControlView - initializePlayerControl(); + //adding the playerControlView + addPlayerControl(); } else { if(getChildAt(1) instanceof PlayerControlView && (exoPlayerView != null)){ removeViewAt(1); From c361b795fc4f3de9eecce397db1f83b02663073d Mon Sep 17 00:00:00 2001 From: Hampton Maxwell Date: Sun, 10 Feb 2019 18:06:49 -0800 Subject: [PATCH 8/9] Cleanup controls comment --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 546244cd45..6593f12ef9 100644 --- a/README.md +++ b/README.md @@ -359,9 +359,9 @@ Determines whether to show player controls. 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, Android ExoPlayer, react-native-dom +Platforms: Android ExoPlayer, iOS, react-native-dom #### filter Add video filter From 40803496f956740648ae322b5948414c4f580c57 Mon Sep 17 00:00:00 2001 From: Hampton Maxwell Date: Sun, 10 Feb 2019 18:15:30 -0800 Subject: [PATCH 9/9] Code formatting cleanups for controls --- .../exoplayer/ReactExoplayerView.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java index 4a396a2b32..2ecd605e20 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -267,7 +267,7 @@ public void onBandwidthSample(int elapsedMs, long bytes, long bitrate) { */ private void togglePlayerControlVisibility() { reLayout(playerControlView); - if(playerControlView.isVisible()) { + if (playerControlView.isVisible()) { playerControlView.hide(); } else { playerControlView.show(); @@ -278,16 +278,16 @@ private void togglePlayerControlVisibility() { * Initializing Player control */ private void initializePlayerControl() { - if(playerControlView == null) { + if (playerControlView == null) { playerControlView = new PlayerControlView(getContext()); } - //Setting the player for the playerControlView + // 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 + // Invoking onClick event for exoplayerView exoPlayerView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -295,7 +295,7 @@ public void onClick(View v) { } }); - //Invoking onPlayerStateChanged event for Player + // Invoking onPlayerStateChanged event for Player eventListener = new Player.EventListener() { @Override public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { @@ -320,12 +320,12 @@ private void addPlayerControl() { /** * 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 - * @param view view needs to update layout */ private void reLayout(View view) { - if(view == null) return; + 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()); @@ -377,7 +377,7 @@ private void initializePlayer() { loadVideoStarted = true; } - //Initializing the playerControlView + // Initializing the playerControlView initializePlayerControl(); } @@ -1141,16 +1141,13 @@ public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBuffe /** * Handling controls prop * - * @param controls value of the controls prop passed from react-native + * @param controls Controls prop, if true enable controls, if false disable them */ public void setControls(boolean controls) { - if(controls && (exoPlayerView != null)) { - //adding the playerControlView - addPlayerControl(); - } else { - if(getChildAt(1) instanceof PlayerControlView && (exoPlayerView != null)){ - removeViewAt(1); - } + if (controls && exoPlayerView != null) { + addPlayerControl(); + } else if (getChildAt(1) instanceof PlayerControlView && exoPlayerView != null) { + removeViewAt(1); } } }