Changed OCFile to keep mRemotePath as a valid URL; CLEAR YOUR CACHE AFTER INSTALLING
[pub/Android/ownCloud.git] / src / eu / alefzero / owncloud / ui / fragment / FileDetailFragment.java
1 /* ownCloud Android client application
2 * Copyright (C) 2011 Bartek Przybylski
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 3 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 package eu.alefzero.owncloud.ui.fragment;
19
20 import java.util.List;
21
22 import android.accounts.Account;
23 import android.accounts.AccountManager;
24 import android.content.BroadcastReceiver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.pm.PackageManager;
29 import android.graphics.Bitmap;
30 import android.graphics.BitmapFactory;
31 import android.net.Uri;
32 import android.os.Bundle;
33 import android.util.Log;
34 import android.view.LayoutInflater;
35 import android.view.View;
36 import android.view.View.OnClickListener;
37 import android.view.ViewGroup;
38 import android.widget.Button;
39 import android.widget.ImageView;
40 import android.widget.TextView;
41 import android.widget.Toast;
42
43 import com.actionbarsherlock.app.SherlockFragment;
44
45 import eu.alefzero.owncloud.DisplayUtils;
46 import eu.alefzero.owncloud.R;
47 import eu.alefzero.owncloud.authenticator.AccountAuthenticator;
48 import eu.alefzero.owncloud.datamodel.OCFile;
49 import eu.alefzero.owncloud.files.services.FileDownloader;
50 import eu.alefzero.owncloud.utils.OwnCloudVersion;
51
52 /**
53 * This Fragment is used to display the details about a file.
54 *
55 * @author Bartek Przybylski
56 *
57 */
58 public class FileDetailFragment extends SherlockFragment implements
59 OnClickListener {
60
61 public static final String EXTRA_FILE = "FILE";
62
63 private DownloadFinishReceiver mDownloadFinishReceiver;
64 private Intent mIntent;
65 private int mLayout;
66 private View mView;
67 private OCFile mFile;
68 private static final String TAG = "FileDetailFragment";
69
70 /**
71 * Default constructor - contains real layout
72 */
73 public FileDetailFragment(){
74 mLayout = R.layout.file_details_fragment;
75 }
76
77 /**
78 * Creates a dummy layout. For use if the user never has
79 * tapped on a file before
80 *
81 * @param useEmptyView If true, use empty layout
82 */
83 public FileDetailFragment(boolean useEmptyView){
84 if(useEmptyView){
85 mLayout = R.layout.file_details_empty;
86 } else {
87 mLayout = R.layout.file_details_fragment;
88 }
89 }
90
91 /**
92 * Use this when creating the fragment and display
93 * a file at the same time
94 *
95 * @param showDetailsIntent The Intent with the required parameters
96 * @see FileDetailFragment#updateFileDetails(Intent)
97 */
98 public FileDetailFragment(Intent showDetailsIntent) {
99 mIntent = showDetailsIntent;
100 mLayout = R.layout.file_details_fragment;
101 }
102
103 @Override
104 public void onResume() {
105 super.onResume();
106 mDownloadFinishReceiver = new DownloadFinishReceiver();
107 IntentFilter filter = new IntentFilter(
108 FileDownloader.DOWNLOAD_FINISH_MESSAGE);
109 getActivity().registerReceiver(mDownloadFinishReceiver, filter);
110 }
111
112 @Override
113 public void onPause() {
114 super.onPause();
115 getActivity().unregisterReceiver(mDownloadFinishReceiver);
116 mDownloadFinishReceiver = null;
117 }
118
119 @Override
120 public View onCreateView(LayoutInflater inflater, ViewGroup container,
121 Bundle savedInstanceState) {
122 View view = null;
123 view = inflater.inflate(mLayout, container, false);
124 mView = view;
125 if(mLayout == R.layout.file_details_fragment){
126 // Phones will launch an activity with this intent
127 if(mIntent == null){
128 mIntent = getActivity().getIntent();
129 }
130 updateFileDetails();
131 }
132
133 return view;
134 }
135
136 @Override
137 public View getView() {
138 return super.getView() == null ? mView : super.getView();
139 }
140
141 @Override
142 public void onClick(View v) {
143 Toast.makeText(getActivity(), "Downloading", Toast.LENGTH_LONG).show();
144 Intent i = new Intent(getActivity(), FileDownloader.class);
145 i.putExtra(FileDownloader.EXTRA_ACCOUNT,
146 mIntent.getParcelableExtra(FileDownloader.EXTRA_ACCOUNT));
147 i.putExtra(FileDownloader.EXTRA_REMOTE_PATH, mFile.getRemotePath());
148 i.putExtra(FileDownloader.EXTRA_FILE_PATH, mFile.getURLDecodedRemotePath());
149 i.putExtra(FileDownloader.EXTRA_FILE_SIZE, mFile.getFileLength());
150 getActivity().startService(i);
151 }
152
153 /**
154 * Can be used to get the file that is currently being displayed.
155 * @return The file on the screen.
156 */
157 public OCFile getDisplayedFile(){
158 return mFile;
159 }
160
161 /**
162 * Use this method to signal this Activity that it shall update its view.
163 *
164 * @param intent The {@link Intent} that contains extra information about
165 * this file The intent needs to have these extras:
166 * <p>
167 *
168 * {@link FileDetailFragment#EXTRA_FILE}: An {@link OCFile}
169 * {@link FileDownloader#EXTRA_ACCOUNT}: The Account that file
170 * belongs to (required for downloading)
171 */
172 public void updateFileDetails(Intent intent) {
173 mIntent = intent;
174 updateFileDetails();
175 }
176
177 /**
178 * Updates the view with all relevant details about that file.
179 */
180 private void updateFileDetails() {
181 mFile = mIntent.getParcelableExtra(EXTRA_FILE);
182 Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);
183
184 if (mFile != null) {
185 // set file details
186 setFilename(mFile.getFileName());
187 setFiletype(DisplayUtils.convertMIMEtoPrettyPrint(mFile
188 .getMimetype()));
189 setFilesize(mFile.getFileLength());
190 if(ocVersionSupportsTimeCreated()){
191 setTimeCreated(mFile.getCreationTimestamp());
192 }
193
194 setTimeModified(mFile.getModificationTimestamp());
195
196 // Update preview
197 if (mFile.getStoragePath() != null) {
198 try {
199 if (mFile.getMimetype().startsWith("image/")) {
200 ImageView preview = (ImageView) getView().findViewById(
201 R.id.fdPreview);
202 Bitmap bmp = BitmapFactory.decodeFile(mFile.getStoragePath());
203 preview.setImageBitmap(bmp);
204 }
205 } catch (OutOfMemoryError e) {
206 Log.e(TAG, "Out of memory occured for file with size " + mFile.getFileLength());
207 }
208 downloadButton.setText(R.string.filedetails_open);
209 downloadButton.setOnClickListener(new OnClickListener() {
210 @Override
211 public void onClick(View v) {
212 Intent i = new Intent(Intent.ACTION_VIEW);
213 i.setDataAndType(Uri.parse("file://"+mFile.getStoragePath()), mFile.getMimetype());
214 List list = getActivity().getPackageManager().queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY);
215 if (list.size() > 0) {
216 startActivity(i);
217 } else {
218 Toast.makeText(getActivity(), "There is no application to handle file " + mFile.getFileName(), Toast.LENGTH_SHORT).show();
219 }
220 }
221 });
222 } else {
223 // Make download button effective
224 downloadButton.setOnClickListener(this);
225 }
226 }
227 }
228
229 /**
230 * Updates the filename in view
231 * @param filename to set
232 */
233 private void setFilename(String filename) {
234 TextView tv = (TextView) getView().findViewById(R.id.fdFilename);
235 if (tv != null)
236 tv.setText(filename);
237 }
238
239 /**
240 * Updates the MIME type in view
241 * @param mimetype to set
242 */
243 private void setFiletype(String mimetype) {
244 TextView tv = (TextView) getView().findViewById(R.id.fdType);
245 if (tv != null)
246 tv.setText(mimetype);
247 }
248
249 /**
250 * Updates the file size in view
251 * @param filesize in bytes to set
252 */
253 private void setFilesize(long filesize) {
254 TextView tv = (TextView) getView().findViewById(R.id.fdSize);
255 if (tv != null)
256 tv.setText(DisplayUtils.bytesToHumanReadable(filesize));
257 }
258
259 /**
260 * Updates the time that the file was created in view
261 * @param milliseconds Unix time to set
262 */
263 private void setTimeCreated(long milliseconds){
264 TextView tv = (TextView) getView().findViewById(R.id.fdCreated);
265 TextView tvLabel = (TextView) getView().findViewById(R.id.fdCreatedLabel);
266 if(tv != null){
267 tv.setText(DisplayUtils.unixTimeToHumanReadable(milliseconds));
268 tv.setVisibility(View.VISIBLE);
269 tvLabel.setVisibility(View.VISIBLE);
270 }
271 }
272
273 /**
274 * Updates the time that the file was last modified
275 * @param milliseconds Unix time to set
276 */
277 private void setTimeModified(long milliseconds){
278 TextView tv = (TextView) getView().findViewById(R.id.fdModified);
279 if(tv != null){
280 tv.setText(DisplayUtils.unixTimeToHumanReadable(milliseconds));
281 }
282 }
283
284 /**
285 * In ownCloud 3.0.3 and 4.0.0 there is a bug that SabreDAV does not return
286 * the time that the file was created. There is a chance that this will
287 * be fixed in future versions. Use this method to check if this version of
288 * ownCloud has this fix.
289 * @return True, if ownCloud the ownCloud version is > 3.0.4 and 4.0.1
290 */
291 private boolean ocVersionSupportsTimeCreated(){
292 if(mIntent != null){
293 Account ocAccount = mIntent.getParcelableExtra(FileDownloader.EXTRA_ACCOUNT);
294 if(ocAccount != null){
295 AccountManager accManager = (AccountManager) getActivity().getSystemService(Context.ACCOUNT_SERVICE);
296 OwnCloudVersion ocVersion = new OwnCloudVersion(accManager
297 .getUserData(ocAccount, AccountAuthenticator.KEY_OC_VERSION));
298 if(ocVersion.compareTo(new OwnCloudVersion(0x030004)) >= 0 || ocVersion.compareTo(new OwnCloudVersion(0x040001)) >= 0){
299 return true;
300 }
301 }
302 }
303 return false;
304 }
305
306 /**
307 * Once the file download has finished -> update view
308 * @author Bartek Przybylski
309 */
310 private class DownloadFinishReceiver extends BroadcastReceiver {
311 @Override
312 public void onReceive(Context context, Intent intent) {
313 ((OCFile)mIntent.getParcelableExtra(EXTRA_FILE)).setStoragePath(intent.getStringExtra(FileDownloader.EXTRA_FILE_PATH));
314 updateFileDetails(mIntent);
315 }
316
317 }
318
319 }