mirror of
https://github.com/nextcloud/android.git
synced 2024-11-29 10:49:04 +03:00
Merge pull request #746 from owncloud/thumbnailForUpload
Thumbnails added to Upload activity
This commit is contained in:
commit
9bf4e0f7b9
6 changed files with 365 additions and 234 deletions
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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/"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue