8147af7341f9b0a238a64077a1654fa408666d98
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / activity / VideoActivity.java
1 /* ownCloud Android client application
2 * Copyright (C) 2012-2013 ownCloud Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 package com.owncloud.android.ui.activity;
20
21 import android.accounts.Account;
22 import android.app.Activity;
23 import android.app.AlertDialog;
24 import android.content.DialogInterface;
25 import android.content.Intent;
26 import android.media.MediaPlayer;
27 import android.media.MediaPlayer.OnCompletionListener;
28 import android.media.MediaPlayer.OnErrorListener;
29 import android.media.MediaPlayer.OnPreparedListener;
30 import android.net.Uri;
31 import android.os.Bundle;
32 import android.util.Log;
33 import android.view.MotionEvent;
34 import android.widget.MediaController;
35 import android.widget.VideoView;
36
37 import com.owncloud.android.AccountUtils;
38 import com.owncloud.android.R;
39 import com.owncloud.android.datamodel.OCFile;
40 import com.owncloud.android.media.MediaService;
41
42 /**
43 * Activity implementing a basic video player.
44 *
45 * Used as an utility to preview video files contained in an ownCloud account.
46 *
47 * Currently, it always plays in landscape mode, full screen. When the playback ends,
48 * the activity is finished.
49 *
50 * @author David A. Velasco
51 */
52 public class VideoActivity extends Activity implements OnCompletionListener, OnPreparedListener, OnErrorListener {
53
54 /** Key to receive an {@link OCFile} to play as an extra value in an {@link Intent} */
55 public static final String EXTRA_FILE = "FILE";
56 /** Key to receive the ownCloud {@link Account} where the file to play is saved as an extra value in an {@link Intent} */
57 public static final String EXTRA_ACCOUNT = "ACCOUNT";
58
59 private static final String TAG = null;
60
61 private OCFile mFile; // video file to play
62 private Account mAccount; // ownCloud account holding mFile
63 private VideoView mVideoPlayer; // view to play the file; both performs and show the playback
64 private MediaController mMediaController; // panel control used by the user to control the playback
65
66 /**
67 * Called when the activity is first created.
68 *
69 * Searches for an {@link OCFile} and ownCloud {@link Account} holding it in the starting {@link Intent}.
70 *
71 * The {@link Account} is unnecessary if the file is downloaded; else, the {@link Account} is used to
72 * try to stream the remote file - TODO get the streaming works
73 *
74 * {@inheritDoc}
75 */
76 @Override
77 public void onCreate(Bundle savedInstanceState) {
78 super.onCreate(savedInstanceState);
79
80 setContentView(R.layout.video_layout);
81
82 mFile = getIntent().getExtras().getParcelable(EXTRA_FILE);
83 mAccount = getIntent().getExtras().getParcelable(EXTRA_ACCOUNT);
84
85 mVideoPlayer = (VideoView) findViewById(R.id.videoPlayer);
86
87 // set listeners to get more contol on the playback
88 mVideoPlayer.setOnPreparedListener(this);
89 mVideoPlayer.setOnCompletionListener(this);
90 mVideoPlayer.setOnErrorListener(this);
91
92 // keep the screen on while the playback is performed (prevents screen off by battery save)
93 mVideoPlayer.setKeepScreenOn(true);
94
95 if (mFile != null) {
96 if (mFile.isDown()) {
97 mVideoPlayer.setVideoPath(mFile.getStoragePath());
98
99 } else if (mAccount != null) {
100 String url = AccountUtils.constructFullURLForAccount(this, mAccount) + mFile.getRemotePath();
101 mVideoPlayer.setVideoURI(Uri.parse(url));
102
103 } else {
104 onError(null, MediaService.OC_MEDIA_ERROR, R.string.media_err_no_account);
105 }
106
107 // create and prepare control panel for the user
108 mMediaController = new MediaController(this);
109 mMediaController.setMediaPlayer(mVideoPlayer);
110 mMediaController.setAnchorView(mVideoPlayer);
111 mVideoPlayer.setMediaController(mMediaController);
112
113 } else {
114 onError(null, MediaService.OC_MEDIA_ERROR, R.string.media_err_nothing_to_play);
115 }
116 }
117
118
119 /**
120 * Called when the file is ready to be played.
121 *
122 * Just starts the playback.
123 *
124 * @param mp {@link MediaPlayer} instance performing the playback.
125 */
126 @Override
127 public void onPrepared(MediaPlayer vp) {
128 mVideoPlayer.start();
129 mMediaController.show(5000);
130 }
131
132
133 /**
134 * Called when the file is finished playing.
135 *
136 * Finishes the activity.
137 *
138 * @param mp {@link MediaPlayer} instance performing the playback.
139 */
140 @Override
141 public void onCompletion(MediaPlayer mp) {
142 this.finish();
143 }
144
145
146 /**
147 * Called when an error in playback occurs.
148 *
149 * @param mp {@link MediaPlayer} instance performing the playback.
150 * @param what Type of error
151 * @param extra Extra code specific to the error
152 */
153 @Override
154 public boolean onError(MediaPlayer mp, int what, int extra) {
155 Log.e(TAG, "Error in video playback, what = " + what + ", extra = " + extra);
156
157 if (mMediaController != null) {
158 mMediaController.hide();
159 }
160
161 if (mVideoPlayer.getWindowToken() != null) {
162 int messageId;
163 if (what == MediaService.OC_MEDIA_ERROR) {
164 messageId = extra;
165
166 } else if (what == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
167 messageId = android.R.string.VideoView_error_text_invalid_progressive_playback;
168
169 } else {
170 // what == MediaPlayer.MEDIA_ERROR_UNKNOWN or MEDIA_ERROR_SERVER_DIED
171 messageId = android.R.string.VideoView_error_text_unknown;
172
173 }
174 new AlertDialog.Builder(this)
175 .setMessage(messageId)
176 .setPositiveButton(android.R.string.VideoView_error_button,
177 new DialogInterface.OnClickListener() {
178 public void onClick(DialogInterface dialog, int whichButton) {
179 VideoActivity.this.onCompletion(null);
180 }
181 })
182 .setCancelable(false)
183 .show();
184 }
185
186
187 /*
188 switch (what) {
189 case MediaPlayer.MEDIA_ERROR_UNKNOWN:
190 /*Added in API level 1
191 Unspecified media player error.
192 Constant Value: 1 (0x00000001)
193 *-/
194 break;
195
196 case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
197 /* Added in API level 1
198 Media server died. In this case, the application must release the MediaPlayer object and instantiate a new one.
199 Constant Value: 100 (0x00000064) *-/
200 break;
201
202 case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
203 /* Added in API level 3
204 The video is streamed and its container is not valid for progressive playback i.e the video's index (e.g moov atom) is not at the start of the file.
205 See Also
206 MediaPlayer.OnErrorListener
207 Constant Value: 200 (0x000000c8)
208 *-/
209 break;
210
211 /// under this, seems they are values for extra
212 case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
213 /* Added in API level 17
214 Bitstream is conforming to the related coding standard or file spec, but the media framework does not support the feature.
215 Constant Value: -1010 (0xfffffc0e)
216 *-/
217 break;
218
219 case MediaPlayer.MEDIA_ERROR_IO:
220 /* Added in API level 17
221 File or network related operation errors.
222 Constant Value: -1004 (0xfffffc14) *-/
223 break;
224
225 case MediaPlayer.MEDIA_ERROR_MALFORMED:
226 /* Added in API level 17
227 Bitstream is not conforming to the related coding standard or file spec.
228 Constant Value: -1007 (0xfffffc11) *-/
229 break;
230
231 case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
232 /*Added in API level 17
233 Some operation takes too long to complete, usually more than 3-5 seconds.
234 Constant Value: -110 (0xffffff92)
235 *-/
236 break;
237 }
238 */
239
240 return true;
241 }
242
243
244 /**
245 * Screen touches trigger the appearance of the control panel for a limited time.
246 *
247 * {@inheritDoc}
248 */
249 @Override
250 public boolean onTouchEvent (MotionEvent ev){
251 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
252 mMediaController.show(MediaService.MEDIA_CONTROL_LIFE);
253 return true;
254 } else {
255 return false;
256 }
257 }
258
259
260 }