Merge pull request #746 from owncloud/thumbnailForUpload

Thumbnails added to Upload activity
This commit is contained in:
David A. Velasco 2015-01-14 08:25:04 +01:00
commit 9bf4e0f7b9
6 changed files with 365 additions and 234 deletions

View file

@ -29,10 +29,8 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.AsyncTask;
@ -76,7 +74,7 @@ public class ThumbnailsCacheManager {
public static Bitmap mDefaultImg =
BitmapFactory.decodeResource(
MainApp.getAppContext().getResources(),
DisplayUtils.getResourceId("image/png", "default.png")
DisplayUtils.getFileTypeIconId("image/png", "default.png")
);
@ -139,12 +137,208 @@ public class ThumbnailsCacheManager {
return null;
}
public static boolean cancelPotentialWork(OCFile file, ImageView imageView) {
public static class ThumbnailGenerationTask extends AsyncTask<Object, Void, Bitmap> {
private final WeakReference<ImageView> mImageViewReference;
private static Account mAccount;
private Object mFile;
private FileDataStorageManager mStorageManager;
public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, Account account) {
// Use a WeakReference to ensure the ImageView can be garbage collected
mImageViewReference = new WeakReference<ImageView>(imageView);
if (storageManager == null)
throw new IllegalArgumentException("storageManager must not be NULL");
mStorageManager = storageManager;
mAccount = account;
}
public ThumbnailGenerationTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
mImageViewReference = new WeakReference<ImageView>(imageView);
}
@Override
protected Bitmap doInBackground(Object... params) {
Bitmap thumbnail = null;
try {
if (mAccount != null) {
AccountManager accountMgr = AccountManager.get(MainApp.getAppContext());
mServerVersion = accountMgr.getUserData(mAccount, Constants.KEY_OC_VERSION);
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, MainApp.getAppContext());
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
getClientFor(ocAccount, MainApp.getAppContext());
}
mFile = params[0];
if (mFile instanceof OCFile) {
thumbnail = doOCFileInBackground();
} else if (mFile instanceof File) {
thumbnail = doFileInBackground();
} else {
// do nothing
}
}catch(Throwable t){
// the app should never break due to a problem with thumbnails
Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t);
if (t instanceof OutOfMemoryError) {
System.gc();
}
}
return thumbnail;
}
protected void onPostExecute(Bitmap bitmap){
if (isCancelled()) {
bitmap = null;
}
if (mImageViewReference != null && bitmap != null) {
final ImageView imageView = mImageViewReference.get();
final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (this == bitmapWorkerTask && imageView != null) {
String tagId = "";
if (mFile instanceof OCFile){
tagId = String.valueOf(((OCFile)mFile).getFileId());
} else if (mFile instanceof File){
tagId = String.valueOf(((File)mFile).hashCode());
}
if (String.valueOf(imageView.getTag()).equals(tagId)) {
imageView.setImageBitmap(bitmap);
}
}
}
}
/**
* Add thumbnail to cache
* @param imageKey: thumb key
* @param bitmap: image for extracting thumbnail
* @param path: image path
* @param px: thumbnail dp
* @return Bitmap
*/
private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int px){
Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
// Rotate image, obeying exif tag
thumbnail = BitmapUtils.rotateImage(thumbnail,path);
// Add thumbnail to cache
addBitmapToCache(imageKey, thumbnail);
return thumbnail;
}
/**
* Converts size of file icon from dp to pixel
* @return int
*/
private int getThumbnailDimension(){
// Converts dp to pixel
Resources r = MainApp.getAppContext().getResources();
return (int) Math.round(r.getDimension(R.dimen.file_icon_size));
}
private Bitmap doOCFileInBackground() {
Bitmap thumbnail = null;
OCFile file = (OCFile)mFile;
final String imageKey = String.valueOf(file.getRemoteId());
// Check disk cache in background thread
thumbnail = getBitmapFromDiskCache(imageKey);
// Not found in disk cache
if (thumbnail == null || file.needsUpdateThumbnail()) {
int px = getThumbnailDimension();
if (file.isDown()) {
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
file.getStoragePath(), px, px);
if (bitmap != null) {
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), px);
file.setNeedsUpdateThumbnail(false);
mStorageManager.saveFile(file);
}
} else {
// Download thumbnail from server
if (mClient != null && mServerVersion != null) {
OwnCloudVersion serverOCVersion = new OwnCloudVersion(mServerVersion);
if (serverOCVersion.compareTo(new OwnCloudVersion(MINOR_SERVER_VERSION_FOR_THUMBS)) >= 0) {
try {
int status = -1;
String uri = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" +
px + "/" + px + Uri.encode(file.getRemotePath(), "/");
Log_OC.d("Thumbnail", "URI: " + uri);
GetMethod get = new GetMethod(uri);
status = mClient.executeMethod(get);
if (status == HttpStatus.SC_OK) {
byte[] bytes = get.getResponseBody();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
// Add thumbnail to cache
if (thumbnail != null) {
addBitmapToCache(imageKey, thumbnail);
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
Log_OC.d(TAG, "Server too old");
}
}
}
}
return thumbnail;
}
private Bitmap doFileInBackground() {
Bitmap thumbnail = null;
File file = (File)mFile;
final String imageKey = String.valueOf(file.hashCode());
// Check disk cache in background thread
thumbnail = getBitmapFromDiskCache(imageKey);
// Not found in disk cache
if (thumbnail == null) {
int px = getThumbnailDimension();
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
file.getAbsolutePath(), px, px);
if (bitmap != null) {
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px);
}
}
return thumbnail;
}
}
public static boolean cancelPotentialWork(Object file, ImageView imageView) {
final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
if (bitmapWorkerTask != null) {
final OCFile bitmapData = bitmapWorkerTask.mFile;
final Object bitmapData = bitmapWorkerTask.mFile;
// If bitmapData is not yet set or it differs from the new data
if (bitmapData == null || bitmapData != file) {
// Cancel previous task
@ -157,7 +351,7 @@ public class ThumbnailsCacheManager {
// No task associated with the ImageView, or an existing task was cancelled
return true;
}
public static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
if (imageView != null) {
final Drawable drawable = imageView.getDrawable();
@ -165,162 +359,24 @@ public class ThumbnailsCacheManager {
final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
return asyncDrawable.getBitmapWorkerTask();
}
}
return null;
}
public static class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {
private final WeakReference<ImageView> mImageViewReference;
private static Account mAccount;
private OCFile mFile;
private FileDataStorageManager mStorageManager;
public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, Account account) {
// Use a WeakReference to ensure the ImageView can be garbage collected
mImageViewReference = new WeakReference<ImageView>(imageView);
if (storageManager == null)
throw new IllegalArgumentException("storageManager must not be NULL");
mStorageManager = storageManager;
mAccount = account;
}
// Decode image in background.
@Override
protected Bitmap doInBackground(OCFile... params) {
Bitmap thumbnail = null;
try {
if (mAccount != null) {
AccountManager accountMgr = AccountManager.get(MainApp.getAppContext());
mServerVersion = accountMgr.getUserData(mAccount, Constants.KEY_OC_VERSION);
OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, MainApp.getAppContext());
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
getClientFor(ocAccount, MainApp.getAppContext());
}
mFile = params[0];
final String imageKey = String.valueOf(mFile.getRemoteId());
// Check disk cache in background thread
thumbnail = getBitmapFromDiskCache(imageKey);
// Not found in disk cache
if (thumbnail == null || mFile.needsUpdateThumbnail()) {
// Converts dp to pixel
Resources r = MainApp.getAppContext().getResources();
int px = (int) Math.round(r.getDimension(R.dimen.file_icon_size));
if (mFile.isDown()){
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
mFile.getStoragePath(), px, px);
if (bitmap != null) {
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
// Rotate image, obeying exif tag
thumbnail = BitmapUtils.rotateImage(thumbnail, mFile.getStoragePath());
// Add thumbnail to cache
addBitmapToCache(imageKey, thumbnail);
mFile.setNeedsUpdateThumbnail(false);
mStorageManager.saveFile(mFile);
}
} else {
// Download thumbnail from server
if (mClient != null && mServerVersion != null) {
OwnCloudVersion serverOCVersion = new OwnCloudVersion(mServerVersion);
if (serverOCVersion.compareTo(new OwnCloudVersion(MINOR_SERVER_VERSION_FOR_THUMBS)) >= 0) {
try {
int status = -1;
String uri = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" +
px + "/" + px + Uri.encode(mFile.getRemotePath(), "/");
Log_OC.d("Thumbnail", "URI: " + uri);
GetMethod get = new GetMethod(uri);
status = mClient.executeMethod(get);
if (status == HttpStatus.SC_OK) {
byte[] bytes = get.getResponseBody();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
// Add thumbnail to cache
if (thumbnail != null) {
addBitmapToCache(imageKey, thumbnail);
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
Log_OC.d(TAG, "Server too old");
}
}
}
}
} catch (Throwable t) {
// the app should never break due to a problem with thumbnails
Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t);
if (t instanceof OutOfMemoryError) {
System.gc();
}
}
return thumbnail;
}
protected void onPostExecute(Bitmap bitmap){
if (isCancelled()) {
bitmap = null;
}
if (mImageViewReference != null && bitmap != null) {
final ImageView imageView = mImageViewReference.get();
final ThumbnailGenerationTask bitmapWorkerTask =
getBitmapWorkerTask(imageView);
if (this == bitmapWorkerTask && imageView != null) {
if (imageView.getTag().equals(mFile.getFileId())) {
imageView.setImageBitmap(bitmap);
}
}
}
}
return null;
}
public static class AsyncDrawable extends BitmapDrawable {
private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
public AsyncDrawable(
Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask
) {
) {
super(res, bitmap);
bitmapWorkerTaskReference =
new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
new WeakReference<ThumbnailGenerationTask>(bitmapWorkerTask);
}
public ThumbnailGenerationTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
/**
* Remove from cache the remoteId passed
* @param fileRemoteId: remote id of mFile passed
*/
public static void removeFileFromCache(String fileRemoteId){
synchronized (mThumbnailsDiskCacheLock) {
if (mThumbnailCache != null) {
mThumbnailCache.removeKey(fileRemoteId);
}
mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads
}
}
}

View file

@ -17,7 +17,7 @@
*/
package com.owncloud.android.ui.adapter;
import java.io.File;
import java.util.Collections;
import java.util.Comparator;
@ -44,13 +44,12 @@ import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncDrawable;
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
import com.owncloud.android.ui.activity.ComponentsGetter;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.FileStorageUtils;
/**
* This Adapter populates a ListView with all files and folders in an ownCloud
@ -60,7 +59,7 @@ import com.owncloud.android.utils.FileStorageUtils;
* @author Tobias Kaminsky
* @author David A. Velasco
*/
public class FileListListAdapter extends BaseAdapter implements ListAdapter {
public class FileListListAdapter extends BaseAdapter implements ListAdapter {
private final static String PERMISSION_SHARED_WITH_ME = "S";
private Context mContext;
@ -68,8 +67,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
private Vector<OCFile> mFiles = null;
private boolean mJustFolders;
private FileDataStorageManager mStorageManager;
private Account mAccount;
private FileDataStorageManager mStorageManager;
private Account mAccount;
private ComponentsGetter mTransferServiceGetter;
private SharedPreferences mAppPreferences;
@ -83,22 +82,22 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
mJustFolders = justFolders;
mContext = context;
mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);
mTransferServiceGetter = transferServiceGetter;
mTransferServiceGetter = transferServiceGetter;
mAppPreferences = PreferenceManager
.getDefaultSharedPreferences(mContext);
// Read sorting order, default to sort by name ascending
FileStorageUtils.mSortOrder = mAppPreferences
.getInt("sortOrder", 0);
FileStorageUtils.mSortAscending = mAppPreferences.getBoolean("sortAscending", true);
FileStorageUtils.mSortOrder = mAppPreferences.getInt("sortOrder", 0);
FileStorageUtils.mSortAscending = mAppPreferences.getBoolean("sortAscending", true);
// initialise thumbnails cache on background thread
new ThumbnailsCacheManager.InitDiskCacheTask().execute();
}
@Override
public boolean areAllItemsEnabled() {
return true;
@ -210,16 +209,18 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
if (thumbnail != null && !file.needsUpdateThumbnail()){
fileIcon.setImageBitmap(thumbnail);
} else {
// generate new Thumbnail
if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
new ThumbnailsCacheManager.ThumbnailGenerationTask(
fileIcon, mStorageManager, mAccount
);
if (thumbnail == null) {
thumbnail = ThumbnailsCacheManager.mDefaultImg;
}
final AsyncDrawable asyncDrawable = new AsyncDrawable(
final ThumbnailsCacheManager.AsyncDrawable asyncDrawable =
new ThumbnailsCacheManager.AsyncDrawable(
mContext.getResources(),
thumbnail,
task
@ -229,11 +230,9 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
}
}
} else {
fileIcon.setImageResource(
DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())
);
fileIcon.setImageResource(DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName()));
}
if (checkIfFileIsSharedWithMe(file)) {
sharedWithMeIconV.setVisibility(View.VISIBLE);
}
@ -246,7 +245,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
// } else {
fileSizeV.setVisibility(View.INVISIBLE);
// }
lastModV.setVisibility(View.VISIBLE);
lastModV.setText(showRelativeTimestamp(file));
checkBoxV.setVisibility(View.GONE);
@ -257,7 +256,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
sharedWithMeIconV.setVisibility(View.VISIBLE);
} else {
fileIcon.setImageResource(
DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())
DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName())
);
}
@ -277,7 +276,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
return view;
}
/**
* Local Folder size in human readable format
*
@ -297,8 +296,27 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
return "0 B";
}
/**
* Local Folder size
* @param dir File
* @return Size in bytes
*/
private long getFolderSize(File dir) {
if (dir.exists()) {
long result = 0;
File[] fileList = dir.listFiles();
for(int i = 0; i < fileList.length; i++) {
if(fileList[i].isDirectory()) {
result += getFolderSize(fileList[i]);
} else {
result += fileList[i].length();
}
}
return result;
}
return 0;
}
@Override
public int getViewTypeCount() {
return 1;
@ -382,7 +400,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
FileStorageUtils.mSortOrder = order;
FileStorageUtils.mSortAscending = ascending;
mFiles = FileStorageUtils.sortFolder(mFiles);
notifyDataSetChanged();
@ -391,6 +409,5 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
private CharSequence showRelativeTimestamp(OCFile file){
return DisplayUtils.getRelativeDateTimeString(mContext, file.getModificationTimestamp(),
DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0);
}
}
}

