Merge branch 'master' into sdcard-save
[pub/Android/ownCloud.git] / src / com / owncloud / android / utils / FileStorageUtils.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
21 package com.owncloud.android.utils;
22
23 import java.io.File;
24 import java.util.Collections;
25 import java.util.Comparator;
26 import java.util.Vector;
27
28 import third_parties.daveKoeller.AlphanumComparator;
29
30 import com.owncloud.android.MainApp;
31 import com.owncloud.android.R;
32 import com.owncloud.android.datamodel.OCFile;
33 import com.owncloud.android.lib.resources.files.RemoteFile;
34
35 import android.annotation.SuppressLint;
36 import android.content.Context;
37 import android.content.SharedPreferences;
38 import android.preference.PreferenceManager;
39 import android.net.Uri;
40 import android.os.Environment;
41 import android.os.StatFs;
42 import android.webkit.MimeTypeMap;
43
44
45 /**
46 * Static methods to help in access to local file system.
47 */
48 public class FileStorageUtils {
49 public static Integer mSortOrder;
50 public static Boolean mSortAscending;
51 public static final Integer SORT_NAME = 0;
52 public static final Integer SORT_DATE = 1;
53 public static final Integer SORT_SIZE = 2;
54
55
56 //private static final String TAG = FileStorageUtils.class.getSimpleName();
57
58 @SuppressLint("NewApi")
59 private static final File getBaseStorePath() {
60 File baseStoragePath = Environment.getExternalStorageDirectory();
61 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
62 File[] dirs = MainApp.getAppContext().getExternalFilesDirs(null);
63 if (dirs.length > 1) {
64 baseStoragePath = dirs[1];
65 }
66 }
67 return baseStoragePath;
68 }
69
70 @SuppressLint("NewApi")
71 private static final String getBaseStorePathString() {
72 File baseStoragePath = Environment.getExternalStorageDirectory();
73 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
74 File[] dirs = MainApp.getAppContext().getExternalFilesDirs(null);
75 if (dirs.length > 1) {
76 baseStoragePath = dirs[1];
77 }
78 return baseStoragePath.getAbsolutePath();
79 } else {
80 return baseStoragePath.getAbsolutePath() + "/" + MainApp.getDataFolder();
81 }
82 }
83
84
85 public static final String getSavePath(String accountName) {
86 //File sdCard = Environment.getExternalStorageDirectory();
87 //return sdCard.getAbsolutePath() + "/" + MainApp.getDataFolder() + "/" + Uri.encode(accountName, "@");
88 // URL encoding is an 'easy fix' to overcome that NTFS and FAT32 don't allow ":" in file names, that can be in the accountName since 0.1.190B
89 //return getBaseStorePath().getAbsolutePath() + "/" + Uri.encode(accountName, "@");
90 return getBaseStorePathString() + "/" + Uri.encode(accountName, "@");
91 }
92
93 public static final String getDefaultSavePathFor(String accountName, OCFile file) {
94 return getSavePath(accountName) + file.getRemotePath();
95 }
96
97 public static final String getTemporalPath(String accountName) {
98 //File sdCard = Environment.getExternalStorageDirectory();
99 //return sdCard.getAbsolutePath() + "/" + MainApp.getDataFolder() + "/tmp/" + Uri.encode(accountName, "@");
100 // URL encoding is an 'easy fix' to overcome that NTFS and FAT32 don't allow ":" in file names, that can be in the accountName since 0.1.190B
101 //return getBaseStorePath().getAbsolutePath() + "/tmp/" + Uri.encode(accountName, "@");
102 return getBaseStorePathString() + "/tmp/" + Uri.encode(accountName, "@");
103 }
104
105 @SuppressLint("NewApi")
106 public static final long getUsableSpace(String accountName) {
107 //File savePath = Environment.getExternalStorageDirectory();
108 File savePath = getBaseStorePath();
109 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
110 return savePath.getUsableSpace();
111
112 } else {
113 StatFs stats = new StatFs(savePath.getAbsolutePath());
114 return stats.getAvailableBlocks() * stats.getBlockSize();
115 }
116
117 }
118
119 public static final String getLogPath() {
120 return Environment.getExternalStorageDirectory() + File.separator + MainApp.getDataFolder() + File.separator + "log";
121 }
122
123 public static String getInstantUploadFilePath(Context context, String fileName) {
124 SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
125 String uploadPathdef = context.getString(R.string.instant_upload_path);
126 String uploadPath = pref.getString("instant_upload_path", uploadPathdef);
127 String value = uploadPath + OCFile.PATH_SEPARATOR + (fileName == null ? "" : fileName);
128 return value;
129 }
130
131 /**
132 * Gets the composed path when video is or must be stored
133 * @param context
134 * @param fileName: video file name
135 * @return String: video file path composed
136 */
137 public static String getInstantVideoUploadFilePath(Context context, String fileName) {
138 SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
139 String uploadVideoPathdef = context.getString(R.string.instant_upload_path);
140 String uploadVideoPath = pref.getString("instant_video_upload_path", uploadVideoPathdef);
141 String value = uploadVideoPath + OCFile.PATH_SEPARATOR + (fileName == null ? "" : fileName);
142 return value;
143 }
144
145 public static String getParentPath(String remotePath) {
146 String parentPath = new File(remotePath).getParent();
147 parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR;
148 return parentPath;
149 }
150
151 /**
152 * Creates and populates a new {@link OCFile} object with the data read from the server.
153 *
154 * @param remote remote file read from the server (remote file or folder).
155 * @return New OCFile instance representing the remote resource described by we.
156 */
157 public static OCFile fillOCFile(RemoteFile remote) {
158 OCFile file = new OCFile(remote.getRemotePath());
159 file.setCreationTimestamp(remote.getCreationTimestamp());
160 file.setFileLength(remote.getLength());
161 file.setMimetype(remote.getMimeType());
162 file.setModificationTimestamp(remote.getModifiedTimestamp());
163 file.setEtag(remote.getEtag());
164 file.setPermissions(remote.getPermissions());
165 file.setRemoteId(remote.getRemoteId());
166 return file;
167 }
168
169 /**
170 * Creates and populates a new {@link RemoteFile} object with the data read from an {@link OCFile}.
171 *
172 * @param ocFile OCFile
173 * @return New RemoteFile instance representing the resource described by ocFile.
174 */
175 public static RemoteFile fillRemoteFile(OCFile ocFile){
176 RemoteFile file = new RemoteFile(ocFile.getRemotePath());
177 file.setCreationTimestamp(ocFile.getCreationTimestamp());
178 file.setLength(ocFile.getFileLength());
179 file.setMimeType(ocFile.getMimetype());
180 file.setModifiedTimestamp(ocFile.getModificationTimestamp());
181 file.setEtag(ocFile.getEtag());
182 file.setPermissions(ocFile.getPermissions());
183 file.setRemoteId(ocFile.getRemoteId());
184 return file;
185 }
186
187 /**
188 * Sorts all filenames, regarding last user decision
189 */
190 public static Vector<OCFile> sortFolder(Vector<OCFile> files){
191 switch (mSortOrder){
192 case 0:
193 files = FileStorageUtils.sortByName(files);
194 break;
195 case 1:
196 files = FileStorageUtils.sortByDate(files);
197 break;
198 case 2:
199 // mFiles = FileStorageUtils.sortBySize(mSortAscending);
200 break;
201 }
202
203 return files;
204 }
205
206 /**
207 * Sorts list by Date
208 * @param files
209 */
210 public static Vector<OCFile> sortByDate(Vector<OCFile> files){
211 final Integer val;
212 if (mSortAscending){
213 val = 1;
214 } else {
215 val = -1;
216 }
217
218 Collections.sort(files, new Comparator<OCFile>() {
219 public int compare(OCFile o1, OCFile o2) {
220 if (o1.isFolder() && o2.isFolder()) {
221 Long obj1 = o1.getModificationTimestamp();
222 return val * obj1.compareTo(o2.getModificationTimestamp());
223 }
224 else if (o1.isFolder()) {
225 return -1;
226 } else if (o2.isFolder()) {
227 return 1;
228 } else if (o1.getModificationTimestamp() == 0 || o2.getModificationTimestamp() == 0){
229 return 0;
230 } else {
231 Long obj1 = o1.getModificationTimestamp();
232 return val * obj1.compareTo(o2.getModificationTimestamp());
233 }
234 }
235 });
236
237 return files;
238 }
239
240 // /**
241 // * Sorts list by Size
242 // * @param sortAscending true: ascending, false: descending
243 // */
244 // public static Vector<OCFile> sortBySize(Vector<OCFile> files){
245 // final Integer val;
246 // if (mSortAscending){
247 // val = 1;
248 // } else {
249 // val = -1;
250 // }
251 //
252 // Collections.sort(files, new Comparator<OCFile>() {
253 // public int compare(OCFile o1, OCFile o2) {
254 // if (o1.isFolder() && o2.isFolder()) {
255 // Long obj1 = getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o1)));
256 // return val * obj1.compareTo(getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o2))));
257 // }
258 // else if (o1.isFolder()) {
259 // return -1;
260 // } else if (o2.isFolder()) {
261 // return 1;
262 // } else if (o1.getFileLength() == 0 || o2.getFileLength() == 0){
263 // return 0;
264 // } else {
265 // Long obj1 = o1.getFileLength();
266 // return val * obj1.compareTo(o2.getFileLength());
267 // }
268 // }
269 // });
270 //
271 // return files;
272 // }
273
274 /**
275 * Sorts list by Name
276 * @param files files to sort
277 */
278 public static Vector<OCFile> sortByName(Vector<OCFile> files){
279 final Integer val;
280 if (mSortAscending){
281 val = 1;
282 } else {
283 val = -1;
284 }
285
286 Collections.sort(files, new Comparator<OCFile>() {
287 public int compare(OCFile o1, OCFile o2) {
288 if (o1.isFolder() && o2.isFolder()) {
289 return val * o1.getRemotePath().toLowerCase().compareTo(o2.getRemotePath().toLowerCase());
290 } else if (o1.isFolder()) {
291 return -1;
292 } else if (o2.isFolder()) {
293 return 1;
294 }
295 return val * new AlphanumComparator().compare(o1, o2);
296 }
297 });
298
299 return files;
300 }
301
302 /**
303 * Local Folder size
304 * @param dir File
305 * @return Size in bytes
306 */
307 public static long getFolderSize(File dir) {
308 if (dir.exists()) {
309 long result = 0;
310 File[] fileList = dir.listFiles();
311 for(int i = 0; i < fileList.length; i++) {
312 if(fileList[i].isDirectory()) {
313 result += getFolderSize(fileList[i]);
314 } else {
315 result += fileList[i].length();
316 }
317 }
318 return result;
319 }
320 return 0;
321 }
322
323 /**
324 * Mimetype String of a file
325 * @param path
326 * @return
327 */
328 public static String getMimeTypeFromName(String path) {
329 String extension = "";
330 int pos = path.lastIndexOf('.');
331 if (pos >= 0) {
332 extension = path.substring(pos + 1);
333 }
334 String result = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
335 return (result != null) ? result : "";
336 }
337
338 }