user = getUser();
if (!user.isPresent()) {
@@ -2362,7 +2363,7 @@ public void onMessageEvent(SyncEventFinished event) {
startTextPreview((OCFile) bundle.get(EXTRA_FILE), true);
} else if (bundle.containsKey(PreviewVideoActivity.EXTRA_START_POSITION)) {
startMediaPreview((OCFile) bundle.get(EXTRA_FILE),
- (int) bundle.get(PreviewVideoActivity.EXTRA_START_POSITION),
+ (long) bundle.get(PreviewVideoActivity.EXTRA_START_POSITION),
(boolean) bundle.get(PreviewVideoActivity.EXTRA_AUTOPLAY), true, true);
} else if (bundle.containsKey(PreviewImageActivity.EXTRA_VIRTUAL_TYPE)) {
startImagePreview((OCFile)bundle.get(EXTRA_FILE),
diff --git a/src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java b/src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java
index 758d36e740c1..3aeaa4a8f470 100644
--- a/src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java
+++ b/src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java
@@ -31,10 +31,6 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaMetadataRetriever;
-import android.media.MediaPlayer;
-import android.media.MediaPlayer.OnCompletionListener;
-import android.media.MediaPlayer.OnErrorListener;
-import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -48,16 +44,19 @@
import android.view.ViewGroup;
import android.widget.LinearLayout;
+import com.google.android.exoplayer2.MediaItem;
+import com.google.android.exoplayer2.SimpleExoPlayer;
+import com.google.android.exoplayer2.ui.StyledPlayerControlView;
import com.nextcloud.client.account.User;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.device.DeviceInfo;
import com.nextcloud.client.di.Injectable;
-import com.nextcloud.client.media.ErrorFormat;
import com.nextcloud.client.media.PlayerServiceConnection;
import com.nextcloud.client.network.ClientFactory;
import com.owncloud.android.R;
import com.owncloud.android.databinding.FragmentPreviewMediaBinding;
import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.files.FileMenuFilter;
import com.owncloud.android.files.StreamMediaFileOperation;
import com.owncloud.android.lib.common.OwnCloudClient;
@@ -80,14 +79,15 @@
/**
* This fragment shows a preview of a downloaded media file (audio or video).
- *
- * Trying to get an instance with NULL {@link OCFile} or ownCloud {@link Account} values will
- * produce an {@link IllegalStateException}.
- *
- * By now, if the {@link OCFile} passed is not downloaded, an {@link IllegalStateException} is
- * generated on instantiation too.
+ *
+ * Trying to get an instance with NULL {@link OCFile} or ownCloud {@link Account} values will produce an {@link
+ * IllegalStateException}.
+ *
+ * By now, if the {@link OCFile} passed is not downloaded, an {@link IllegalStateException} is generated on
+ * instantiation too.
*/
-public class PreviewMediaFragment extends FileFragment implements OnTouchListener, Injectable {
+public class PreviewMediaFragment extends FileFragment implements OnTouchListener,
+ Injectable, StyledPlayerControlView.OnFullScreenModeChangedListener {
private static final String TAG = PreviewMediaFragment.class.getSimpleName();
@@ -96,6 +96,7 @@ public class PreviewMediaFragment extends FileFragment implements OnTouchListene
private static final String EXTRA_PLAY_POSITION = "PLAY_POSITION";
private static final String EXTRA_PLAYING = "PLAYING";
private static final double MIN_DENSITY_RATIO = 24.0;
+ private static final int MENU_FULLSCREEN_ID = 3344;
private static final String FILE = "FILE";
private static final String USER = "USER";
@@ -103,7 +104,7 @@ public class PreviewMediaFragment extends FileFragment implements OnTouchListene
private static final String AUTOPLAY = "AUTOPLAY";
private User user;
- private int savedPlaybackPosition;
+ private long savedPlaybackPosition;
private boolean autoplay;
private boolean prepared;
@@ -115,6 +116,7 @@ public class PreviewMediaFragment extends FileFragment implements OnTouchListene
@Inject DeviceInfo deviceInfo;
FragmentPreviewMediaBinding binding;
LinearLayout emptyListView;
+ private SimpleExoPlayer exoPlayer;
/**
* Creates a fragment to preview a file.
@@ -124,14 +126,16 @@ public class PreviewMediaFragment extends FileFragment implements OnTouchListene
* @param fileToDetail An {@link OCFile} to preview in the fragment
* @param user Currently active user
*/
- public static PreviewMediaFragment newInstance(OCFile fileToDetail, User user, int startPlaybackPosition,
+ public static PreviewMediaFragment newInstance(OCFile fileToDetail,
+ User user,
+ long startPlaybackPosition,
boolean autoplay) {
PreviewMediaFragment previewMediaFragment = new PreviewMediaFragment();
Bundle bundle = new Bundle();
bundle.putParcelable(FILE, fileToDetail);
bundle.putParcelable(USER, user);
- bundle.putInt(PLAYBACK_POSITION, startPlaybackPosition);
+ bundle.putLong(PLAYBACK_POSITION, startPlaybackPosition);
bundle.putBoolean(AUTOPLAY, autoplay);
previewMediaFragment.setArguments(bundle);
@@ -142,11 +146,10 @@ public static PreviewMediaFragment newInstance(OCFile fileToDetail, User user, i
/**
* Creates an empty fragment for previews.
*
- * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically
- * (for instance, when the device is turned a aside).
+ * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically (for instance, when the
+ * device is turned a aside).
*
- * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful
- * construction
+ * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful construction
*/
public PreviewMediaFragment() {
super();
@@ -163,7 +166,7 @@ public void onCreate(Bundle savedInstanceState) {
setFile(bundle.getParcelable(FILE));
user = bundle.getParcelable(USER);
- savedPlaybackPosition = bundle.getInt(PLAYBACK_POSITION);
+ savedPlaybackPosition = bundle.getLong(PLAYBACK_POSITION);
autoplay = bundle.getBoolean(AUTOPLAY);
mediaPlayerServiceConnection = new PlayerServiceConnection(getContext());
}
@@ -178,8 +181,6 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
emptyListView = binding.emptyView.emptyListView;
- binding.videoPreview.setOnTouchListener(this);
-
setLoadingView();
return view;
}
@@ -222,11 +223,10 @@ public void onActivityCreated(Bundle savedInstanceState) {
if (file != null) {
if (MimeTypeUtil.isVideo(file)) {
- binding.videoPreview.setVisibility(View.VISIBLE);
+ binding.exoplayerView.setVisibility(View.VISIBLE);
binding.imagePreview.setVisibility(View.GONE);
- prepareVideo();
} else {
- binding.videoPreview.setVisibility(View.GONE);
+ binding.exoplayerView.setVisibility(View.GONE);
binding.imagePreview.setVisibility(View.VISIBLE);
extractAndSetCoverArt(file);
}
@@ -241,22 +241,37 @@ public void onActivityCreated(Bundle savedInstanceState) {
*/
private void extractAndSetCoverArt(OCFile file) {
if (MimeTypeUtil.isAudio(file)) {
- try {
- MediaMetadataRetriever mmr = new MediaMetadataRetriever();
- mmr.setDataSource(file.getStoragePath());
- byte[] data = mmr.getEmbeddedPicture();
- if (data != null) {
- Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- binding.imagePreview.setImageBitmap(bitmap); //associated cover art in bitmap
- } else {
+ if (file.getStoragePath() == null) {
+ setThumbnailForAudio(file);
+ } else {
+ try {
+ MediaMetadataRetriever mmr = new MediaMetadataRetriever();
+ mmr.setDataSource(file.getStoragePath());
+ byte[] data = mmr.getEmbeddedPicture();
+ if (data != null) {
+ Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
+ binding.imagePreview.setImageBitmap(bitmap); //associated cover art in bitmap
+ } else {
+ setThumbnailForAudio(file);
+ }
+ } catch (Throwable t) {
binding.imagePreview.setImageResource(R.drawable.logo);
}
- } catch (Throwable t) {
- binding.imagePreview.setImageResource(R.drawable.logo);
}
}
}
+ private void setThumbnailForAudio(OCFile file) {
+ Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
+ ThumbnailsCacheManager.PREFIX_THUMBNAIL + file.getRemoteId());
+
+ if (thumbnail != null) {
+ binding.imagePreview.setImageBitmap(thumbnail);
+ } else {
+ binding.imagePreview.setImageResource(R.drawable.logo);
+ }
+ }
+
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
@@ -266,13 +281,11 @@ public void onSaveInstanceState(@NonNull Bundle outState) {
outState.putParcelable(EXTRA_USER, user);
if (MimeTypeUtil.isVideo(getFile())) {
- if (binding.videoPreview != null) {
- savedPlaybackPosition = binding.videoPreview.getCurrentPosition();
- autoplay = binding.videoPreview.isPlaying();
- outState.putInt(EXTRA_PLAY_POSITION, savedPlaybackPosition);
- outState.putBoolean(EXTRA_PLAYING, autoplay);
- }
- } else if(mediaPlayerServiceConnection.isConnected()) {
+ savedPlaybackPosition = exoPlayer.getCurrentPosition();
+ autoplay = exoPlayer.isPlaying();
+ outState.putLong(EXTRA_PLAY_POSITION, savedPlaybackPosition);
+ outState.putBoolean(EXTRA_PLAYING, autoplay);
+ } else if (mediaPlayerServiceConnection.isConnected()) {
outState.putInt(EXTRA_PLAY_POSITION, mediaPlayerServiceConnection.getCurrentPosition());
outState.putBoolean(EXTRA_PLAYING, mediaPlayerServiceConnection.isPlaying());
}
@@ -287,12 +300,15 @@ public void onStart() {
// bind to any existing player
mediaPlayerServiceConnection.bind();
+ exoPlayer = new SimpleExoPlayer.Builder(getContext()).build();
+ binding.exoplayerView.setPlayer(exoPlayer);
+
if (MimeTypeUtil.isAudio(file)) {
binding.mediaController.setMediaPlayer(mediaPlayerServiceConnection);
+ binding.mediaController.setVisibility(View.VISIBLE);
mediaPlayerServiceConnection.start(user, file, autoplay, savedPlaybackPosition);
binding.emptyView.emptyListView.setVisibility(View.GONE);
binding.progress.setVisibility(View.GONE);
- binding.filePreviewContainer.setVisibility(View.VISIBLE);
} else if (MimeTypeUtil.isVideo(file)) {
if (mediaPlayerServiceConnection.isConnected()) {
// always stop player
@@ -311,6 +327,7 @@ private void stopAudio() {
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.removeItem(R.id.action_search);
+ menu.add(Menu.NONE, MENU_FULLSCREEN_ID, 99, R.string.fullscreen);
inflater.inflate(R.menu.item_file, menu);
}
@@ -375,10 +392,10 @@ public void onPrepareOptionsMenu(@NonNull Menu menu) {
item.setEnabled(false);
}
- if(getFile().isSharedWithMe() && !getFile().canReshare()){
+ if (getFile().isSharedWithMe() && !getFile().canReshare()) {
// additional restriction for this fragment
item = menu.findItem(R.id.action_send_share_file);
- if(item != null){
+ if (item != null) {
item.setVisible(false);
item.setEnabled(false);
}
@@ -404,6 +421,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
} else if (itemId == R.id.action_sync_file) {
containerActivity.getFileOperationsHelper().syncFile(getFile());
return true;
+ } else if (itemId == MENU_FULLSCREEN_ID) {
+ startFullScreenVideo();
+ return true;
}
return super.onOptionsItemSelected(item);
}
@@ -411,7 +431,7 @@ public boolean onOptionsItemSelected(MenuItem item) {
/**
* Update the file of the fragment with file value
*
- * @param file Replaces the held file with a new one
+ * @param file Replaces the held file with a new one
*/
public void updateFile(OCFile file) {
setFile(file);
@@ -427,44 +447,55 @@ private void sendShareFile() {
containerActivity.getFileOperationsHelper().sendShareFile(getFile());
}
- private void prepareVideo() {
- // create helper to get more control on the playback
- VideoHelper videoHelper = new VideoHelper();
- binding.videoPreview.setOnPreparedListener(videoHelper);
- binding.videoPreview.setOnCompletionListener(videoHelper);
- binding.videoPreview.setOnErrorListener(videoHelper);
- }
-
private void playVideo() {
- // create and prepare control panel for the user
- binding.mediaController.setMediaPlayer(binding.videoPreview);
-
// load the video file in the video player
// when done, VideoHelper#onPrepared() will be called
if (getFile().isDown()) {
- binding.videoPreview.setVideoURI(getFile().getStorageUri());
+ binding.progress.setVisibility(View.GONE);
+
+ exoPlayer.addMediaItem(MediaItem.fromUri(getFile().getStorageUri()));
+ exoPlayer.prepare();
+
+ if (savedPlaybackPosition >= 0) {
+ exoPlayer.seekTo(savedPlaybackPosition);
+ }
+ exoPlayer.play();
} else {
try {
- OwnCloudClient client = clientFactory.create(user);
- new LoadStreamUrl(this, client).execute(getFile().getLocalId());
+ new LoadStreamUrl(this, user, clientFactory).execute(getFile().getLocalId());
} catch (Exception e) {
Log_OC.e(TAG, "Loading stream url not possible: " + e);
}
}
}
+ @Override
+ public void onFullScreenModeChanged(boolean isFullScreen) {
+ Log_OC.e(TAG, "Fullscreen: " + isFullScreen);
+ }
+
private static class LoadStreamUrl extends AsyncTask {
- private OwnCloudClient client;
- private WeakReference previewMediaFragmentWeakReference;
+ private final ClientFactory clientFactory;
+ private final User user;
+ private final WeakReference previewMediaFragmentWeakReference;
- public LoadStreamUrl(PreviewMediaFragment previewMediaFragment, OwnCloudClient client) {
- this.client = client;
+ public LoadStreamUrl(PreviewMediaFragment previewMediaFragment, User user, ClientFactory clientFactory) {
this.previewMediaFragmentWeakReference = new WeakReference<>(previewMediaFragment);
+ this.user = user;
+ this.clientFactory = clientFactory;
}
@Override
protected Uri doInBackground(String... fileId) {
+ OwnCloudClient client;
+ try {
+ client = clientFactory.create(user);
+ } catch (ClientFactory.CreationException e) {
+ Log_OC.e(TAG, "Loading stream url not possible: " + e);
+ return null;
+ }
+
StreamMediaFileOperation sfo = new StreamMediaFileOperation(fileId[0]);
RemoteOperationResult result = sfo.execute(client);
@@ -482,7 +513,12 @@ protected void onPostExecute(Uri uri) {
if (previewMediaFragment != null && context != null) {
if (uri != null) {
previewMediaFragment.videoUri = uri;
- previewMediaFragment.binding.videoPreview.setVideoURI(uri);
+
+ previewMediaFragment.binding.progress.setVisibility(View.GONE);
+
+ previewMediaFragment.exoPlayer.addMediaItem(MediaItem.fromUri(uri));
+ previewMediaFragment.exoPlayer.prepare();
+ previewMediaFragment.exoPlayer.play();
} else {
previewMediaFragment.emptyListView.setVisibility(View.VISIBLE);
previewMediaFragment.setVideoErrorMessage(
@@ -495,70 +531,6 @@ protected void onPostExecute(Uri uri) {
}
}
- private class VideoHelper implements OnCompletionListener, OnPreparedListener, OnErrorListener {
-
- /**
- * Called when the file is ready to be played.
- *
- * Just starts the playback.
- *
- * @param vp {@link MediaPlayer} instance performing the playback.
- */
- @Override
- public void onPrepared(MediaPlayer vp) {
- Log_OC.v(TAG, "onPrepared");
- binding.emptyView.emptyListView.setVisibility(View.GONE);
- binding.progress.setVisibility(View.GONE);
- binding.filePreviewContainer.setVisibility(View.VISIBLE);
- binding.videoPreview.seekTo(savedPlaybackPosition);
- if (autoplay) {
- binding.videoPreview.start();
- }
- binding.mediaController.setEnabled(true);
- binding.mediaController.updatePausePlay();
- prepared = true;
- }
-
-
- /**
- * Called when the file is finished playing.
- *
- * Finishes the activity.
- *
- * @param mp {@link MediaPlayer} instance performing the playback.
- */
- @Override
- public void onCompletion(MediaPlayer mp) {
- Log_OC.v(TAG, "completed");
- if (mp != null) {
- binding.videoPreview.seekTo(0);
- } // else : called from onError()
- binding.mediaController.updatePausePlay();
- }
-
- /**
- * Called when an error in playback occurs.
- *
- * @param mp {@link MediaPlayer} instance performing the playback.
- * @param what Type of error
- * @param extra Extra code specific to the error
- */
- @Override
- public boolean onError(MediaPlayer mp, int what, int extra) {
- Log_OC.e(TAG, "Error in video playback, what = " + what + ", extra = " + extra);
- binding.filePreviewContainer.setVisibility(View.GONE);
- binding.progress.setVisibility(View.GONE);
- final Context context = getActivity();
- if (binding.videoPreview.getWindowToken() != null && context != null) {
- String message = ErrorFormat.toString(context, what, extra);
- binding.emptyView.emptyListView.setVisibility(View.VISIBLE);
- setVideoErrorMessage(message, R.string.preview_sorry);
- }
- return true;
- }
-
- }
-
@Override
public void onPause() {
Log_OC.v(TAG, "onPause");
@@ -568,6 +540,7 @@ public void onPause() {
@Override
public void onResume() {
super.onResume();
+ autoplay = false;
Log_OC.v(TAG, "onResume");
}
@@ -587,6 +560,10 @@ public void onDestroyView() {
@Override
public void onStop() {
Log_OC.v(TAG, "onStop");
+ if (MimeTypeUtil.isAudio(getFile()) && !mediaPlayerServiceConnection.isPlaying()) {
+ stopAudio();
+ }
+
mediaPlayerServiceConnection.unbind();
toggleDrawerLockMode(containerActivity, DrawerLayout.LOCK_MODE_UNLOCKED);
super.onStop();
@@ -594,7 +571,7 @@ public void onStop() {
@Override
public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN && v.equals(binding.videoPreview)) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN && v.equals(binding.exoplayerView)) {
// added a margin on the left to avoid interfering with gesture to open navigation drawer
if (event.getX() / Resources.getSystem().getDisplayMetrics().density > MIN_DENSITY_RATIO) {
startFullScreenVideo();
@@ -608,10 +585,10 @@ private void startFullScreenVideo() {
Intent intent = new Intent(getActivity(), PreviewVideoActivity.class);
intent.putExtra(FileActivity.EXTRA_ACCOUNT, user.toPlatformAccount());
intent.putExtra(FileActivity.EXTRA_FILE, getFile());
- intent.putExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, binding.videoPreview.isPlaying());
+ intent.putExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, exoPlayer.isPlaying());
intent.putExtra(PreviewVideoActivity.EXTRA_STREAM_URL, videoUri);
- binding.videoPreview.pause();
- intent.putExtra(PreviewVideoActivity.EXTRA_START_POSITION, binding.videoPreview.getCurrentPosition());
+ exoPlayer.pause();
+ intent.putExtra(PreviewVideoActivity.EXTRA_START_POSITION, exoPlayer.getCurrentPosition());
startActivityForResult(intent, FileActivity.REQUEST_CODE__LAST_SHARED + 1);
}
@@ -626,7 +603,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log_OC.v(TAG, "onActivityResult " + this);
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
- savedPlaybackPosition = data.getIntExtra(PreviewVideoActivity.EXTRA_START_POSITION, 0);
+ savedPlaybackPosition = data.getLongExtra(PreviewVideoActivity.EXTRA_START_POSITION, 0);
autoplay = data.getBooleanExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, false);
}
}
@@ -641,8 +618,7 @@ private void openFile() {
}
/**
- * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewMediaFragment}
- * to be previewed.
+ * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewMediaFragment} to be previewed.
*
* @param file File to test if can be previewed.
* @return 'True' if the file can be handled by the fragment.
@@ -656,7 +632,7 @@ public void stopPreview(boolean stopAudio) {
if (MimeTypeUtil.isAudio(file) && stopAudio) {
mediaPlayerServiceConnection.pause();
} else if (MimeTypeUtil.isVideo(file)) {
- binding.videoPreview.stopPlayback();
+ exoPlayer.stop(true);
}
}
@@ -670,9 +646,9 @@ private void finishPreview() {
}
}
- public int getPosition() {
+ public long getPosition() {
if (prepared) {
- savedPlaybackPosition = binding.videoPreview.getCurrentPosition();
+ savedPlaybackPosition = exoPlayer.getCurrentPosition();
}
Log_OC.v(TAG, "getting position: " + savedPlaybackPosition);
return savedPlaybackPosition;
@@ -681,4 +657,13 @@ public int getPosition() {
private void toggleDrawerLockMode(ContainerActivity containerActivity, int lockMode) {
((DrawerActivity) containerActivity).setDrawerLockMode(lockMode);
}
+
+ @Override
+ public void onDetach() {
+
+ exoPlayer.stop();
+ exoPlayer.release();
+
+ super.onDetach();
+ }
}
diff --git a/src/main/java/com/owncloud/android/ui/preview/PreviewVideoActivity.java b/src/main/java/com/owncloud/android/ui/preview/PreviewVideoActivity.java
index dad19f4f3d36..d4496be2c5df 100644
--- a/src/main/java/com/owncloud/android/ui/preview/PreviewVideoActivity.java
+++ b/src/main/java/com/owncloud/android/ui/preview/PreviewVideoActivity.java
@@ -21,7 +21,6 @@
package com.owncloud.android.ui.preview;
import android.accounts.Account;
-import android.content.DialogInterface;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
@@ -29,9 +28,11 @@
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Bundle;
-import android.widget.MediaController;
-import android.widget.VideoView;
+import com.google.android.exoplayer2.ExoPlayer;
+import com.google.android.exoplayer2.MediaItem;
+import com.google.android.exoplayer2.SimpleExoPlayer;
+import com.google.android.exoplayer2.ui.StyledPlayerView;
import com.nextcloud.client.media.ErrorFormat;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.OCFile;
@@ -62,10 +63,9 @@ public class PreviewVideoActivity extends FileActivity implements OnCompletionLi
private static final String TAG = PreviewVideoActivity.class.getSimpleName();
- private int mSavedPlaybackPosition; // in the unit time handled by MediaPlayer.getCurrentPosition()
+ private long mSavedPlaybackPosition = -1; // in the unit time handled by MediaPlayer.getCurrentPosition()
private boolean mAutoplay; // when 'true', the playback starts immediately with the activity
- private VideoView mVideoPlayer; // view to play the file; both performs and show the playback
- private MediaController mMediaController; // panel control used by the user to control the playback
+ private ExoPlayer exoPlayer; // view to play the file; both performs and show the playback
private Uri mStreamUri;
/**
@@ -85,26 +85,25 @@ public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.video_layout);
- if (savedInstanceState == null) {
- Bundle extras = getIntent().getExtras();
- mSavedPlaybackPosition = extras.getInt(EXTRA_START_POSITION);
+ Bundle extras = getIntent().getExtras();
+
+ if (savedInstanceState == null && extras != null) {
+ mSavedPlaybackPosition = extras.getLong(EXTRA_START_POSITION);
mAutoplay = extras.getBoolean(EXTRA_AUTOPLAY);
mStreamUri = (Uri) extras.get(EXTRA_STREAM_URL);
- } else {
- mSavedPlaybackPosition = savedInstanceState.getInt(EXTRA_START_POSITION);
+ } else if (savedInstanceState != null) {
+ mSavedPlaybackPosition = savedInstanceState.getLong(EXTRA_START_POSITION);
mAutoplay = savedInstanceState.getBoolean(EXTRA_AUTOPLAY);
mStreamUri = (Uri) savedInstanceState.get(EXTRA_STREAM_URL);
}
- mVideoPlayer = findViewById(R.id.videoPlayer);
-
- // set listeners to get more control on the playback
- mVideoPlayer.setOnPreparedListener(this);
- mVideoPlayer.setOnCompletionListener(this);
- mVideoPlayer.setOnErrorListener(this);
+ StyledPlayerView playerView = findViewById(R.id.videoPlayer);
+ exoPlayer = new SimpleExoPlayer.Builder(this).build();
+ playerView.setPlayer(exoPlayer);
- // keep the screen on while the playback is performed (prevents screen off by battery save)
- mVideoPlayer.setKeepScreenOn(true);
+ if (mSavedPlaybackPosition >= 0) {
+ exoPlayer.seekTo(mSavedPlaybackPosition);
+ }
if (getSupportActionBar() != null) {
getSupportActionBar().hide();
@@ -117,8 +116,8 @@ public void onCreate(Bundle savedInstanceState) {
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putInt(PreviewVideoActivity.EXTRA_START_POSITION, mVideoPlayer.getCurrentPosition());
- outState.putBoolean(PreviewVideoActivity.EXTRA_AUTOPLAY , mVideoPlayer.isPlaying());
+ outState.putLong(PreviewVideoActivity.EXTRA_START_POSITION, exoPlayer.getCurrentPosition());
+ outState.putBoolean(PreviewVideoActivity.EXTRA_AUTOPLAY, exoPlayer.isPlaying());
outState.putParcelable(PreviewVideoActivity.EXTRA_STREAM_URL, mStreamUri);
}
@@ -127,9 +126,13 @@ public void onSaveInstanceState(@NonNull Bundle outState) {
public void onBackPressed() {
Log_OC.v(TAG, "onBackPressed");
Intent i = new Intent();
- i.putExtra(EXTRA_AUTOPLAY, mVideoPlayer.isPlaying());
- i.putExtra(EXTRA_START_POSITION, mVideoPlayer.getCurrentPosition());
+ i.putExtra(EXTRA_AUTOPLAY, exoPlayer.isPlaying());
+ i.putExtra(EXTRA_START_POSITION, exoPlayer.getCurrentPosition());
setResult(RESULT_OK, i);
+
+ exoPlayer.stop();
+ exoPlayer.release();
+
super.onBackPressed();
}
@@ -144,11 +147,10 @@ public void onBackPressed() {
@Override
public void onPrepared(MediaPlayer mp) {
Log_OC.v(TAG, "onPrepare");
- mVideoPlayer.seekTo(mSavedPlaybackPosition);
+ exoPlayer.seekTo(mSavedPlaybackPosition);
if (mAutoplay) {
- mVideoPlayer.start();
+ exoPlayer.play();
}
- mMediaController.show(5000);
}
@@ -161,7 +163,7 @@ public void onPrepared(MediaPlayer mp) {
*/
@Override
public void onCompletion(MediaPlayer mp) {
- mVideoPlayer.seekTo(0);
+ exoPlayer.seekTo(0);
}
@@ -176,23 +178,13 @@ public void onCompletion(MediaPlayer mp) {
public boolean onError(MediaPlayer mp, int what, int extra) {
Log_OC.e(TAG, "Error in video playback, what = " + what + ", extra = " + extra);
- if (mMediaController != null) {
- mMediaController.hide();
- }
-
- if (mVideoPlayer.getWindowToken() != null) {
- String message = ErrorFormat.toString(this, what, extra);
- new AlertDialog.Builder(this)
- .setMessage(message)
- .setPositiveButton(android.R.string.VideoView_error_button,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int whichButton) {
- PreviewVideoActivity.this.onCompletion(null);
- }
- })
- .setCancelable(false)
- .show();
- }
+ String message = ErrorFormat.toString(this, what, extra);
+ new AlertDialog.Builder(this)
+ .setMessage(message)
+ .setPositiveButton(android.R.string.VideoView_error_button,
+ (dialog, whichButton) -> PreviewVideoActivity.this.onCompletion(null))
+ .setCancelable(false)
+ .show();
return true;
}
@@ -211,17 +203,13 @@ protected void onStart() {
file = getStorageManager().getFileById(file.getFileId());
if (file != null) {
if (file.isDown()) {
- mVideoPlayer.setVideoURI(file.getStorageUri());
+ exoPlayer.addMediaItem(MediaItem.fromUri(file.getStorageUri()));
} else {
- mVideoPlayer.setVideoURI(mStreamUri);
+ exoPlayer.addMediaItem(MediaItem.fromUri(mStreamUri));
}
- // create and prepare control panel for the user
- mMediaController = new MediaController(this);
- mMediaController.setMediaPlayer(mVideoPlayer);
- mMediaController.setAnchorView(mVideoPlayer);
- mVideoPlayer.setMediaController(mMediaController);
-
+ exoPlayer.prepare();
+ exoPlayer.play();
} else {
finish();
}
diff --git a/src/main/res/layout/fragment_preview_media.xml b/src/main/res/layout/fragment_preview_media.xml
index e8456adc2ee1..47bbb85e4e4a 100644
--- a/src/main/res/layout/fragment_preview_media.xml
+++ b/src/main/res/layout/fragment_preview_media.xml
@@ -20,53 +20,38 @@
-->
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_gravity="center"
+ app:show_buffering="when_playing" />
+
+
-
-
-
-
-
-
+ android:layout_gravity="center"
+ android:background="@color/black" />
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 831dd11e19b2..18b289e8445c 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -958,4 +958,5 @@
Please select one template
Please choose a template and enter a file name.
Strict mode: no http connection allowed!
+ Fullscreen