From: jabarros Date: Mon, 12 Jan 2015 13:30:06 +0000 (+0100) Subject: Merge branch 'develop' into thumbnailForUpload X-Git-Tag: oc-android-1.7.0_signed~42^2 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/6c70154a506b0963ed5aa0a402dc80a2933f1087?hp=26403abd0a9df7a3b83d49b302d19d223ddc0406 Merge branch 'develop' into thumbnailForUpload --- diff --git a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index ce53c444..edab29d4 100644 --- a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java @@ -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,44 +137,15 @@ public class ThumbnailsCacheManager { return null; } - - public static boolean cancelPotentialWork(OCFile file, ImageView imageView) { - final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView); - - if (bitmapWorkerTask != null) { - final OCFile bitmapData = bitmapWorkerTask.mFile; - // If bitmapData is not yet set or it differs from the new data - if (bitmapData == null || bitmapData != file) { - // Cancel previous task - bitmapWorkerTask.cancel(true); - } else { - // The same work is already in progress - return false; - } - } - // 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(); - if (drawable instanceof AsyncDrawable) { - final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; - return asyncDrawable.getBitmapWorkerTask(); - } - } - return null; - } - - public static class ThumbnailGenerationTask extends AsyncTask { + public static class ThumbnailGenerationTask extends AsyncTask { private final WeakReference mImageViewReference; private static Account mAccount; - private OCFile mFile; + 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 + // Use a WeakReference to ensure the ImageView can be garbage collected mImageViewReference = new WeakReference(imageView); if (storageManager == null) throw new IllegalArgumentException("storageManager must not be NULL"); @@ -184,95 +153,46 @@ public class ThumbnailsCacheManager { mAccount = account; } - // Decode image in background. + public ThumbnailGenerationTask(ImageView imageView) { + // Use a WeakReference to ensure the ImageView can be garbage collected + mImageViewReference = new WeakReference(imageView); + } + @Override - protected Bitmap doInBackground(OCFile... params) { + 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]; - 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"); - } - } - } + 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(); + + }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; @@ -280,47 +200,183 @@ public class ThumbnailsCacheManager { if (mImageViewReference != null && bitmap != null) { final ImageView imageView = mImageViewReference.get(); - final ThumbnailGenerationTask bitmapWorkerTask = - getBitmapWorkerTask(imageView); + final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (this == bitmapWorkerTask && imageView != null) { - if (imageView.getTag().equals(mFile.getFileId())) { + 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 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 + bitmapWorkerTask.cancel(true); + } else { + // The same work is already in progress + return false; + } + } + // 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(); + if (drawable instanceof AsyncDrawable) { + final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; + return asyncDrawable.getBitmapWorkerTask(); + } + } + return null; + } + public static class AsyncDrawable extends BitmapDrawable { private final WeakReference bitmapWorkerTaskReference; public AsyncDrawable( Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask - ) { - + ) { + super(res, bitmap); bitmapWorkerTaskReference = - new WeakReference(bitmapWorkerTask); + new WeakReference(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 - } - } - } diff --git a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java index be470614..9c8c8e1f 100644 --- a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java +++ b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java @@ -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 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); - } - + } } diff --git a/src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java b/src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java index 6190ebee..996851e1 100644 --- a/src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java +++ b/src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java @@ -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); diff --git a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java index 2ff29250..1e0e7ee3 100644 --- a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java +++ b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java @@ -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)); } } diff --git a/src/com/owncloud/android/utils/BitmapUtils.java b/src/com/owncloud/android/utils/BitmapUtils.java index 70367278..92824f44 100644 --- a/src/com/owncloud/android/utils/BitmapUtils.java +++ b/src/com/owncloud/android/utils/BitmapUtils.java @@ -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/")); + } } diff --git a/src/com/owncloud/android/utils/DisplayUtils.java b/src/com/owncloud/android/utils/DisplayUtils.java index a1afb894..32d90173 100644 --- a/src/com/owncloud/android/utils/DisplayUtils.java +++ b/src/com/owncloud/android/utils/DisplayUtils.java @@ -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 SUBTYPES_DOCUMENT_SET = new HashSet(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 SUBTYPES_SPREADSHEET_SET = new HashSet(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 SUBTYPES_PRESENTATION_SET = new HashSet(Arrays.asList(SUBTYPES_PRESENTATION)); private static final String[] SUBTYPES_COMPRESSED = {"x-tar", "x-gzip", "zip"}; private static final Set SUBTYPES_COMPRESSED_SET = new HashSet(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. @@ -114,30 +125,6 @@ public class DisplayUtils { } /** - * 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]; } /**