From 94bceb472bce35b08e04b2e93bb0c11096ce30fe Mon Sep 17 00:00:00 2001 From: Tuan Luong Date: Sat, 4 Jul 2020 17:41:15 +0700 Subject: [PATCH 01/31] add fullscreen activity --- .../ExoPlayerFullscreenVideoActivity.java | 107 ++++++++++++++++++ .../brentvatne/exoplayer/ExoPlayerView.java | 3 - .../exoplayer/ReactExoplayerView.java | 91 ++++++++++----- .../res/layout/exo_player_control_view.xml | 19 +++- .../layout/exo_player_fullscreen_video.xml | 18 +++ android/src/main/AndroidManifest.xml | 8 +- 6 files changed, 211 insertions(+), 35 deletions(-) create mode 100644 android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java create mode 100644 android-exoplayer/src/main/res/layout/exo_player_fullscreen_video.xml diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java new file mode 100644 index 00000000..1f2ee1d5 --- /dev/null +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java @@ -0,0 +1,107 @@ +package com.brentvatne.exoplayer; + +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; + +import androidx.appcompat.app.AppCompatActivity; + +import com.brentvatne.react.R; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.ui.PlayerControlView; + +public class ExoPlayerFullscreenVideoActivity extends AppCompatActivity implements ReactExoplayerView.FullScreenDelegate { + public static final String EXTRA_ID = "extra_id"; + public static final String EXTRA_IS_PLAYING = "extra_is_playing"; + + private int id; + private PlayerControlView playerControlView; + private SimpleExoPlayer player; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.exo_player_fullscreen_video); + id = getIntent().getIntExtra(EXTRA_ID, -1); + player = ReactExoplayerView.getViewInstance(id).getPlayer(); + + ExoPlayerView playerView = findViewById(R.id.player_view); + playerView.setPlayer(player); + playerView.setOnClickListener(v -> togglePlayerControlVisibility()); + + playerControlView = findViewById(R.id.player_controls); + playerControlView.setPlayer(player); + // Set the fullscreen button to "close fullscreen" icon + ImageView fullscreenIcon = playerControlView.findViewById(R.id.exo_fullscreen_icon); + fullscreenIcon.setImageResource(R.drawable.exo_controls_fullscreen_exit); + playerControlView.findViewById(R.id.exo_fullscreen_button) + .setOnClickListener(v -> finish()); + } + + @Override + public void onResume() { + super.onResume(); + boolean isPlaying = getIntent().getBooleanExtra(EXTRA_IS_PLAYING, false); + player.setPlayWhenReady(isPlaying); + ReactExoplayerView.getViewInstance(id).registerFullScreenDelegate(this); + } + + @Override + public void onPause() { + super.onPause(); + boolean isPlaying = player.getPlayWhenReady() && player.getPlaybackState() == Player.STATE_READY; + ReactExoplayerView.getViewInstance(id).setPausedModifier(!isPlaying); + player.setPlayWhenReady(false); + ReactExoplayerView.getViewInstance(id).registerFullScreenDelegate(null); + } + + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + if (hasFocus) { + hideSystemUI(); + } + } + + private void togglePlayerControlVisibility() { + if (playerControlView.isVisible()) { + playerControlView.hide(); + } else { + playerControlView.show(); + } + } + + /** + * Enables regular immersive mode. + */ + private void hideSystemUI() { + View decorView = getWindow().getDecorView(); + decorView.setSystemUiVisibility( + View.SYSTEM_UI_FLAG_IMMERSIVE + // Set the content to appear under the system bars so that the + // content doesn't resize when the system bars hide and show. + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + // Hide the nav bar and status bar + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_FULLSCREEN); + } + + /** + * Shows the system bars by removing all the flags + * except for the ones that make the content appear under the system bars. + */ + private void showSystemUI() { + View decorView = getWindow().getDecorView(); + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + } + + @Override + public void closeFullScreen() { + finish(); + } +} diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java index afa5106c..1a244f29 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java @@ -120,9 +120,6 @@ public final class ExoPlayerView extends FrameLayout { * @param player The {@link SimpleExoPlayer} to use. */ public void setPlayer(SimpleExoPlayer player) { - if (this.player == player) { - return; - } if (this.player != null) { this.player.setTextOutput(null); this.player.setVideoListener(null); 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 4e6fea58..6cd6b844 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -1,8 +1,8 @@ package com.brentvatne.exoplayer; import android.annotation.SuppressLint; -import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.media.AudioManager; import android.net.Uri; import android.os.Handler; @@ -10,10 +10,12 @@ import android.os.Message; import android.text.TextUtils; import android.util.Log; import android.view.View; -import android.view.Window; import android.view.accessibility.CaptioningManager; import android.widget.FrameLayout; -import android.widget.ImageButton; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentTransaction; import com.brentvatne.react.R; import com.brentvatne.receiver.AudioBecomingNoisyReceiver; @@ -25,28 +27,33 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; +import com.facebook.react.modules.timepicker.TimePickerDialogFragment; +import com.facebook.react.uimanager.NativeViewHierarchyManager; import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.UIBlock; +import com.facebook.react.uimanager.UIManagerModule; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultLoadControl; -import com.google.android.exoplayer2.DefaultRenderersFactory; import com.google.android.exoplayer2.ExoPlaybackException; +import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayerFactory; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; +import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil; import com.google.android.exoplayer2.metadata.Metadata; -import com.google.android.exoplayer2.metadata.MetadataOutput; +import com.google.android.exoplayer2.metadata.MetadataRenderer; import com.google.android.exoplayer2.source.BehindLiveWindowException; +import com.google.android.exoplayer2.source.ExtractorMediaSource; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MergingMediaSource; -import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.source.SingleSampleMediaSource; -import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; +import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.dash.DashMediaSource; import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource; import com.google.android.exoplayer2.source.hls.HlsMediaSource; @@ -57,17 +64,20 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; 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.ui.PlayerControlView; -import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DefaultAllocator; +import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; -import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.util.Util; +import com.google.android.exoplayer2.ui.PlayerControlView; import java.net.CookieHandler; import java.net.CookieManager; import java.net.CookiePolicy; +import java.lang.Math; +import java.util.HashMap; +import java.util.Map; +import java.lang.Object; import java.util.ArrayList; import java.util.Locale; import java.util.Map; @@ -91,6 +101,11 @@ class ReactExoplayerView extends FrameLayout implements DEFAULT_COOKIE_MANAGER.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER); } + private static Map instances = new HashMap<>(); + private static int UNIQUE_ID = 0; + private int uid = ++UNIQUE_ID; + private FullScreenDelegate fullScreenDelegate; + private final VideoEventEmitter eventEmitter; private final ReactExoplayerConfig config; private final DefaultBandwidthMeter bandwidthMeter; @@ -187,7 +202,6 @@ class ReactExoplayerView extends FrameLayout implements createViews(); audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - themedReactContext.addLifecycleEventListener(this); audioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver(themedReactContext); initializePlayer(); @@ -235,6 +249,7 @@ class ReactExoplayerView extends FrameLayout implements @Override public void onHostResume() { + exoPlayerView.setPlayer(player); if (!playInBackground || !isInBackground) { setPlayWhenReady(!isPaused); } @@ -275,6 +290,22 @@ class ReactExoplayerView extends FrameLayout implements } } + public static ReactExoplayerView getViewInstance(Integer uid) { + return instances.get(uid); + } + + public SimpleExoPlayer getPlayer() { + return player; + } + + public boolean isPaused() { + return isPaused; + } + + public void registerFullScreenDelegate(FullScreenDelegate delegate) { + this.fullScreenDelegate = delegate; + } + // Internal methods /** @@ -290,6 +321,15 @@ class ReactExoplayerView extends FrameLayout implements } } + private void showFullscreen() { + instances.put(uid, this); + Intent intent = new Intent(getContext(), ExoPlayerFullscreenVideoActivity.class); + intent.putExtra(ExoPlayerFullscreenVideoActivity.EXTRA_ID, this.uid); + boolean isPlaying = player.getPlayWhenReady() && player.getPlaybackState() == Player.STATE_READY; + intent.putExtra(ExoPlayerFullscreenVideoActivity.EXTRA_IS_PLAYING, isPlaying); + getContext().startActivity(intent); + } + /** * Initializing Player control */ @@ -302,6 +342,7 @@ class ReactExoplayerView extends FrameLayout implements playerControlView.setPlayer(player); playerControlView.show(); playPauseControlContainer = playerControlView.findViewById(R.id.exo_play_pause_container); + playerControlView.findViewById(R.id.exo_fullscreen_button).setOnClickListener(v -> showFullscreen()); // Invoking onClick event for exoplayerView exoPlayerView.setOnClickListener(new OnClickListener() { @@ -374,6 +415,7 @@ class ReactExoplayerView extends FrameLayout implements } private void initializePlayer() { + themedReactContext.addLifecycleEventListener(this); ReactExoplayerView self = this; // This ensures all props have been settled, to avoid async racing conditions. new Handler().postDelayed(new Runnable() { @@ -1217,30 +1259,15 @@ class ReactExoplayerView extends FrameLayout implements return; // Avoid generating events when nothing is changing } isFullscreen = fullscreen; - - Activity activity = themedReactContext.getCurrentActivity(); - if (activity == null) { - return; - } - Window window = activity.getWindow(); - View decorView = window.getDecorView(); - int uiOptions; if (isFullscreen) { - if (Util.SDK_INT >= 19) { // 4.4+ - uiOptions = SYSTEM_UI_FLAG_HIDE_NAVIGATION - | SYSTEM_UI_FLAG_IMMERSIVE_STICKY - | SYSTEM_UI_FLAG_FULLSCREEN; - } else { - uiOptions = SYSTEM_UI_FLAG_HIDE_NAVIGATION - | SYSTEM_UI_FLAG_FULLSCREEN; - } eventEmitter.fullscreenWillPresent(); - decorView.setSystemUiVisibility(uiOptions); + showFullscreen(); eventEmitter.fullscreenDidPresent(); } else { - uiOptions = View.SYSTEM_UI_FLAG_VISIBLE; eventEmitter.fullscreenWillDismiss(); - decorView.setSystemUiVisibility(uiOptions); + if (fullScreenDelegate != null) { + fullScreenDelegate.closeFullScreen(); + } eventEmitter.fullscreenDidDismiss(); } } @@ -1279,4 +1306,8 @@ class ReactExoplayerView extends FrameLayout implements } } } + + public interface FullScreenDelegate { + void closeFullScreen(); + } } 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 becee6a9..51cbf3a8 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 @@ -1,5 +1,6 @@ - + + + + + + diff --git a/android-exoplayer/src/main/res/layout/exo_player_fullscreen_video.xml b/android-exoplayer/src/main/res/layout/exo_player_fullscreen_video.xml new file mode 100644 index 00000000..671a00ee --- /dev/null +++ b/android-exoplayer/src/main/res/layout/exo_player_fullscreen_video.xml @@ -0,0 +1,18 @@ + + + + + + + \ No newline at end of file diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 3535ad44..2d632b3d 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,3 +1,9 @@ + package="com.brentvatne.react"> + + + + From 32880544e5aa7424067feefa6f947b3e0e5b6688 Mon Sep 17 00:00:00 2001 From: Tuan Luong Date: Sat, 4 Jul 2020 22:08:57 +0700 Subject: [PATCH 02/31] update manifest and import --- .../src/main/AndroidManifest.xml | 5 ++++ .../exoplayer/ReactExoplayerView.java | 28 ++++++------------- android/src/main/AndroidManifest.xml | 6 ---- 3 files changed, 14 insertions(+), 25 deletions(-) diff --git a/android-exoplayer/src/main/AndroidManifest.xml b/android-exoplayer/src/main/AndroidManifest.xml index 3535ad44..39515895 100644 --- a/android-exoplayer/src/main/AndroidManifest.xml +++ b/android-exoplayer/src/main/AndroidManifest.xml @@ -1,3 +1,8 @@ + + + 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 6cd6b844..5d546877 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -12,10 +12,7 @@ import android.util.Log; import android.view.View; import android.view.accessibility.CaptioningManager; import android.widget.FrameLayout; - -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentTransaction; +import android.widget.ImageButton; import com.brentvatne.react.R; import com.brentvatne.receiver.AudioBecomingNoisyReceiver; @@ -27,33 +24,28 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; -import com.facebook.react.modules.timepicker.TimePickerDialogFragment; -import com.facebook.react.uimanager.NativeViewHierarchyManager; import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.UIBlock; -import com.facebook.react.uimanager.UIManagerModule; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.DefaultLoadControl; +import com.google.android.exoplayer2.DefaultRenderersFactory; import com.google.android.exoplayer2.ExoPlaybackException; -import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayerFactory; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; -import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil; import com.google.android.exoplayer2.metadata.Metadata; -import com.google.android.exoplayer2.metadata.MetadataRenderer; +import com.google.android.exoplayer2.metadata.MetadataOutput; import com.google.android.exoplayer2.source.BehindLiveWindowException; -import com.google.android.exoplayer2.source.ExtractorMediaSource; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MergingMediaSource; +import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.source.SingleSampleMediaSource; -import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroup; +import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.dash.DashMediaSource; import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource; import com.google.android.exoplayer2.source.hls.HlsMediaSource; @@ -64,21 +56,19 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; 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.ui.PlayerControlView; +import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DefaultAllocator; -import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; +import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.util.Util; -import com.google.android.exoplayer2.ui.PlayerControlView; import java.net.CookieHandler; import java.net.CookieManager; import java.net.CookiePolicy; -import java.lang.Math; -import java.util.HashMap; -import java.util.Map; -import java.lang.Object; import java.util.ArrayList; +import java.util.HashMap; import java.util.Locale; import java.util.Map; diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 2d632b3d..42a828cc 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,9 +1,3 @@ - - - - From 0b7ea71d7707516c8c108f021f70477e962c7bcb Mon Sep 17 00:00:00 2001 From: Tuan Luong Date: Sun, 5 Jul 2020 11:00:25 +0700 Subject: [PATCH 03/31] update fullscreen activity --- .../src/main/AndroidManifest.xml | 3 +- .../ExoPlayerFullscreenVideoActivity.java | 35 +++++++++++++++---- .../exoplayer/ReactExoplayerView.java | 16 ++++++--- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/android-exoplayer/src/main/AndroidManifest.xml b/android-exoplayer/src/main/AndroidManifest.xml index 39515895..53e507e0 100644 --- a/android-exoplayer/src/main/AndroidManifest.xml +++ b/android-exoplayer/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ + android:configChanges="orientation|keyboardHidden|screenSize" + android:launchMode="singleTop" /> diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java index 1f2ee1d5..5492145f 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java @@ -1,6 +1,7 @@ package com.brentvatne.exoplayer; import android.os.Bundle; +import android.view.KeyEvent; import android.view.View; import android.widget.ImageView; @@ -13,7 +14,6 @@ import com.google.android.exoplayer2.ui.PlayerControlView; public class ExoPlayerFullscreenVideoActivity extends AppCompatActivity implements ReactExoplayerView.FullScreenDelegate { public static final String EXTRA_ID = "extra_id"; - public static final String EXTRA_IS_PLAYING = "extra_is_playing"; private int id; private PlayerControlView playerControlView; @@ -36,26 +36,40 @@ public class ExoPlayerFullscreenVideoActivity extends AppCompatActivity implemen ImageView fullscreenIcon = playerControlView.findViewById(R.id.exo_fullscreen_icon); fullscreenIcon.setImageResource(R.drawable.exo_controls_fullscreen_exit); playerControlView.findViewById(R.id.exo_fullscreen_button) - .setOnClickListener(v -> finish()); + .setOnClickListener(v -> ReactExoplayerView.getViewInstance(id).setFullscreen(false)); + //Handling the playButton click event + playerControlView.findViewById(R.id.exo_play).setOnClickListener(v -> { + if (player != null && player.getPlaybackState() == Player.STATE_ENDED) { + player.seekTo(0); + } + ReactExoplayerView.getViewInstance(id).setPausedModifier(false); + }); + + //Handling the pauseButton click event + playerControlView.findViewById(R.id.exo_pause).setOnClickListener(v -> ReactExoplayerView.getViewInstance(id).setPausedModifier(true)); } @Override public void onResume() { super.onResume(); - boolean isPlaying = getIntent().getBooleanExtra(EXTRA_IS_PLAYING, false); - player.setPlayWhenReady(isPlaying); + boolean isPaused = ReactExoplayerView.getViewInstance(id).isPaused(); + player.setPlayWhenReady(!isPaused); ReactExoplayerView.getViewInstance(id).registerFullScreenDelegate(this); } @Override public void onPause() { super.onPause(); - boolean isPlaying = player.getPlayWhenReady() && player.getPlaybackState() == Player.STATE_READY; - ReactExoplayerView.getViewInstance(id).setPausedModifier(!isPlaying); player.setPlayWhenReady(false); ReactExoplayerView.getViewInstance(id).registerFullScreenDelegate(null); } + @Override + protected void onDestroy() { + super.onDestroy(); + ReactExoplayerView.getViewInstance(id).removeViewInstance(); + } + @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); @@ -64,6 +78,15 @@ public class ExoPlayerFullscreenVideoActivity extends AppCompatActivity implemen } } + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if ((keyCode == KeyEvent.KEYCODE_BACK)) { + ReactExoplayerView.getViewInstance(id).setFullscreen(false); + return false; + } + return super.onKeyDown(keyCode, event); + } + private void togglePlayerControlVisibility() { if (playerControlView.isVisible()) { playerControlView.hide(); 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 5d546877..38bcd827 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -239,9 +239,13 @@ class ReactExoplayerView extends FrameLayout implements @Override public void onHostResume() { - exoPlayerView.setPlayer(player); if (!playInBackground || !isInBackground) { - setPlayWhenReady(!isPaused); + if (player != null) { + exoPlayerView.setPlayer(player); + boolean temp = this.disableFocus; + player.setPlayWhenReady(!isPaused); + this.disableFocus = temp; + } } isInBackground = false; } @@ -296,6 +300,10 @@ class ReactExoplayerView extends FrameLayout implements this.fullScreenDelegate = delegate; } + public void removeViewInstance() { + instances.remove(uid); + } + // Internal methods /** @@ -315,8 +323,6 @@ class ReactExoplayerView extends FrameLayout implements instances.put(uid, this); Intent intent = new Intent(getContext(), ExoPlayerFullscreenVideoActivity.class); intent.putExtra(ExoPlayerFullscreenVideoActivity.EXTRA_ID, this.uid); - boolean isPlaying = player.getPlayWhenReady() && player.getPlaybackState() == Player.STATE_READY; - intent.putExtra(ExoPlayerFullscreenVideoActivity.EXTRA_IS_PLAYING, isPlaying); getContext().startActivity(intent); } @@ -332,7 +338,7 @@ class ReactExoplayerView extends FrameLayout implements playerControlView.setPlayer(player); playerControlView.show(); playPauseControlContainer = playerControlView.findViewById(R.id.exo_play_pause_container); - playerControlView.findViewById(R.id.exo_fullscreen_button).setOnClickListener(v -> showFullscreen()); + playerControlView.findViewById(R.id.exo_fullscreen_button).setOnClickListener(v -> setFullscreen(true)); // Invoking onClick event for exoplayerView exoPlayerView.setOnClickListener(new OnClickListener() { From 5fe76574bbf30b7ea95fa4308760c12b26377f5e Mon Sep 17 00:00:00 2001 From: Tuan Luong Date: Fri, 10 Jul 2020 10:45:41 +0700 Subject: [PATCH 04/31] add fullscreenOrientation --- README.md | 2 +- .../ExoPlayerFullscreenVideoActivity.java | 33 ++++++++++++------- .../exoplayer/ReactExoplayerView.java | 11 ++++--- .../exoplayer/ReactExoplayerViewManager.java | 6 ++++ 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 00fc7932..3e701aa7 100644 --- a/README.md +++ b/README.md @@ -469,7 +469,7 @@ Platforms: iOS * **landscape** * **portrait** -Platforms: iOS +Platforms: Android ExoPlayer, iOS #### headers Pass headers to the HTTP client. Can be used for authorization. Headers must be a part of the source object. diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java index 5492145f..6996eb6c 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java @@ -1,5 +1,6 @@ package com.brentvatne.exoplayer; +import android.content.pm.ActivityInfo; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; @@ -14,7 +15,8 @@ import com.google.android.exoplayer2.ui.PlayerControlView; public class ExoPlayerFullscreenVideoActivity extends AppCompatActivity implements ReactExoplayerView.FullScreenDelegate { public static final String EXTRA_ID = "extra_id"; - + public static final String EXTRA_ORIENTATION = "extra_orientation"; + private int id; private PlayerControlView playerControlView; private SimpleExoPlayer player; @@ -22,8 +24,14 @@ public class ExoPlayerFullscreenVideoActivity extends AppCompatActivity implemen @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.exo_player_fullscreen_video); id = getIntent().getIntExtra(EXTRA_ID, -1); + String orientation = getIntent().getStringExtra(EXTRA_ORIENTATION); + if ("landscape".equals(orientation)) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); + } else if ("portrait".equals(orientation)) { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); + } + setContentView(R.layout.exo_player_fullscreen_video); player = ReactExoplayerView.getViewInstance(id).getPlayer(); ExoPlayerView playerView = findViewById(R.id.player_view); @@ -54,20 +62,18 @@ public class ExoPlayerFullscreenVideoActivity extends AppCompatActivity implemen super.onResume(); boolean isPaused = ReactExoplayerView.getViewInstance(id).isPaused(); player.setPlayWhenReady(!isPaused); - ReactExoplayerView.getViewInstance(id).registerFullScreenDelegate(this); + if (ReactExoplayerView.getViewInstance(id) != null) { + ReactExoplayerView.getViewInstance(id).registerFullScreenDelegate(this); + } } @Override public void onPause() { super.onPause(); player.setPlayWhenReady(false); - ReactExoplayerView.getViewInstance(id).registerFullScreenDelegate(null); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - ReactExoplayerView.getViewInstance(id).removeViewInstance(); + if (ReactExoplayerView.getViewInstance(id) != null) { + ReactExoplayerView.getViewInstance(id).registerFullScreenDelegate(null); + } } @Override @@ -81,8 +87,11 @@ public class ExoPlayerFullscreenVideoActivity extends AppCompatActivity implemen @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK)) { - ReactExoplayerView.getViewInstance(id).setFullscreen(false); - return false; + if (ReactExoplayerView.getViewInstance(id) != null) { + ReactExoplayerView.getViewInstance(id).setFullscreen(false); + return false; + } + return true; } return super.onKeyDown(keyCode, event); } 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 38bcd827..875d3402 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -114,6 +114,7 @@ class ReactExoplayerView extends FrameLayout implements private long resumePosition; private boolean loadVideoStarted; private boolean isFullscreen; + private String fullScreenOrientation; private boolean isInBackground; private boolean isPaused; private boolean isBuffering; @@ -266,6 +267,7 @@ class ReactExoplayerView extends FrameLayout implements public void cleanUpResources() { stopPlayback(); + instances.remove(uid); } //BandwidthMeter.EventListener implementation @@ -300,10 +302,6 @@ class ReactExoplayerView extends FrameLayout implements this.fullScreenDelegate = delegate; } - public void removeViewInstance() { - instances.remove(uid); - } - // Internal methods /** @@ -323,6 +321,7 @@ class ReactExoplayerView extends FrameLayout implements instances.put(uid, this); Intent intent = new Intent(getContext(), ExoPlayerFullscreenVideoActivity.class); intent.putExtra(ExoPlayerFullscreenVideoActivity.EXTRA_ID, this.uid); + intent.putExtra(ExoPlayerFullscreenVideoActivity.EXTRA_ORIENTATION, this.fullScreenOrientation); getContext().startActivity(intent); } @@ -1268,6 +1267,10 @@ class ReactExoplayerView extends FrameLayout implements } } + public void setFullscreenOrientation(String orientation) { + this.fullScreenOrientation = orientation; + } + public void setUseTextureView(boolean useTextureView) { exoPlayerView.setUseTextureView(useTextureView); } 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 cf50fdae..d520970d 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerViewManager.java @@ -54,6 +54,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager Date: Mon, 13 Jul 2020 14:41:38 +0700 Subject: [PATCH 05/31] do not hide fullscreen in stopPlayback --- .../ExoPlayerFullscreenVideoActivity.java | 3 +- .../exoplayer/ReactExoplayerView.java | 29 ++++++++++++------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java index 6996eb6c..329a8fda 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java @@ -60,9 +60,8 @@ public class ExoPlayerFullscreenVideoActivity extends AppCompatActivity implemen @Override public void onResume() { super.onResume(); - boolean isPaused = ReactExoplayerView.getViewInstance(id).isPaused(); - player.setPlayWhenReady(!isPaused); if (ReactExoplayerView.getViewInstance(id) != null) { + ReactExoplayerView.getViewInstance(id).syncPlayerState(); ReactExoplayerView.getViewInstance(id).registerFullScreenDelegate(this); } } 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 875d3402..83d70361 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java @@ -116,6 +116,7 @@ class ReactExoplayerView extends FrameLayout implements private boolean isFullscreen; private String fullScreenOrientation; private boolean isInBackground; + private boolean isInFullscreen; private boolean isPaused; private boolean isBuffering; private boolean muted = false; @@ -241,11 +242,14 @@ class ReactExoplayerView extends FrameLayout implements @Override public void onHostResume() { if (!playInBackground || !isInBackground) { - if (player != null) { - exoPlayerView.setPlayer(player); - boolean temp = this.disableFocus; - player.setPlayWhenReady(!isPaused); - this.disableFocus = temp; + if (isInFullscreen) { + if (player != null) { + exoPlayerView.setPlayer(player); + syncPlayerState(); + } + isInFullscreen = false; + } else { + setPlayWhenReady(!isPaused); } } isInBackground = false; @@ -294,8 +298,15 @@ class ReactExoplayerView extends FrameLayout implements return player; } - public boolean isPaused() { - return isPaused; + public void syncPlayerState() { + if (player == null) return; + if (player.getPlaybackState() == Player.STATE_ENDED) { + // Try to get last frame displayed + player.seekTo(player.getDuration() - 200); + player.setPlayWhenReady(true); + } else { + player.setPlayWhenReady(!isPaused); + } } public void registerFullScreenDelegate(FullScreenDelegate delegate) { @@ -323,6 +334,7 @@ class ReactExoplayerView extends FrameLayout implements intent.putExtra(ExoPlayerFullscreenVideoActivity.EXTRA_ID, this.uid); intent.putExtra(ExoPlayerFullscreenVideoActivity.EXTRA_ORIENTATION, this.fullScreenOrientation); getContext().startActivity(intent); + isInFullscreen = true; } /** @@ -623,9 +635,6 @@ class ReactExoplayerView extends FrameLayout implements } private void onStopPlayback() { - if (isFullscreen) { - setFullscreen(false); - } audioManager.abandonAudioFocus(this); } From 4d35511fb98f5494fc915502f5fe7799237ab724 Mon Sep 17 00:00:00 2001 From: Tuan Luong Date: Mon, 13 Jul 2020 14:50:09 +0700 Subject: [PATCH 06/31] add delay when hideSystemUI --- .../brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java index 329a8fda..d3b87208 100644 --- a/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java +++ b/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ExoPlayerFullscreenVideoActivity.java @@ -79,7 +79,7 @@ public class ExoPlayerFullscreenVideoActivity extends AppCompatActivity implemen public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { - hideSystemUI(); + playerControlView.postDelayed(this::hideSystemUI, 200); } } From 522af9eaa7d1b4e013a5bd835c1439f7f92d0ee4 Mon Sep 17 00:00:00 2001 From: redspear Date: Mon, 28 Sep 2020 09:56:06 +1000 Subject: [PATCH 07/31] Bugfix: #1930 --- ios/Video/RCTVideo.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index 8780f48f..a26c1bdd 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -718,7 +718,10 @@ static int const RCTVideoUnset = -1; } } else if (object == _player) { if([keyPath isEqualToString:playbackRate]) { - if(self.onPlaybackRateChange) { + if (_player.rate > 0 && _rate > 0 && _player.rate != _rate) { + // Playback is resuming, apply rate modifer. + [_player setRate:_rate]; + } else if(self.onPlaybackRateChange) { self.onPlaybackRateChange(@{@"playbackRate": [NSNumber numberWithFloat:_player.rate], @"target": self.reactTag}); } From f79782b4470f74c64926eff80db511596b07a05b Mon Sep 17 00:00:00 2001 From: Cameron Perry Date: Thu, 19 Nov 2020 16:18:31 -0800 Subject: [PATCH 08/31] =?UTF-8?q?Resolved=20an=20issue=20where=20setting?= =?UTF-8?q?=20a=20video=20to=20paused=20would=20ignore=20the=20=E2=80=9Csi?= =?UTF-8?q?lent=20switch=E2=80=9D=20setting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Video/RCTVideo.m | 51 +++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index 8780f48f..a4702cee 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -915,6 +915,7 @@ static int const RCTVideoUnset = -1; - (void)setIgnoreSilentSwitch:(NSString *)ignoreSilentSwitch { _ignoreSilentSwitch = ignoreSilentSwitch; + [self configureAudio]; [self applyModifiers]; } @@ -930,29 +931,8 @@ static int const RCTVideoUnset = -1; [_player pause]; [_player setRate:0.0]; } else { - AVAudioSession *session = [AVAudioSession sharedInstance]; - AVAudioSessionCategory category = nil; - AVAudioSessionCategoryOptions options = nil; - if([_ignoreSilentSwitch isEqualToString:@"ignore"]) { - category = AVAudioSessionCategoryPlayback; - } else if([_ignoreSilentSwitch isEqualToString:@"obey"]) { - category = AVAudioSessionCategoryAmbient; - } - - if([_mixWithOthers isEqualToString:@"mix"]) { - options = AVAudioSessionCategoryOptionMixWithOthers; - } else if([_mixWithOthers isEqualToString:@"duck"]) { - options = AVAudioSessionCategoryOptionDuckOthers; - } - - if (category != nil && options != nil) { - [session setCategory:category withOptions:options error:nil]; - } else if (category != nil && options == nil) { - [session setCategory:category error:nil]; - } else if (category == nil && options != nil) { - [session setCategory:session.category withOptions:options error:nil]; - } + [self configureAudio]; if (@available(iOS 10.0, *) && !_automaticallyWaitsToMinimizeStalling) { [_player playImmediatelyAtRate:_rate]; @@ -1086,6 +1066,33 @@ static int const RCTVideoUnset = -1; [self setAllowsExternalPlayback:_allowsExternalPlayback]; } +- (void)configureAudio +{ + AVAudioSession *session = [AVAudioSession sharedInstance]; + AVAudioSessionCategory category = nil; + AVAudioSessionCategoryOptions options = nil; + + if([_ignoreSilentSwitch isEqualToString:@"ignore"]) { + category = AVAudioSessionCategoryPlayback; + } else if([_ignoreSilentSwitch isEqualToString:@"obey"]) { + category = AVAudioSessionCategoryAmbient; + } + + if([_mixWithOthers isEqualToString:@"mix"]) { + options = AVAudioSessionCategoryOptionMixWithOthers; + } else if([_mixWithOthers isEqualToString:@"duck"]) { + options = AVAudioSessionCategoryOptionDuckOthers; + } + + if (category != nil && options != nil) { + [session setCategory:category withOptions:options error:nil]; + } else if (category != nil && options == nil) { + [session setCategory:category error:nil]; + } else if (category == nil && options != nil) { + [session setCategory:session.category withOptions:options error:nil]; + } +} + - (void)setRepeat:(BOOL)repeat { _repeat = repeat; } From 88b636f158f6287daa2a4286c7498c5f5a8f2255 Mon Sep 17 00:00:00 2001 From: Nick Fujita Date: Wed, 13 Jan 2021 19:18:01 +0900 Subject: [PATCH 09/31] iOS DRM Fixes for License Fetching (#2208) --- Video.js | 4 ++-- ios/Video/RCTVideo.m | 46 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Video.js b/Video.js index 6b84021f..b492d48b 100644 --- a/Video.js +++ b/Video.js @@ -236,8 +236,8 @@ export default class Video extends Component { _onGetLicense = (event) => { if (this.props.drm && this.props.drm.getLicense instanceof Function) { const data = event.nativeEvent; - if (data && data.spc) { - const getLicenseOverride = this.props.drm.getLicense(data.spc, data.contentId, data.spcBase64, this.props); + if (data && data.spcBase64) { + const getLicenseOverride = this.props.drm.getLicense(data.spcBase64, data.contentId, data.licenseUrl); const getLicensePromise = Promise.resolve(getLicenseOverride); // Handles both scenarios, getLicenseOverride being a promise and not. getLicensePromise.then((result => { if (result !== undefined) { diff --git a/ios/Video/RCTVideo.m b/ios/Video/RCTVideo.m index 8780f48f..989167a6 100644 --- a/ios/Video/RCTVideo.m +++ b/ios/Video/RCTVideo.m @@ -1764,11 +1764,15 @@ didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest { } _loadingRequest = loadingRequest; NSURL *url = loadingRequest.request.URL; - NSString *contentId = url.host; if (self->_drm != nil) { + NSString *contentId; NSString *contentIdOverride = (NSString *)[self->_drm objectForKey:@"contentId"]; if (contentIdOverride != nil) { contentId = contentIdOverride; + } else if (self.onGetLicense) { + contentId = url.host; + } else { + contentId = [url.absoluteString stringByReplacingOccurrencesOfString:@"skd://" withString:@""]; } NSString *drmType = (NSString *)[self->_drm objectForKey:@"type"]; if ([drmType isEqualToString:@"fairplay"]) { @@ -1782,7 +1786,12 @@ didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest { } if (certificateData != nil) { - NSData *contentIdData = [contentId dataUsingEncoding:NSUTF8StringEncoding]; + NSData *contentIdData; + if(self.onGetLicense) { + contentIdData = [contentId dataUsingEncoding:NSUTF8StringEncoding]; + } else { + contentIdData = [NSData dataWithBytes: [contentId cStringUsingEncoding:NSUTF8StringEncoding] length:[contentId lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; + } AVAssetResourceLoadingDataRequest *dataRequest = [loadingRequest dataRequest]; if (dataRequest != nil) { NSError *spcError = nil; @@ -1795,12 +1804,16 @@ didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest { } if (spcData != nil) { if(self.onGetLicense) { - NSString *spcStr = [[NSString alloc] initWithData:spcData encoding:NSASCIIStringEncoding]; + NSString *base64Encoded = [spcData base64EncodedStringWithOptions:0]; self->_requestingCertificate = YES; - self.onGetLicense(@{@"spc": spcStr, + if (licenseServer == nil) { + licenseServer = @""; + } + self.onGetLicense(@{@"licenseUrl": licenseServer, @"contentId": contentId, - @"spcBase64": [[[NSData alloc] initWithBase64EncodedData:certificateData options:NSDataBase64DecodingIgnoreUnknownCharacters] base64EncodedStringWithOptions:0], - @"target": self.reactTag}); + @"spcBase64": base64Encoded, + @"target": self.reactTag} + ); } else if(licenseServer != nil) { NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setHTTPMethod:@"POST"]; @@ -1813,9 +1826,17 @@ didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest { [request setValue:value forHTTPHeaderField:key]; } } - // + + if(self.onGetLicense) { + [request setHTTPBody: spcData]; + } else { + NSString *spcEncoded = [spcData base64EncodedStringWithOptions:0]; + NSString *spcUrlEncoded = (NSString *) CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)spcEncoded, NULL, CFSTR("?=&+"), kCFStringEncodingUTF8)); + NSString *post = [NSString stringWithFormat:@"spc=%@&%@", spcUrlEncoded, contentId]; + NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; + [request setHTTPBody: postData]; + } - [request setHTTPBody: spcData]; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { @@ -1838,7 +1859,12 @@ didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest { [self finishLoadingWithError:licenseError]; self->_requestingCertificateErrored = YES; } else if (data != nil) { - [dataRequest respondWithData:data]; + if(self.onGetLicense) { + [dataRequest respondWithData:data]; + } else { + NSData *decodedData = [[NSData alloc] initWithBase64EncodedData:data options:0]; + [dataRequest respondWithData:decodedData]; + } [loadingRequest finishLoading]; } else { NSError *licenseError = [NSError errorWithDomain: @"RCTVideo" @@ -1852,7 +1878,7 @@ didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest { [self finishLoadingWithError:licenseError]; self->_requestingCertificateErrored = YES; } - + } }]; [postDataTask resume]; From 5adedb131bc21bdf03eabca78e3eb8d7bab231ac Mon Sep 17 00:00:00 2001 From: Nick Date: Thu, 14 Jan 2021 11:13:39 +0900 Subject: [PATCH 10/31] Update package.json version number to 5.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2e0144c5..06d2765c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-video", - "version": "5.1.0-alpha8", + "version": "5.1.1", "description": "A