PreviewMediaFragment.java 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. /*
  2. * ownCloud Android client application
  3. *
  4. * @author David A. Velasco
  5. * @author Chris Narkiewicz
  6. * @author Andy Scherzinger
  7. * Copyright (C) 2016 ownCloud Inc.
  8. * Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
  9. * Copyright (C) 2020 Andy Scherzinger
  10. *
  11. * This program is free software: you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License version 2,
  13. * as published by the Free Software Foundation.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. package com.owncloud.android.ui.preview;
  24. import android.accounts.Account;
  25. import android.app.Activity;
  26. import android.content.Context;
  27. import android.content.Intent;
  28. import android.content.res.Configuration;
  29. import android.content.res.Resources;
  30. import android.graphics.Bitmap;
  31. import android.graphics.BitmapFactory;
  32. import android.media.MediaMetadataRetriever;
  33. import android.media.MediaPlayer;
  34. import android.media.MediaPlayer.OnCompletionListener;
  35. import android.media.MediaPlayer.OnErrorListener;
  36. import android.media.MediaPlayer.OnPreparedListener;
  37. import android.net.Uri;
  38. import android.os.AsyncTask;
  39. import android.os.Bundle;
  40. import android.view.LayoutInflater;
  41. import android.view.Menu;
  42. import android.view.MenuInflater;
  43. import android.view.MenuItem;
  44. import android.view.MotionEvent;
  45. import android.view.View;
  46. import android.view.View.OnTouchListener;
  47. import android.view.ViewGroup;
  48. import android.widget.LinearLayout;
  49. import com.nextcloud.client.account.User;
  50. import com.nextcloud.client.account.UserAccountManager;
  51. import com.nextcloud.client.device.DeviceInfo;
  52. import com.nextcloud.client.di.Injectable;
  53. import com.nextcloud.client.media.ErrorFormat;
  54. import com.nextcloud.client.media.PlayerServiceConnection;
  55. import com.nextcloud.client.network.ClientFactory;
  56. import com.owncloud.android.R;
  57. import com.owncloud.android.databinding.FragmentPreviewMediaBinding;
  58. import com.owncloud.android.datamodel.OCFile;
  59. import com.owncloud.android.files.FileMenuFilter;
  60. import com.owncloud.android.files.StreamMediaFileOperation;
  61. import com.owncloud.android.lib.common.OwnCloudClient;
  62. import com.owncloud.android.lib.common.operations.RemoteOperationResult;
  63. import com.owncloud.android.lib.common.utils.Log_OC;
  64. import com.owncloud.android.ui.activity.DrawerActivity;
  65. import com.owncloud.android.ui.activity.FileActivity;
  66. import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
  67. import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
  68. import com.owncloud.android.ui.fragment.FileFragment;
  69. import com.owncloud.android.utils.MimeTypeUtil;
  70. import java.lang.ref.WeakReference;
  71. import javax.inject.Inject;
  72. import androidx.annotation.NonNull;
  73. import androidx.annotation.StringRes;
  74. import androidx.drawerlayout.widget.DrawerLayout;
  75. /**
  76. * This fragment shows a preview of a downloaded media file (audio or video).
  77. *
  78. * Trying to get an instance with NULL {@link OCFile} or ownCloud {@link Account} values will
  79. * produce an {@link IllegalStateException}.
  80. *
  81. * By now, if the {@link OCFile} passed is not downloaded, an {@link IllegalStateException} is
  82. * generated on instantiation too.
  83. */
  84. public class PreviewMediaFragment extends FileFragment implements OnTouchListener, Injectable {
  85. private static final String TAG = PreviewMediaFragment.class.getSimpleName();
  86. public static final String EXTRA_FILE = "FILE";
  87. public static final String EXTRA_USER = "USER";
  88. private static final String EXTRA_PLAY_POSITION = "PLAY_POSITION";
  89. private static final String EXTRA_PLAYING = "PLAYING";
  90. private static final double MIN_DENSITY_RATIO = 24.0;
  91. private static final String FILE = "FILE";
  92. private static final String USER = "USER";
  93. private static final String PLAYBACK_POSITION = "PLAYBACK_POSITION";
  94. private static final String AUTOPLAY = "AUTOPLAY";
  95. private User user;
  96. private int savedPlaybackPosition;
  97. private boolean autoplay;
  98. private boolean prepared;
  99. private PlayerServiceConnection mediaPlayerServiceConnection;
  100. private Uri videoUri;
  101. @Inject ClientFactory clientFactory;
  102. @Inject UserAccountManager accountManager;
  103. @Inject DeviceInfo deviceInfo;
  104. FragmentPreviewMediaBinding binding;
  105. LinearLayout emptyListView;
  106. /**
  107. * Creates a fragment to preview a file.
  108. * <p>
  109. * When 'fileToDetail' or 'user' are null
  110. *
  111. * @param fileToDetail An {@link OCFile} to preview in the fragment
  112. * @param user Currently active user
  113. */
  114. public static PreviewMediaFragment newInstance(OCFile fileToDetail, User user, int startPlaybackPosition,
  115. boolean autoplay) {
  116. PreviewMediaFragment previewMediaFragment = new PreviewMediaFragment();
  117. Bundle bundle = new Bundle();
  118. bundle.putParcelable(FILE, fileToDetail);
  119. bundle.putParcelable(USER, user);
  120. bundle.putInt(PLAYBACK_POSITION, startPlaybackPosition);
  121. bundle.putBoolean(AUTOPLAY, autoplay);
  122. previewMediaFragment.setArguments(bundle);
  123. return previewMediaFragment;
  124. }
  125. /**
  126. * Creates an empty fragment for previews.
  127. * <p/>
  128. * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically
  129. * (for instance, when the device is turned a aside).
  130. * <p/>
  131. * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful
  132. * construction
  133. */
  134. public PreviewMediaFragment() {
  135. super();
  136. savedPlaybackPosition = 0;
  137. autoplay = true;
  138. }
  139. @Override
  140. public void onCreate(Bundle savedInstanceState) {
  141. super.onCreate(savedInstanceState);
  142. setHasOptionsMenu(true);
  143. Bundle bundle = getArguments();
  144. setFile(bundle.getParcelable(FILE));
  145. user = bundle.getParcelable(USER);
  146. savedPlaybackPosition = bundle.getInt(PLAYBACK_POSITION);
  147. autoplay = bundle.getBoolean(AUTOPLAY);
  148. mediaPlayerServiceConnection = new PlayerServiceConnection(getContext());
  149. }
  150. @Override
  151. public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  152. super.onCreateView(inflater, container, savedInstanceState);
  153. Log_OC.v(TAG, "onCreateView");
  154. binding = FragmentPreviewMediaBinding.inflate(inflater, container, false);
  155. View view = binding.getRoot();
  156. emptyListView = binding.emptyView.emptyListView;
  157. binding.videoPreview.setOnTouchListener(this);
  158. setLoadingView();
  159. return view;
  160. }
  161. private void setLoadingView() {
  162. binding.progress.setVisibility(View.VISIBLE);
  163. binding.emptyView.emptyListView.setVisibility(View.GONE);
  164. }
  165. private void setVideoErrorMessage(String headline, @StringRes int message) {
  166. binding.emptyView.emptyListViewHeadline.setText(headline);
  167. binding.emptyView.emptyListViewText.setText(message);
  168. binding.emptyView.emptyListIcon.setImageResource(R.drawable.file_movie);
  169. binding.emptyView.emptyListViewText.setVisibility(View.VISIBLE);
  170. binding.emptyView.emptyListIcon.setVisibility(View.VISIBLE);
  171. binding.progress.setVisibility(View.GONE);
  172. binding.emptyView.emptyListView.setVisibility(View.VISIBLE);
  173. }
  174. @Override
  175. public void onActivityCreated(Bundle savedInstanceState) {
  176. super.onActivityCreated(savedInstanceState);
  177. Log_OC.v(TAG, "onActivityCreated");
  178. OCFile file = getFile();
  179. if (savedInstanceState == null) {
  180. if (file == null) {
  181. throw new IllegalStateException("Instanced with a NULL OCFile");
  182. }
  183. if (user == null) {
  184. throw new IllegalStateException("Instanced with a NULL ownCloud Account");
  185. }
  186. } else {
  187. file = savedInstanceState.getParcelable(EXTRA_FILE);
  188. setFile(file);
  189. user = savedInstanceState.getParcelable(EXTRA_USER);
  190. savedPlaybackPosition = savedInstanceState.getInt(EXTRA_PLAY_POSITION);
  191. autoplay = savedInstanceState.getBoolean(EXTRA_PLAYING);
  192. }
  193. if (file != null) {
  194. if (MimeTypeUtil.isVideo(file)) {
  195. binding.videoPreview.setVisibility(View.VISIBLE);
  196. binding.imagePreview.setVisibility(View.GONE);
  197. prepareVideo();
  198. } else {
  199. binding.videoPreview.setVisibility(View.GONE);
  200. binding.imagePreview.setVisibility(View.VISIBLE);
  201. extractAndSetCoverArt(file);
  202. }
  203. }
  204. toggleDrawerLockMode(containerActivity, DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
  205. }
  206. /**
  207. * tries to read the cover art from the audio file and sets it as cover art.
  208. *
  209. * @param file audio file with potential cover art
  210. */
  211. private void extractAndSetCoverArt(OCFile file) {
  212. if (MimeTypeUtil.isAudio(file)) {
  213. try {
  214. MediaMetadataRetriever mmr = new MediaMetadataRetriever();
  215. mmr.setDataSource(file.getStoragePath());
  216. byte[] data = mmr.getEmbeddedPicture();
  217. if (data != null) {
  218. Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
  219. binding.imagePreview.setImageBitmap(bitmap); //associated cover art in bitmap
  220. } else {
  221. binding.imagePreview.setImageResource(R.drawable.logo);
  222. }
  223. } catch (Throwable t) {
  224. binding.imagePreview.setImageResource(R.drawable.logo);
  225. }
  226. }
  227. }
  228. @Override
  229. public void onSaveInstanceState(@NonNull Bundle outState) {
  230. super.onSaveInstanceState(outState);
  231. Log_OC.v(TAG, "onSaveInstanceState");
  232. toggleDrawerLockMode(containerActivity, DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
  233. outState.putParcelable(EXTRA_FILE, getFile());
  234. outState.putParcelable(EXTRA_USER, user);
  235. if (MimeTypeUtil.isVideo(getFile())) {
  236. if (binding.videoPreview != null) {
  237. savedPlaybackPosition = binding.videoPreview.getCurrentPosition();
  238. autoplay = binding.videoPreview.isPlaying();
  239. outState.putInt(EXTRA_PLAY_POSITION, savedPlaybackPosition);
  240. outState.putBoolean(EXTRA_PLAYING, autoplay);
  241. }
  242. } else if(mediaPlayerServiceConnection.isConnected()) {
  243. outState.putInt(EXTRA_PLAY_POSITION, mediaPlayerServiceConnection.getCurrentPosition());
  244. outState.putBoolean(EXTRA_PLAYING, mediaPlayerServiceConnection.isPlaying());
  245. }
  246. }
  247. @Override
  248. public void onStart() {
  249. super.onStart();
  250. Log_OC.v(TAG, "onStart");
  251. OCFile file = getFile();
  252. if (file != null) {
  253. // bind to any existing player
  254. mediaPlayerServiceConnection.bind();
  255. if (MimeTypeUtil.isAudio(file)) {
  256. binding.mediaController.setMediaPlayer(mediaPlayerServiceConnection);
  257. mediaPlayerServiceConnection.start(user, file, autoplay, savedPlaybackPosition);
  258. binding.emptyView.emptyListView.setVisibility(View.GONE);
  259. binding.progress.setVisibility(View.GONE);
  260. binding.filePreviewContainer.setVisibility(View.VISIBLE);
  261. } else if (MimeTypeUtil.isVideo(file)) {
  262. if (mediaPlayerServiceConnection.isConnected()) {
  263. // always stop player
  264. stopAudio();
  265. }
  266. playVideo();
  267. }
  268. }
  269. }
  270. private void stopAudio() {
  271. mediaPlayerServiceConnection.stop();
  272. }
  273. @Override
  274. public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
  275. super.onCreateOptionsMenu(menu, inflater);
  276. menu.removeItem(R.id.action_search);
  277. inflater.inflate(R.menu.item_file, menu);
  278. }
  279. @Override
  280. public void onPrepareOptionsMenu(@NonNull Menu menu) {
  281. super.onPrepareOptionsMenu(menu);
  282. if (containerActivity.getStorageManager() != null) {
  283. User currentUser = accountManager.getUser();
  284. FileMenuFilter mf = new FileMenuFilter(
  285. getFile(),
  286. containerActivity,
  287. getActivity(),
  288. false,
  289. deviceInfo,
  290. currentUser
  291. );
  292. mf.filter(menu, true);
  293. }
  294. // additional restriction for this fragment
  295. // TODO allow renaming in PreviewImageFragment
  296. MenuItem item = menu.findItem(R.id.action_rename_file);
  297. if (item != null) {
  298. item.setVisible(false);
  299. item.setEnabled(false);
  300. }
  301. // additional restriction for this fragment
  302. item = menu.findItem(R.id.action_select_all);
  303. if (item != null) {
  304. item.setVisible(false);
  305. item.setEnabled(false);
  306. }
  307. // additional restriction for this fragment
  308. item = menu.findItem(R.id.action_move);
  309. if (item != null) {
  310. item.setVisible(false);
  311. item.setEnabled(false);
  312. }
  313. // additional restriction for this fragment
  314. item = menu.findItem(R.id.action_copy);
  315. if (item != null) {
  316. item.setVisible(false);
  317. item.setEnabled(false);
  318. }
  319. // additional restriction for this fragment
  320. item = menu.findItem(R.id.action_favorite);
  321. if (item != null) {
  322. item.setVisible(false);
  323. item.setEnabled(false);
  324. }
  325. // additional restriction for this fragment
  326. item = menu.findItem(R.id.action_unset_favorite);
  327. if (item != null) {
  328. item.setVisible(false);
  329. item.setEnabled(false);
  330. }
  331. if(getFile().isSharedWithMe() && !getFile().canReshare()){
  332. // additional restriction for this fragment
  333. item = menu.findItem(R.id.action_send_share_file);
  334. if(item != null){
  335. item.setVisible(false);
  336. item.setEnabled(false);
  337. }
  338. }
  339. }
  340. @Override
  341. public boolean onOptionsItemSelected(MenuItem item) {
  342. int itemId = item.getItemId();
  343. if (itemId == R.id.action_send_share_file) {
  344. sendShareFile();
  345. return true;
  346. } else if (itemId == R.id.action_open_file_with) {
  347. openFile();
  348. return true;
  349. } else if (itemId == R.id.action_remove_file) {
  350. RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(getFile());
  351. dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
  352. return true;
  353. } else if (itemId == R.id.action_see_details) {
  354. seeDetails();
  355. return true;
  356. } else if (itemId == R.id.action_sync_file) {
  357. containerActivity.getFileOperationsHelper().syncFile(getFile());
  358. return true;
  359. }
  360. return super.onOptionsItemSelected(item);
  361. }
  362. /**
  363. * Update the file of the fragment with file value
  364. *
  365. * @param file Replaces the held file with a new one
  366. */
  367. public void updateFile(OCFile file) {
  368. setFile(file);
  369. }
  370. private void seeDetails() {
  371. stopPreview(false);
  372. containerActivity.showDetails(getFile());
  373. }
  374. private void sendShareFile() {
  375. stopPreview(false);
  376. containerActivity.getFileOperationsHelper().sendShareFile(getFile());
  377. }
  378. private void prepareVideo() {
  379. // create helper to get more control on the playback
  380. VideoHelper videoHelper = new VideoHelper();
  381. binding.videoPreview.setOnPreparedListener(videoHelper);
  382. binding.videoPreview.setOnCompletionListener(videoHelper);
  383. binding.videoPreview.setOnErrorListener(videoHelper);
  384. }
  385. private void playVideo() {
  386. // create and prepare control panel for the user
  387. binding.mediaController.setMediaPlayer(binding.videoPreview);
  388. // load the video file in the video player
  389. // when done, VideoHelper#onPrepared() will be called
  390. if (getFile().isDown()) {
  391. binding.videoPreview.setVideoURI(getFile().getStorageUri());
  392. } else {
  393. try {
  394. OwnCloudClient client = clientFactory.create(user);
  395. new LoadStreamUrl(this, client).execute(getFile().getLocalId());
  396. } catch (Exception e) {
  397. Log_OC.e(TAG, "Loading stream url not possible: " + e);
  398. }
  399. }
  400. }
  401. private static class LoadStreamUrl extends AsyncTask<String, Void, Uri> {
  402. private OwnCloudClient client;
  403. private WeakReference<PreviewMediaFragment> previewMediaFragmentWeakReference;
  404. public LoadStreamUrl(PreviewMediaFragment previewMediaFragment, OwnCloudClient client) {
  405. this.client = client;
  406. this.previewMediaFragmentWeakReference = new WeakReference<>(previewMediaFragment);
  407. }
  408. @Override
  409. protected Uri doInBackground(String... fileId) {
  410. StreamMediaFileOperation sfo = new StreamMediaFileOperation(fileId[0]);
  411. RemoteOperationResult result = sfo.execute(client);
  412. if (!result.isSuccess()) {
  413. return null;
  414. }
  415. return Uri.parse((String) result.getData().get(0));
  416. }
  417. @Override
  418. protected void onPostExecute(Uri uri) {
  419. final PreviewMediaFragment previewMediaFragment = previewMediaFragmentWeakReference.get();
  420. final Context context = previewMediaFragment != null ? previewMediaFragment.getContext() : null;
  421. if (previewMediaFragment != null && context != null) {
  422. if (uri != null) {
  423. previewMediaFragment.videoUri = uri;
  424. previewMediaFragment.binding.videoPreview.setVideoURI(uri);
  425. } else {
  426. previewMediaFragment.emptyListView.setVisibility(View.VISIBLE);
  427. previewMediaFragment.setVideoErrorMessage(
  428. previewMediaFragment.getString(R.string.stream_not_possible_headline),
  429. R.string.stream_not_possible_message);
  430. }
  431. } else {
  432. Log_OC.e(TAG, "Error streaming file: no previewMediaFragment!");
  433. }
  434. }
  435. }
  436. private class VideoHelper implements OnCompletionListener, OnPreparedListener, OnErrorListener {
  437. /**
  438. * Called when the file is ready to be played.
  439. * <p/>
  440. * Just starts the playback.
  441. *
  442. * @param vp {@link MediaPlayer} instance performing the playback.
  443. */
  444. @Override
  445. public void onPrepared(MediaPlayer vp) {
  446. Log_OC.v(TAG, "onPrepared");
  447. binding.emptyView.emptyListView.setVisibility(View.GONE);
  448. binding.progress.setVisibility(View.GONE);
  449. binding.filePreviewContainer.setVisibility(View.VISIBLE);
  450. binding.videoPreview.seekTo(savedPlaybackPosition);
  451. if (autoplay) {
  452. binding.videoPreview.start();
  453. }
  454. binding.mediaController.setEnabled(true);
  455. binding.mediaController.updatePausePlay();
  456. prepared = true;
  457. }
  458. /**
  459. * Called when the file is finished playing.
  460. * <p/>
  461. * Finishes the activity.
  462. *
  463. * @param mp {@link MediaPlayer} instance performing the playback.
  464. */
  465. @Override
  466. public void onCompletion(MediaPlayer mp) {
  467. Log_OC.v(TAG, "completed");
  468. if (mp != null) {
  469. binding.videoPreview.seekTo(0);
  470. } // else : called from onError()
  471. binding.mediaController.updatePausePlay();
  472. }
  473. /**
  474. * Called when an error in playback occurs.
  475. *
  476. * @param mp {@link MediaPlayer} instance performing the playback.
  477. * @param what Type of error
  478. * @param extra Extra code specific to the error
  479. */
  480. @Override
  481. public boolean onError(MediaPlayer mp, int what, int extra) {
  482. Log_OC.e(TAG, "Error in video playback, what = " + what + ", extra = " + extra);
  483. binding.filePreviewContainer.setVisibility(View.GONE);
  484. binding.progress.setVisibility(View.GONE);
  485. final Context context = getActivity();
  486. if (binding.videoPreview.getWindowToken() != null && context != null) {
  487. String message = ErrorFormat.toString(context, what, extra);
  488. binding.emptyView.emptyListView.setVisibility(View.VISIBLE);
  489. setVideoErrorMessage(message, R.string.preview_sorry);
  490. }
  491. return true;
  492. }
  493. }
  494. @Override
  495. public void onPause() {
  496. Log_OC.v(TAG, "onPause");
  497. super.onPause();
  498. }
  499. @Override
  500. public void onResume() {
  501. super.onResume();
  502. Log_OC.v(TAG, "onResume");
  503. }
  504. @Override
  505. public void onDestroy() {
  506. Log_OC.v(TAG, "onDestroy");
  507. super.onDestroy();
  508. }
  509. @Override
  510. public void onDestroyView() {
  511. Log_OC.v(TAG, "onDestroyView");
  512. super.onDestroyView();
  513. binding = null;
  514. }
  515. @Override
  516. public void onStop() {
  517. Log_OC.v(TAG, "onStop");
  518. mediaPlayerServiceConnection.unbind();
  519. toggleDrawerLockMode(containerActivity, DrawerLayout.LOCK_MODE_UNLOCKED);
  520. super.onStop();
  521. }
  522. @Override
  523. public boolean onTouch(View v, MotionEvent event) {
  524. if (event.getAction() == MotionEvent.ACTION_DOWN && v.equals(binding.videoPreview)) {
  525. // added a margin on the left to avoid interfering with gesture to open navigation drawer
  526. if (event.getX() / Resources.getSystem().getDisplayMetrics().density > MIN_DENSITY_RATIO) {
  527. startFullScreenVideo();
  528. }
  529. return true;
  530. }
  531. return false;
  532. }
  533. private void startFullScreenVideo() {
  534. Intent intent = new Intent(getActivity(), PreviewVideoActivity.class);
  535. intent.putExtra(FileActivity.EXTRA_ACCOUNT, user.toPlatformAccount());
  536. intent.putExtra(FileActivity.EXTRA_FILE, getFile());
  537. intent.putExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, binding.videoPreview.isPlaying());
  538. intent.putExtra(PreviewVideoActivity.EXTRA_STREAM_URL, videoUri);
  539. binding.videoPreview.pause();
  540. intent.putExtra(PreviewVideoActivity.EXTRA_START_POSITION, binding.videoPreview.getCurrentPosition());
  541. startActivityForResult(intent, FileActivity.REQUEST_CODE__LAST_SHARED + 1);
  542. }
  543. @Override
  544. public void onConfigurationChanged(@NonNull Configuration newConfig) {
  545. super.onConfigurationChanged(newConfig);
  546. Log_OC.v(TAG, "onConfigurationChanged " + this);
  547. }
  548. @Override
  549. public void onActivityResult(int requestCode, int resultCode, Intent data) {
  550. Log_OC.v(TAG, "onActivityResult " + this);
  551. super.onActivityResult(requestCode, resultCode, data);
  552. if (resultCode == Activity.RESULT_OK) {
  553. savedPlaybackPosition = data.getIntExtra(PreviewVideoActivity.EXTRA_START_POSITION, 0);
  554. autoplay = data.getBooleanExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, false);
  555. }
  556. }
  557. /**
  558. * Opens the previewed file with an external application.
  559. */
  560. private void openFile() {
  561. stopPreview(true);
  562. containerActivity.getFileOperationsHelper().openFile(getFile());
  563. finishPreview();
  564. }
  565. /**
  566. * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewMediaFragment}
  567. * to be previewed.
  568. *
  569. * @param file File to test if can be previewed.
  570. * @return 'True' if the file can be handled by the fragment.
  571. */
  572. public static boolean canBePreviewed(OCFile file) {
  573. return file != null && (MimeTypeUtil.isAudio(file) || MimeTypeUtil.isVideo(file));
  574. }
  575. public void stopPreview(boolean stopAudio) {
  576. OCFile file = getFile();
  577. if (MimeTypeUtil.isAudio(file) && stopAudio) {
  578. mediaPlayerServiceConnection.pause();
  579. } else if (MimeTypeUtil.isVideo(file)) {
  580. binding.videoPreview.stopPlayback();
  581. }
  582. }
  583. /**
  584. * Finishes the preview
  585. */
  586. private void finishPreview() {
  587. final Activity activity = getActivity();
  588. if (activity != null) {
  589. activity.onBackPressed();
  590. }
  591. }
  592. public int getPosition() {
  593. if (prepared) {
  594. savedPlaybackPosition = binding.videoPreview.getCurrentPosition();
  595. }
  596. Log_OC.v(TAG, "getting position: " + savedPlaybackPosition);
  597. return savedPlaybackPosition;
  598. }
  599. private void toggleDrawerLockMode(ContainerActivity containerActivity, int lockMode) {
  600. ((DrawerActivity) containerActivity).setDrawerLockMode(lockMode);
  601. }
  602. }