fbd0ce2d18b79b42927fb64e4a2fed9a9d897b06
[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
41 /**
42 * Activity implementing a basic video player.
43 *
44 * Used as an utility to preview video files contained in an ownCloud account.
45 *
46 * Currently, it always plays in landscape mode, full screen. When the playback ends,
47 * the activity is finished.
48 *
49 * @author David A. Velasco
50 */
51 public class VideoActivity extends Activity implements OnCompletionListener, OnPreparedListener, OnErrorListener {
52
53 /** Key to receive an {@link OCFile} to play as an extra value in an {@link Intent} */
54 public static final String EXTRA_FILE = "FILE";
55 /** Key to receive the ownCloud {@link Account} where the file to play is saved as an extra value in an {@link Intent} */
56 public static final String EXTRA_ACCOUNT = "ACCOUNT";
57
58 // Time To keep the control panel visible when the user does not use it
59 private static final int MEDIA_CONTOL_LIFE = 5000;
60
61 private static final int OC_MEDIA_ERROR = 0;
62 private static final String TAG = null;
63
64 private OCFile mFile; // video file to play
65 private Account mAccount; // ownCloud account holding mFile
66 private VideoView mVideoPlayer; // view to play the file; both performs and show the playback
67 private MediaController mMediaController; // panel control used by the user to control the playback
68
69 /**
70 * Called when the activity is first created.
71 *
72 * Searches for an {@link OCFile} and ownCloud {@link Account} holding it in the starting {@link Intent}.
73 *
74 * The {@link Account} is unnecessary if the file is downloaded; else, the {@link Account} is used to
75 * try to stream the remote file - TODO get the streaming works
76 *
77 * {@inheritDoc}
78 */
79 @Override
80 public void onCreate(Bundle savedInstanceState) {
81 super.onCreate(savedInstanceState);
82
83 setContentView(R.layout.video_layout);
84
85 mFile = getIntent().getExtras().getParcelable(EXTRA_FILE);
86 mAccount = getIntent().getExtras().getParcelable(EXTRA_ACCOUNT);
87
88 mVideoPlayer = (VideoView) findViewById(R.id.videoPlayer);
89
90 // set listeners to get more contol on the playback
91 mVideoPlayer.setOnPreparedListener(this);
92 mVideoPlayer.setOnCompletionListener(this);
93 mVideoPlayer.setOnErrorListener(this);
94
95 // keep the screen on while the playback is performed (prevents screen off by battery save)
96 mVideoPlayer.setKeepScreenOn(true);
97
98 if (mFile != null) {
99 if (mFile.isDown()) {
100 mVideoPlayer.setVideoPath(mFile.getStoragePath());
101
102 } else if (mAccount != null) {
103 String url = AccountUtils.constructFullURLForAccount(this, mAccount) + mFile.getRemotePath();
104 mVideoPlayer.setVideoURI(Uri.parse(url));
105
106 } else {
107 onError(null, OC_MEDIA_ERROR, R.string.media_err_no_account);
108 }
109
110 // create and prepare control panel for the user
111 mMediaController = new MediaController(this);
112 mMediaController.setMediaPlayer(mVideoPlayer);
113 mMediaController.setAnchorView(mVideoPlayer);
114 mVideoPlayer.setMediaController(mMediaController);
115
116 } else {
117 onError(null, OC_MEDIA_ERROR, R.string.media_err_nothing_to_play);
118 }
119 }
120
121
122 /**
123 * Called when the file is ready to be played.
124 *
125 * Just starts the playback.
126 *
127 * @param mp {@link MediaPlayer} instance performing the playback.
128 */
129 @Override
130 public void onPrepared(MediaPlayer vp) {
131 mVideoPlayer.start(); // TODO maybe unnecessary
132 //mMediaController.show(5000); // TODO maybe unnecessary; maybe not, it's up when the Surface notifies the VideoView about creation
133 }
134
135
136 /**
137 * Called when the file is finished playing.
138 *
139 * Finishes the activity.
140 *
141 * @param mp {@link MediaPlayer} instance performing the playback.
142 */
143 @Override
144 public void onCompletion(MediaPlayer mp) {
145 this.finish();
146 }
147
148
149 /**
150 * Called when an error in playback occurs.
151 *
152 * @param mp {@link MediaPlayer} instance performing the playback.
153 * @param what Type of error
154 * @param extra Extra code specific to the error
155 */
156 @Override
157 public boolean onError(MediaPlayer mp, int what, int extra) {
158 Log.e(TAG, "Error in video playback, what = " + what + ", extra = " + extra);
159
160 if (mMediaController != null) {
161 mMediaController.hide();
162 }
163
164 if (mVideoPlayer.getWindowToken() != null) {
165 int messageId;
166 if (what == OC_MEDIA_ERROR) {
167 messageId = extra;
168
169 } else if (what == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
170 messageId = android.R.string.VideoView_error_text_invalid_progressive_playback;
171
172 } else {
173 // what == MediaPlayer.MEDIA_ERROR_UNKNOWN or MEDIA_ERROR_SERVER_DIED
174 messageId = android.R.string.VideoView_error_text_unknown;
175
176 }
177 new AlertDialog.Builder(this)
178 .setMessage(messageId)
179 .setPositiveButton(android.R.string.VideoView_error_button,
180 new DialogInterface.OnClickListener() {
181 public void onClick(DialogInterface dialog, int whichButton) {
182 VideoActivity.this.onCompletion(null);
183 }
184 })
185 .setCancelable(false)
186 .show();
187 }
188
189
190 /*
191 switch (what) {
192 case MediaPlayer.MEDIA_ERROR_UNKNOWN:
193 /*Added in API level 1
194 Unspecified media player error.
195 Constant Value: 1 (0x00000001)
196 *-/
197 break;
198
199 case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
200 /* Added in API level 1
201 Media server died. In this case, the application must release the MediaPlayer object and instantiate a new one.
202 Constant Value: 100 (0x00000064) *-/
203 break;
204
205 case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
206 /* Added in API level 3
207 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.
208 See Also
209 MediaPlayer.OnErrorListener
210 Constant Value: 200 (0x000000c8)
211 *-/
212 break;
213
214 /// under this, seems they are values for extra
215 case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
216 /* Added in API level 17
217 Bitstream is conforming to the related coding standard or file spec, but the media framework does not support the feature.
218 Constant Value: -1010 (0xfffffc0e)
219 *-/
220 break;
221
222 case MediaPlayer.MEDIA_ERROR_IO:
223 /* Added in API level 17
224 File or network related operation errors.
225 Constant Value: -1004 (0xfffffc14) *-/
226 break;
227
228 case MediaPlayer.MEDIA_ERROR_MALFORMED:
229 /* Added in API level 17
230 Bitstream is not conforming to the related coding standard or file spec.
231 Constant Value: -1007 (0xfffffc11) *-/
232 break;
233
234 case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
235 /*Added in API level 17
236 Some operation takes too long to complete, usually more than 3-5 seconds.
237 Constant Value: -110 (0xffffff92)
238 *-/
239 break;
240 }
241 */
242
243 return true;
244 }
245
246
247 /**
248 * Screen touches trigger the appearance of the control panel for a limited time.
249 *
250 * {@inheritDoc}
251 */
252 @Override
253 public boolean onTouchEvent (MotionEvent ev){
254 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
255 mMediaController.show(MEDIA_CONTOL_LIFE);
256 return true;
257 } else {
258 return false;
259 }
260 }
261
262
263 }