View file

@ -22,6 +22,7 @@ import java.util.Arrays;
import java.util.Comparator;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -32,6 +33,8 @@ import android.widget.ListView;
import android.widget.TextView;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.utils.BitmapUtils;
import com.owncloud.android.utils.DisplayUtils;
/**
@ -46,7 +49,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
private Context mContext;
private File mDirectory;
private File[] mFiles = null;
public LocalFileListAdapter(File directory, Context context) {
mContext = context;
swapDirectory(directory);
@ -105,6 +108,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
} else {
fileIcon.setImageResource(R.drawable.ic_menu_archive);
}
fileIcon.setTag(file.hashCode());
TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);
TextView lastModV = (TextView) view.findViewById(R.id.last_mod);
@ -125,6 +129,37 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
}
checkBoxV.setVisibility(View.VISIBLE);
}
// get Thumbnail if file is image
if (BitmapUtils.isImage(file)){
// Thumbnail in Cache?
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
String.valueOf(file.hashCode())
);
if (thumbnail != null){
fileIcon.setImageBitmap(thumbnail);
} else {
// generate new Thumbnail
if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
new ThumbnailsCacheManager.ThumbnailGenerationTask(fileIcon);
if (thumbnail == null) {
thumbnail = ThumbnailsCacheManager.mDefaultImg;
}
final ThumbnailsCacheManager.AsyncDrawable asyncDrawable =
new ThumbnailsCacheManager.AsyncDrawable(
mContext.getResources(),
thumbnail,
task
);
fileIcon.setImageDrawable(asyncDrawable);
task.execute(file);
}
}
} else {
fileIcon.setImageResource(DisplayUtils.getFileTypeIconId(null, file.getName()));
}
} else {
fileSizeV.setVisibility(View.GONE);
@ -132,7 +167,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
checkBoxV.setVisibility(View.GONE);
}
view.findViewById(R.id.imageView2).setVisibility(View.INVISIBLE); // not GONE; the alignment changes; ugly way to keep it
view.findViewById(R.id.imageView2).setVisibility(View.INVISIBLE); // not GONE; the alignment would change
view.findViewById(R.id.imageView3).setVisibility(View.GONE);
view.findViewById(R.id.sharedIcon).setVisibility(View.GONE);

View file

@ -396,7 +396,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
}
ImageView iv = (ImageView) getView().findViewById(R.id.fdIcon);
if (iv != null) {
iv.setImageResource(DisplayUtils.getResourceId(mimetype, filename));
iv.setImageResource(DisplayUtils.getFileTypeIconId(mimetype, filename));
}
}

View file

@ -23,6 +23,10 @@ import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.BitmapFactory.Options;
import android.media.ExifInterface;
import android.net.Uri;
import android.webkit.MimeTypeMap;
import java.io.File;
/**
* Utility class with methods for decoding Bitmaps.
@ -169,6 +173,18 @@ public class BitmapUtils {
}
return resultBitmap;
}
/**
* Checks if file passed is an image
* @param file
* @return true/false
*/
public static boolean isImage(File file) {
Uri selectedUri = Uri.fromFile(file);
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(selectedUri.toString().toLowerCase());
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
return (mimeType != null && mimeType.startsWith("image/"));
}
}

