wip
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / preview / PreviewMediaFragment.java
1 /**
2 * ownCloud Android client application
3 *
4 * @author David A. Velasco
5 * Copyright (C) 2015 ownCloud Inc.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2,
9 * as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20 package com.owncloud.android.ui.preview;
21
22 import android.accounts.Account;
23 import android.accounts.AuthenticatorException;
24 import android.accounts.OperationCanceledException;
25 import android.app.Activity;
26 import android.content.ActivityNotFoundException;
27 import android.graphics.Bitmap;
28 import android.graphics.BitmapFactory;
29 import android.media.MediaMetadataRetriever;
30 import android.os.AsyncTask;
31 import android.support.v7.app.AlertDialog;
32 import android.content.ComponentName;
33 import android.content.Context;
34 import android.content.DialogInterface;
35 import android.content.Intent;
36 import android.content.ServiceConnection;
37 import android.content.res.Configuration;
38 import android.content.res.Resources;
39 import android.media.MediaPlayer;
40 import android.media.MediaPlayer.OnCompletionListener;
41 import android.media.MediaPlayer.OnErrorListener;
42 import android.media.MediaPlayer.OnPreparedListener;
43 import android.net.Uri;
44 import android.os.Build;
45 import android.os.Bundle;
46 import android.os.IBinder;
47 import android.view.LayoutInflater;
48 import android.view.Menu;
49 import android.view.MenuInflater;
50 import android.view.MenuItem;
51 import android.view.MotionEvent;
52 import android.view.View;
53 import android.view.View.OnTouchListener;
54 import android.view.ViewGroup;
55 import android.widget.ImageView;
56 import android.widget.Toast;
57 import android.widget.VideoView;
58
59 import com.owncloud.android.MainApp;
60 import com.owncloud.android.R;
61 import com.owncloud.android.datamodel.OCFile;
62 import com.owncloud.android.datamodel.ThumbnailsCacheManager;
63 import com.owncloud.android.files.FileMenuFilter;
64 import com.owncloud.android.lib.common.OwnCloudAccount;
65 import com.owncloud.android.lib.common.OwnCloudClient;
66 import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
67 import com.owncloud.android.lib.common.OwnCloudCredentials;
68 import com.owncloud.android.lib.common.accounts.AccountUtils;
69 import com.owncloud.android.lib.common.utils.Log_OC;
70 import com.owncloud.android.media.MediaControlView;
71 import com.owncloud.android.media.MediaService;
72 import com.owncloud.android.media.MediaServiceBinder;
73 import com.owncloud.android.ui.activity.FileActivity;
74 import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
75 import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
76 import com.owncloud.android.ui.fragment.FileFragment;
77
78 import java.io.IOException;
79 import java.util.concurrent.ExecutionException;
80
81
82 /**
83 * This fragment shows a preview of a downloaded media file (audio or video).
84 *
85 * Trying to get an instance with NULL {@link OCFile} or ownCloud {@link Account} values will
86 * produce an {@link IllegalStateException}.
87 *
88 * By now, if the {@link OCFile} passed is not downloaded, an {@link IllegalStateException} is
89 * generated on instantiation too.
90 */
91 public class PreviewMediaFragment extends FileFragment implements
92 OnTouchListener {
93
94 public static final String EXTRA_FILE = "FILE";
95 public static final String EXTRA_ACCOUNT = "ACCOUNT";
96 private static final String EXTRA_PLAY_POSITION = "PLAY_POSITION";
97 private static final String EXTRA_PLAYING = "PLAYING";
98
99 private View mView;
100 private Account mAccount;
101 private ImageView mImagePreview;
102 private VideoView mVideoPreview;
103 private int mSavedPlaybackPosition;
104 private String mUri;
105
106 private MediaServiceBinder mMediaServiceBinder = null;
107 private MediaControlView mMediaController = null;
108 private MediaServiceConnection mMediaServiceConnection = null;
109 private VideoHelper mVideoHelper;
110 private boolean mAutoplay;
111 public boolean mPrepared;
112
113 private static final String TAG = PreviewMediaFragment.class.getSimpleName();
114
115
116 /**
117 * Creates a fragment to preview a file.
118 * <p/>
119 * When 'fileToDetail' or 'ocAccount' are null
120 *
121 * @param fileToDetail An {@link OCFile} to preview in the fragment
122 * @param ocAccount An ownCloud account; needed to start downloads
123 */
124 public PreviewMediaFragment(
125 OCFile fileToDetail,
126 Account ocAccount,
127 int startPlaybackPosition,
128 boolean autoplay) {
129
130 super(fileToDetail);
131 mAccount = ocAccount;
132 mSavedPlaybackPosition = startPlaybackPosition;
133 mAutoplay = autoplay;
134 }
135
136
137 /**
138 * Creates an empty fragment for previews.
139 * <p/>
140 * MUST BE KEPT: the system uses it when tries to reinstantiate a fragment automatically
141 * (for instance, when the device is turned a aside).
142 * <p/>
143 * DO NOT CALL IT: an {@link OCFile} and {@link Account} must be provided for a successful
144 * construction
145 */
146 public PreviewMediaFragment() {
147 super();
148 mAccount = null;
149 mSavedPlaybackPosition = 0;
150 mAutoplay = true;
151 }
152
153
154 /**
155 * {@inheritDoc}
156 */
157 @Override
158 public void onCreate(Bundle savedInstanceState) {
159 super.onCreate(savedInstanceState);
160 setHasOptionsMenu(true);
161 }
162
163
164 /**
165 * {@inheritDoc}
166 */
167 @Override
168 public View onCreateView(LayoutInflater inflater, ViewGroup container,
169 Bundle savedInstanceState) {
170 super.onCreateView(inflater, container, savedInstanceState);
171 Log_OC.e(TAG, "onCreateView");
172
173
174 mView = inflater.inflate(R.layout.file_preview, container, false);
175
176 mImagePreview = (ImageView) mView.findViewById(R.id.image_preview);
177 mVideoPreview = (VideoView) mView.findViewById(R.id.video_preview);
178 mVideoPreview.setOnTouchListener(this);
179
180 mMediaController = (MediaControlView) mView.findViewById(R.id.media_controller);
181
182 return mView;
183 }
184
185
186 /**
187 * {@inheritDoc}
188 */
189 @Override
190 public void onActivityCreated(Bundle savedInstanceState) {
191 super.onActivityCreated(savedInstanceState);
192 Log_OC.e(TAG, "onActivityCreated");
193
194 OCFile file = getFile();
195 if (savedInstanceState == null) {
196 if (file == null) {
197 throw new IllegalStateException("Instanced with a NULL OCFile");
198 }
199 if (mAccount == null) {
200 throw new IllegalStateException("Instanced with a NULL ownCloud Account");
201 }
202 // if (!file.isDown()) {
203 // throw new IllegalStateException("There is no local file to preview");
204 // }
205
206 }
207 else {
208 file = (OCFile) savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_FILE);
209 setFile(file);
210 mAccount = savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_ACCOUNT);
211 mSavedPlaybackPosition =
212 savedInstanceState.getInt(PreviewMediaFragment.EXTRA_PLAY_POSITION);
213 mAutoplay = savedInstanceState.getBoolean(PreviewMediaFragment.EXTRA_PLAYING);
214
215 }
216 if (file != null) {
217 if (file.isVideo()) {
218 mVideoPreview.setVisibility(View.VISIBLE);
219 mImagePreview.setVisibility(View.GONE);
220 prepareVideo();
221
222 }
223 else {
224 mVideoPreview.setVisibility(View.GONE);
225 mImagePreview.setVisibility(View.VISIBLE);
226 extractAndSetCoverArt(file);
227 }
228 }
229
230 }
231
232 /**
233 * tries to read the cover art from the audio file and sets it as cover art.
234 *
235 * @param file audio file with potential cover art
236 */
237 private void extractAndSetCoverArt(OCFile file) {
238 if (file.isAudio()) {
239 try {
240 MediaMetadataRetriever mmr = new MediaMetadataRetriever();
241 mmr.setDataSource(file.getStoragePath());
242 byte[] data = mmr.getEmbeddedPicture();
243 if (data != null) {
244 Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
245 mImagePreview.setImageBitmap(bitmap); //associated cover art in bitmap
246 } else {
247 mImagePreview.setImageResource(R.drawable.logo);
248 }
249 } catch (Throwable t) {
250 mImagePreview.setImageResource(R.drawable.logo);
251 }
252 }
253 }
254
255
256 /**
257 * {@inheritDoc}
258 */
259 @Override
260 public void onSaveInstanceState(Bundle outState) {
261 super.onSaveInstanceState(outState);
262 Log_OC.e(TAG, "onSaveInstanceState");
263
264 outState.putParcelable(PreviewMediaFragment.EXTRA_FILE, getFile());
265 outState.putParcelable(PreviewMediaFragment.EXTRA_ACCOUNT, mAccount);
266
267 if (getFile().isVideo()) {
268 mSavedPlaybackPosition = mVideoPreview.getCurrentPosition();
269 mAutoplay = mVideoPreview.isPlaying();
270 outState.putInt(PreviewMediaFragment.EXTRA_PLAY_POSITION, mSavedPlaybackPosition);
271 outState.putBoolean(PreviewMediaFragment.EXTRA_PLAYING, mAutoplay);
272 }
273 else {
274 outState.putInt(
275 PreviewMediaFragment.EXTRA_PLAY_POSITION,
276 mMediaServiceBinder.getCurrentPosition());
277 outState.putBoolean(
278 PreviewMediaFragment.EXTRA_PLAYING, mMediaServiceBinder.isPlaying());
279 }
280 }
281
282
283 @Override
284 public void onStart() {
285 super.onStart();
286 Log_OC.e(TAG, "onStart");
287
288 OCFile file = getFile();
289 if (file != null) {
290 if (file.isAudio()) {
291 bindMediaService();
292
293 }
294 else {
295 if (file.isVideo()) {
296 stopAudio();
297 playVideo();
298 }
299 }
300 }
301 }
302
303
304 private void stopAudio() {
305 Intent i = new Intent(getActivity(), MediaService.class);
306 i.setAction(MediaService.ACTION_STOP_ALL);
307 getActivity().startService(i);
308 }
309
310
311 /**
312 * {@inheritDoc}
313 */
314 @Override
315 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
316 super.onCreateOptionsMenu(menu, inflater);
317 inflater.inflate(R.menu.file_actions_menu, menu);
318 }
319
320
321 /**
322 * {@inheritDoc}
323 */
324 @Override
325 public void onPrepareOptionsMenu(Menu menu) {
326 super.onPrepareOptionsMenu(menu);
327
328 if (mContainerActivity.getStorageManager() != null) {
329 FileMenuFilter mf = new FileMenuFilter(
330 getFile(),
331 mContainerActivity.getStorageManager().getAccount(),
332 mContainerActivity,
333 getActivity()
334 );
335 mf.filter(menu);
336 }
337
338 // additional restriction for this fragment
339 // TODO allow renaming in PreviewImageFragment
340 MenuItem item = menu.findItem(R.id.action_rename_file);
341 if (item != null) {
342 item.setVisible(false);
343 item.setEnabled(false);
344 }
345
346 // additional restriction for this fragment
347 item = menu.findItem(R.id.action_move);
348 if (item != null) {
349 item.setVisible(false);
350 item.setEnabled(false);
351 }
352
353 // additional restriction for this fragment
354 item = menu.findItem(R.id.action_copy);
355 if (item != null) {
356 item.setVisible(false);
357 item.setEnabled(false);
358 }
359 }
360
361
362 /**
363 * {@inheritDoc}
364 */
365 @Override
366 public boolean onOptionsItemSelected(MenuItem item) {
367 switch (item.getItemId()) {
368 case R.id.action_share_file: {
369 stopPreview(false);
370 mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile());
371 return true;
372 }
373 case R.id.action_unshare_file: {
374 stopPreview(false);
375 mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile());
376 return true;
377 }
378 case R.id.action_open_file_with: {
379 openFile();
380 return true;
381 }
382 case R.id.action_remove_file: {
383 RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile());
384 dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
385 return true;
386 }
387 case R.id.action_see_details: {
388 seeDetails();
389 return true;
390 }
391 case R.id.action_send_file: {
392 sendFile();
393 return true;
394 }
395 case R.id.action_sync_file: {
396 mContainerActivity.getFileOperationsHelper().syncFile(getFile());
397 return true;
398 }
399 case R.id.action_favorite_file:{
400 mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), true);
401 return true;
402 }
403 case R.id.action_unfavorite_file:{
404 mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), false);
405 return true;
406 }
407 default:
408 return false;
409 }
410 }
411
412
413 /**
414 * Update the file of the fragment with file value
415 *
416 * @param file
417 */
418 public void updateFile(OCFile file) {
419 setFile(file);
420 }
421
422 private void sendFile() {
423 stopPreview(false);
424 mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
425
426 }
427
428 private void seeDetails() {
429 stopPreview(false);
430 mContainerActivity.showDetails(getFile());
431 }
432
433
434 private void prepareVideo() {
435 // create helper to get more control on the playback
436 mVideoHelper = new VideoHelper();
437 mVideoPreview.setOnPreparedListener(mVideoHelper);
438 mVideoPreview.setOnCompletionListener(mVideoHelper);
439 mVideoPreview.setOnErrorListener(mVideoHelper);
440 }
441
442 @SuppressWarnings("static-access")
443 private void playVideo() {
444 // create and prepare control panel for the user
445 mMediaController.setMediaPlayer(mVideoPreview);
446
447 // load the video file in the video player ;
448 // when done, VideoHelper#onPrepared() will be called
449 if (getFile().isDown()) {
450 mUri = getFile().getStoragePath();
451 } else {
452 Context context = MainApp.getAppContext();
453 Account account = mContainerActivity.getStorageManager().getAccount();
454
455 mUri = generateUrlWithCredentials(account, context, getFile());
456 }
457
458 mVideoPreview.setVideoPath(mUri);
459 }
460
461 public static String generateUrlWithCredentials(Account account, Context context, OCFile file){
462 OwnCloudAccount ocAccount = null;
463 try {
464 ocAccount = new OwnCloudAccount(account, context);
465
466 final ClientGenerationTask task = new ClientGenerationTask();
467 task.execute(ocAccount);
468
469 OwnCloudClient mClient = task.get();
470 String url = AccountUtils.constructFullURLForAccount(context, account) + Uri.encode(file.getRemotePath(), "/");
471 OwnCloudCredentials credentials = mClient.getCredentials();
472
473 return url.replace("//", "//" + credentials.getUsername() + ":" + credentials.getAuthToken() + "@");
474
475 } catch (AccountUtils.AccountNotFoundException e) {
476 e.printStackTrace();
477
478 } catch (InterruptedException e) {
479 e.printStackTrace();
480 } catch (ExecutionException e) {
481 e.printStackTrace();
482 }
483 return "";
484 }
485
486 public static class ClientGenerationTask extends AsyncTask<Object, Void, OwnCloudClient> {
487 @Override
488 protected OwnCloudClient doInBackground(Object... params) {
489 Object account = params[0];
490 if (account instanceof OwnCloudAccount){
491 try {
492 OwnCloudAccount ocAccount = (OwnCloudAccount) account;
493 return OwnCloudClientManagerFactory.getDefaultSingleton().
494 getClientFor(ocAccount, MainApp.getAppContext());
495 } catch (AccountUtils.AccountNotFoundException e) {
496 e.printStackTrace();
497 } catch (OperationCanceledException e) {
498 e.printStackTrace();
499 } catch (AuthenticatorException e) {
500 e.printStackTrace();
501 } catch (IOException e) {
502 e.printStackTrace();
503 }
504 }
505
506 return null;
507 }
508 }
509
510
511 private class VideoHelper implements OnCompletionListener, OnPreparedListener, OnErrorListener {
512
513 /**
514 * Called when the file is ready to be played.
515 * <p/>
516 * Just starts the playback.
517 *
518 * @param vp {@link MediaPlayer} instance performing the playback.
519 */
520 @Override
521 public void onPrepared(MediaPlayer vp) {
522 Log_OC.e(TAG, "onPrepared");
523 mVideoPreview.seekTo(mSavedPlaybackPosition);
524 if (mAutoplay) {
525 mVideoPreview.start();
526 }
527 mMediaController.setEnabled(true);
528 mMediaController.updatePausePlay();
529 mPrepared = true;
530 }
531
532
533 /**
534 * Called when the file is finished playing.
535 * <p/>
536 * Finishes the activity.
537 *
538 * @param mp {@link MediaPlayer} instance performing the playback.
539 */
540 @Override
541 public void onCompletion(MediaPlayer mp) {
542 Log_OC.e(TAG, "completed");
543 if (mp != null) {
544 mVideoPreview.seekTo(0);
545 // next lines are necessary to work around undesired video loops
546 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.GINGERBREAD) {
547 mVideoPreview.pause();
548
549 } else {
550 if (Build.VERSION.SDK_INT == Build.VERSION_CODES.GINGERBREAD_MR1) {
551 // mVideePreview.pause() is not enough
552
553 mMediaController.setEnabled(false);
554 mVideoPreview.stopPlayback();
555 mAutoplay = false;
556 mSavedPlaybackPosition = 0;
557 mVideoPreview.setVideoPath(getFile().getStoragePath());
558 }
559 }
560 } // else : called from onError()
561 mMediaController.updatePausePlay();
562 }
563
564
565 /**
566 * Called when an error in playback occurs.
567 *
568 * @param mp {@link MediaPlayer} instance performing the playback.
569 * @param what Type of error
570 * @param extra Extra code specific to the error
571 */
572 @Override
573 public boolean onError(MediaPlayer mp, int what, int extra) {
574 // if (mVideoPreview.getWindowToken() != null) {
575 // try to open with another app
576 // try{
577 // AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
578 // builder.setMessage("May expose password?")
579 // .setPositiveButton("Stream", new DialogInterface.OnClickListener() {
580 // public void onClick(DialogInterface dialog, int id) {
581 // Intent i = new Intent(android.content.Intent.ACTION_VIEW);
582 // i.setData(Uri.parse(mUri));
583 // startActivity(i);
584 // }
585 // })
586 // .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
587 // public void onClick(DialogInterface dialog, int id) {
588 // // User cancelled the dialog
589 // }
590 // });
591 // builder.show();
592
593 MediaService.streamWithExternalApp(mUri, getActivity()).show();
594
595 // }
596 // catch (ActivityNotFoundException e){
597 // Intent i = new Intent(android.content.Intent.ACTION_VIEW);
598 // i.setData(Uri.parse(mUri));
599 // startActivity(i);
600 // }
601 // }
602 // }
603 return true;
604
605 }
606 }
607
608 @Override
609 public void onPause() {
610 Log_OC.e(TAG, "onPause");
611 super.onPause();
612 }
613
614 @Override
615 public void onResume() {
616 super.onResume();
617 Log_OC.e(TAG, "onResume");
618 }
619
620 @Override
621 public void onDestroy() {
622 Log_OC.e(TAG, "onDestroy");
623 super.onDestroy();
624 }
625
626 @Override
627 public void onStop() {
628 Log_OC.e(TAG, "onStop");
629
630 mPrepared = false;
631 if (mMediaServiceConnection != null) {
632 Log_OC.d(TAG, "Unbinding from MediaService ...");
633 if (mMediaServiceBinder != null && mMediaController != null) {
634 mMediaServiceBinder.unregisterMediaController(mMediaController);
635 }
636 getActivity().unbindService(mMediaServiceConnection);
637 mMediaServiceConnection = null;
638 mMediaServiceBinder = null;
639 }
640
641 super.onStop();
642 }
643
644 @Override
645 public boolean onTouch(View v, MotionEvent event) {
646 if (event.getAction() == MotionEvent.ACTION_DOWN && v == mVideoPreview) {
647 // added a margin on the left to avoid interfering with gesture to open navigation drawer
648 if (event.getX() / Resources.getSystem().getDisplayMetrics().density > 24.0) {
649 startFullScreenVideo();
650 }
651 return true;
652 }
653 return false;
654 }
655
656
657 private void startFullScreenVideo() {
658 Intent i = new Intent(getActivity(), PreviewVideoActivity.class);
659 i.putExtra(FileActivity.EXTRA_ACCOUNT, mAccount);
660 i.putExtra(FileActivity.EXTRA_FILE, getFile());
661 i.putExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, mVideoPreview.isPlaying());
662 mVideoPreview.pause();
663 i.putExtra(PreviewVideoActivity.EXTRA_START_POSITION, mVideoPreview.getCurrentPosition());
664 startActivityForResult(i, 0);
665 }
666
667 @Override
668 public void onConfigurationChanged(Configuration newConfig) {
669 Log_OC.e(TAG, "onConfigurationChanged " + this);
670 }
671
672 @Override
673 public void onActivityResult(int requestCode, int resultCode, Intent data) {
674 Log_OC.e(TAG, "onActivityResult " + this);
675 super.onActivityResult(requestCode, resultCode, data);
676 if (resultCode == Activity.RESULT_OK) {
677 mSavedPlaybackPosition = data.getExtras().getInt(
678 PreviewVideoActivity.EXTRA_START_POSITION);
679 mAutoplay = data.getExtras().getBoolean(PreviewVideoActivity.EXTRA_AUTOPLAY);
680 }
681 }
682
683
684 private void playAudio() {
685 OCFile file = getFile();
686 if (!mMediaServiceBinder.isPlaying(file)) {
687 Log_OC.d(TAG, "starting playback of " + file.getStoragePath());
688 mMediaServiceBinder.start(mAccount, file, mAutoplay, mSavedPlaybackPosition);
689
690 }
691 else {
692 if (!mMediaServiceBinder.isPlaying() && mAutoplay) {
693 mMediaServiceBinder.start();
694 mMediaController.updatePausePlay();
695 }
696 }
697 }
698
699
700 private void bindMediaService() {
701 Log_OC.d(TAG, "Binding to MediaService...");
702 if (mMediaServiceConnection == null) {
703 mMediaServiceConnection = new MediaServiceConnection();
704 }
705 getActivity().bindService( new Intent(getActivity(),
706 MediaService.class),
707 mMediaServiceConnection,
708 Context.BIND_AUTO_CREATE);
709 // follow the flow in MediaServiceConnection#onServiceConnected(...)
710 }
711
712 /** Defines callbacks for service binding, passed to bindService() */
713 private class MediaServiceConnection implements ServiceConnection {
714
715 @Override
716 public void onServiceConnected(ComponentName component, IBinder service) {
717 if (getActivity() != null) {
718 if (component.equals(
719 new ComponentName(getActivity(), MediaService.class))) {
720 Log_OC.d(TAG, "Media service connected");
721 mMediaServiceBinder = (MediaServiceBinder) service;
722 if (mMediaServiceBinder != null) {
723 prepareMediaController();
724 playAudio(); // do not wait for the touch of nobody to play audio
725
726 Log_OC.d(TAG, "Successfully bound to MediaService, MediaController ready");
727
728 }
729 else {
730 Log_OC.e(TAG, "Unexpected response from MediaService while binding");
731 }
732 }
733 }
734 }
735
736 private void prepareMediaController() {
737 mMediaServiceBinder.registerMediaController(mMediaController);
738 if (mMediaController != null) {
739 mMediaController.setMediaPlayer(mMediaServiceBinder);
740 mMediaController.setEnabled(true);
741 mMediaController.updatePausePlay();
742 }
743 }
744
745 @Override
746 public void onServiceDisconnected(ComponentName component) {
747 if (component.equals(new ComponentName(getActivity(), MediaService.class))) {
748 Log_OC.e(TAG, "Media service suddenly disconnected");
749 if (mMediaController != null) {
750 mMediaController.setMediaPlayer(null);
751 }
752 else {
753 Toast.makeText(
754 getActivity(),
755 "No media controller to release when disconnected from media service",
756 Toast.LENGTH_SHORT).show();
757 }
758 mMediaServiceBinder = null;
759 mMediaServiceConnection = null;
760 }
761 }
762 }
763
764
765 /**
766 * Opens the previewed file with an external application.
767 */
768 private void openFile() {
769 stopPreview(true);
770 mContainerActivity.getFileOperationsHelper().openFile(getFile());
771 finish();
772 }
773
774 /**
775 * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewMediaFragment}
776 * to be previewed.
777 *
778 * @param file File to test if can be previewed.
779 * @return 'True' if the file can be handled by the fragment.
780 */
781 public static boolean canBePreviewed(OCFile file) {
782 return (file != null && (file.isAudio() || file.isVideo()));
783 }
784
785
786 public void stopPreview(boolean stopAudio) {
787 OCFile file = getFile();
788 if (file.isAudio() && stopAudio) {
789 mMediaServiceBinder.pause();
790
791 }
792 else {
793 if (file.isVideo()) {
794 mVideoPreview.stopPlayback();
795 }
796 }
797 }
798
799
800 /**
801 * Finishes the preview
802 */
803 private void finish() {
804 getActivity().onBackPressed();
805 }
806
807
808 public int getPosition() {
809 if (mPrepared) {
810 mSavedPlaybackPosition = mVideoPreview.getCurrentPosition();
811 }
812 Log_OC.e(TAG, "getting position: " + mSavedPlaybackPosition);
813 return mSavedPlaybackPosition;
814 }
815
816 public boolean isPlaying() {
817 if (mPrepared) {
818 mAutoplay = mVideoPreview.isPlaying();
819 }
820 return mAutoplay;
821 }
822
823 }