View file

@ -19,6 +19,7 @@
package com.owncloud.android.utils;
import java.net.IDN;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
@ -30,6 +31,7 @@ import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.text.format.DateUtils;
import android.webkit.MimeTypeMap;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
@ -73,21 +75,28 @@ public class DisplayUtils {
private static final String TYPE_VIDEO = "video";
private static final String SUBTYPE_PDF = "pdf";
private static final String[] SUBTYPES_DOCUMENT = { "msword",
"vnd.openxmlformats-officedocument.wordprocessingml.document",
"vnd.oasis.opendocument.text",
"rtf"
};
private static final String SUBTYPE_XML = "xml";
private static final String[] SUBTYPES_DOCUMENT = {
"msword",
"vnd.openxmlformats-officedocument.wordprocessingml.document",
"vnd.oasis.opendocument.text",
"rtf",
"javascript"
};
private static Set<String> SUBTYPES_DOCUMENT_SET = new HashSet<String>(Arrays.asList(SUBTYPES_DOCUMENT));
private static final String[] SUBTYPES_SPREADSHEET = { "msexcel",
"vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"vnd.oasis.opendocument.spreadsheet"
};
private static final String[] SUBTYPES_SPREADSHEET = {
"msexcel",
"vnd.ms-excel",
"vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"vnd.oasis.opendocument.spreadsheet"
};
private static Set<String> SUBTYPES_SPREADSHEET_SET = new HashSet<String>(Arrays.asList(SUBTYPES_SPREADSHEET));
private static final String[] SUBTYPES_PRESENTATION = { "mspowerpoint",
"vnd.openxmlformats-officedocument.presentationml.presentation",
"vnd.oasis.opendocument.presentation"
};
private static final String[] SUBTYPES_PRESENTATION = {
"mspowerpoint",
"vnd.ms-powerpoint",
"vnd.openxmlformats-officedocument.presentationml.presentation",
"vnd.oasis.opendocument.presentation"
};
private static Set<String> SUBTYPES_PRESENTATION_SET = new HashSet<String>(Arrays.asList(SUBTYPES_PRESENTATION));
private static final String[] SUBTYPES_COMPRESSED = {"x-tar", "x-gzip", "zip"};
private static final Set<String> SUBTYPES_COMPRESSED_SET = new HashSet<String>(Arrays.asList(SUBTYPES_COMPRESSED));
@ -95,6 +104,8 @@ public class DisplayUtils {
private static final String EXTENSION_RAR = "rar";
private static final String EXTENSION_RTF = "rtf";
private static final String EXTENSION_3GP = "3gp";
private static final String EXTENSION_PY = "py";
private static final String EXTENSION_JS = "js";
/**
* Converts the file size in bytes to human readable output.
@ -113,30 +124,6 @@ public class DisplayUtils {
return result + " " + sizeSuffixes[attachedsuff];
}
/**
* Removes special HTML entities from a string
*
* @param s Input string
* @return A cleaned version of the string
*/
public static String HtmlDecode(String s) {
/*
* TODO: Perhaps we should use something more proven like:
* http://commons.apache.org/lang/api-2.6/org/apache/commons/lang/StringEscapeUtils.html#unescapeHtml%28java.lang.String%29
*/
String ret = "";
for (int i = 0; i < s.length(); ++i) {
if (s.charAt(i) == '%') {
ret += (char) Integer.parseInt(s.substring(i + 1, i + 3), 16);
i += 2;
} else {
ret += s.charAt(i);
}
}
return ret;
}
/**
* Converts MIME types like "image/jpg" to more end user friendly output
* like "JPG image".
@ -155,18 +142,25 @@ public class DisplayUtils {
/**
* Returns the resource identifier of an image resource to use as icon associated to a
* known MIME type.
* Returns the resource identifier of an image to use as icon associated to a known MIME type.
*
* @param mimetype MIME type string.
* @param filename name, with extension
* @return Resource identifier of an image resource.
* @param mimetype MIME type string; if NULL, the method tries to guess it from the extension in filename
* @param filename Name, with extension.
* @return Identifier of an image resource.
*/
public static int getResourceId(String mimetype, String filename) {
public static int getFileTypeIconId(String mimetype, String filename) {
if (mimetype == null || "DIR".equals(mimetype)) {
return R.drawable.ic_menu_archive;
if (mimetype == null) {
String fileExtension = getExtension(filename);
mimetype = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
if (mimetype == null) {
mimetype = TYPE_APPLICATION + "/" + SUBTYPE_OCTET_STREAM;
}
}
if ("DIR".equals(mimetype)) {
return R.drawable.ic_menu_archive;
} else {
String [] parts = mimetype.split("/");
String type = parts[0];
@ -189,6 +183,9 @@ public class DisplayUtils {
if (SUBTYPE_PDF.equals(subtype)) {
return R.drawable.file_pdf;
} else if (SUBTYPE_XML.equals(subtype)) {
return R.drawable.file_doc;
} else if (SUBTYPES_DOCUMENT_SET.contains(subtype)) {
return R.drawable.file_doc;
@ -200,7 +197,7 @@ public class DisplayUtils {
} else if (SUBTYPES_COMPRESSED_SET.contains(subtype)) {
return R.drawable.file_zip;
} else if (SUBTYPE_OCTET_STREAM.equals(subtype) ) {
if (getExtension(filename).equalsIgnoreCase(EXTENSION_RAR)) {
return R.drawable.file_zip;
@ -210,7 +207,10 @@ public class DisplayUtils {
} else if (getExtension(filename).equalsIgnoreCase(EXTENSION_3GP)) {
return R.drawable.file_movie;
} else if ( getExtension(filename).equalsIgnoreCase(EXTENSION_PY) ||
getExtension(filename).equalsIgnoreCase(EXTENSION_JS)) {
return R.drawable.file_doc;
}
}
}
@ -222,8 +222,7 @@ public class DisplayUtils {
private static String getExtension(String filename) {
String extension = filename.substring(filename.lastIndexOf(".") + 1);
String extension = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
return extension;
}
@ -234,7 +233,8 @@ public class DisplayUtils {
*/
public static String unixTimeToHumanReadable(long milliseconds) {
Date date = new Date(milliseconds);
return date.toLocaleString();
DateFormat df = DateFormat.getDateTimeInstance();
return df.format(date);
}
@ -295,7 +295,11 @@ public class DisplayUtils {
return fileExtension;
}
public static CharSequence getRelativeDateTimeString(Context c, long time, long minResolution, long transitionResolution, int flags){
@SuppressWarnings("deprecation")
public static CharSequence getRelativeDateTimeString (
Context c, long time, long minResolution, long transitionResolution, int flags
){
CharSequence dateString = "";
// in Future
@ -307,18 +311,21 @@ public class DisplayUtils {
return c.getString(R.string.file_list_seconds_ago);
} else {
// Workaround 2.x bug (see https://github.com/owncloud/android/issues/716)
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB && (System.currentTimeMillis() - time) > 24 * 60 * 60 * 1000){
if ( Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB &&
(System.currentTimeMillis() - time) > 24 * 60 * 60 * 1000 ) {
Date date = new Date(time);
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
dateString = DateUtils.getRelativeDateTimeString(c, date.getTime(), minResolution, transitionResolution, flags);
dateString = DateUtils.getRelativeDateTimeString(
c, date.getTime(), minResolution, transitionResolution, flags
);
} else {
dateString = DateUtils.getRelativeDateTimeString(c, time, minResolution, transitionResolution, flags);
}
}
return dateString.toString().split(",")[0];
return dateString.toString().split(",")[0];
}
/**