mirror of
https://github.com/nextcloud/android.git
synced 2024-11-26 23:28:42 +03:00
Resized images
This commit is contained in:
parent
f838dd7b43
commit
0a649f01bb
19 changed files with 688 additions and 158 deletions
|
@ -185,6 +185,12 @@
|
||||||
android:resource="@xml/exposed_filepaths" />
|
android:resource="@xml/exposed_filepaths" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:name=".providers.DiskLruImageCacheFileProvider"
|
||||||
|
android:authorities="org.nextcloud.imageCache.provider"
|
||||||
|
android:exported="true">
|
||||||
|
</provider>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".authentication.AuthenticatorActivity"
|
android:name=".authentication.AuthenticatorActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/**
|
/*
|
||||||
* ownCloud Android client application
|
* ownCloud Android client application
|
||||||
*
|
*
|
||||||
* @author Tobias Kaminsky
|
* @author Tobias Kaminsky
|
||||||
|
@ -23,12 +23,14 @@ package com.owncloud.android.datamodel;
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Bitmap.CompressFormat;
|
import android.graphics.Bitmap.CompressFormat;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Point;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.media.MediaMetadataRetriever;
|
import android.media.MediaMetadataRetriever;
|
||||||
|
@ -36,7 +38,9 @@ import android.media.ThumbnailUtils;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.view.Display;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
import android.view.WindowManager;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import com.owncloud.android.MainApp;
|
import com.owncloud.android.MainApp;
|
||||||
|
@ -49,7 +53,9 @@ import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||||
import com.owncloud.android.ui.adapter.DiskLruImageCache;
|
import com.owncloud.android.ui.adapter.DiskLruImageCache;
|
||||||
|
import com.owncloud.android.ui.preview.PreviewImageFragment;
|
||||||
import com.owncloud.android.utils.BitmapUtils;
|
import com.owncloud.android.utils.BitmapUtils;
|
||||||
|
import com.owncloud.android.utils.ConnectivityUtils;
|
||||||
import com.owncloud.android.utils.DisplayUtils.AvatarGenerationListener;
|
import com.owncloud.android.utils.DisplayUtils.AvatarGenerationListener;
|
||||||
import com.owncloud.android.utils.FileStorageUtils;
|
import com.owncloud.android.utils.FileStorageUtils;
|
||||||
import com.owncloud.android.utils.MimeTypeUtil;
|
import com.owncloud.android.utils.MimeTypeUtil;
|
||||||
|
@ -58,6 +64,7 @@ import org.apache.commons.httpclient.HttpStatus;
|
||||||
import org.apache.commons.httpclient.methods.GetMethod;
|
import org.apache.commons.httpclient.methods.GetMethod;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -69,6 +76,9 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
*/
|
*/
|
||||||
public class ThumbnailsCacheManager {
|
public class ThumbnailsCacheManager {
|
||||||
|
|
||||||
|
public static final String PREFIX_RESIZED_IMAGE = "r";
|
||||||
|
public static final String PREFIX_THUMBNAIL = "t";
|
||||||
|
|
||||||
private static final String TAG = ThumbnailsCacheManager.class.getSimpleName();
|
private static final String TAG = ThumbnailsCacheManager.class.getSimpleName();
|
||||||
|
|
||||||
private static final String CACHE_FOLDER = "thumbnailCache";
|
private static final String CACHE_FOLDER = "thumbnailCache";
|
||||||
|
@ -77,7 +87,7 @@ public class ThumbnailsCacheManager {
|
||||||
private static DiskLruImageCache mThumbnailCache = null;
|
private static DiskLruImageCache mThumbnailCache = null;
|
||||||
private static boolean mThumbnailCacheStarting = true;
|
private static boolean mThumbnailCacheStarting = true;
|
||||||
|
|
||||||
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
|
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 200; // 200MB
|
||||||
private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
|
private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
|
||||||
private static final int mCompressQuality = 70;
|
private static final int mCompressQuality = 70;
|
||||||
private static OwnCloudClient mClient = null;
|
private static OwnCloudClient mClient = null;
|
||||||
|
@ -106,19 +116,19 @@ public class ThumbnailsCacheManager {
|
||||||
try {
|
try {
|
||||||
// Check if media is mounted or storage is built-in, if so,
|
// Check if media is mounted or storage is built-in, if so,
|
||||||
// try and use external cache dir; otherwise use internal cache dir
|
// try and use external cache dir; otherwise use internal cache dir
|
||||||
final String cachePath =
|
File cacheDir = MainApp.getAppContext().getExternalCacheDir();
|
||||||
MainApp.getAppContext().getExternalCacheDir().getPath() +
|
|
||||||
File.separator + CACHE_FOLDER;
|
if (cacheDir != null) {
|
||||||
Log_OC.d(TAG, "create dir: " + cachePath);
|
String cachePath = cacheDir.getPath() + File.separator + CACHE_FOLDER;
|
||||||
final File diskCacheDir = new File(cachePath);
|
Log_OC.d(TAG, "create dir: " + cachePath);
|
||||||
mThumbnailCache = new DiskLruImageCache(
|
File diskCacheDir = new File(cachePath);
|
||||||
diskCacheDir,
|
mThumbnailCache = new DiskLruImageCache(diskCacheDir, DISK_CACHE_SIZE, mCompressFormat,
|
||||||
DISK_CACHE_SIZE,
|
mCompressQuality);
|
||||||
mCompressFormat,
|
} else {
|
||||||
mCompressQuality
|
throw new FileNotFoundException("Thumbnail cache could not be opened");
|
||||||
);
|
}
|
||||||
} catch (Exception e) {
|
} catch (java.io.IOException e) {
|
||||||
Log_OC.d(TAG, "Thumbnail cache could not be opened ", e);
|
Log_OC.d(TAG, e.getMessage());
|
||||||
mThumbnailCache = null;
|
mThumbnailCache = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,17 +149,32 @@ public class ThumbnailsCacheManager {
|
||||||
return Math.round(r.getDimension(R.dimen.file_icon_size_grid));
|
return Math.round(r.getDimension(R.dimen.file_icon_size_grid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts dimension of screen as point
|
||||||
|
*
|
||||||
|
* @return Point
|
||||||
|
*/
|
||||||
|
private static Point getScreenDimension() {
|
||||||
|
WindowManager wm = (WindowManager) MainApp.getAppContext().
|
||||||
|
getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
Display display = wm.getDefaultDisplay();
|
||||||
|
Point point = new Point();
|
||||||
|
display.getSize(point);
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add thumbnail to cache
|
* Add thumbnail to cache
|
||||||
* @param imageKey: thumb key
|
* @param imageKey: thumb key
|
||||||
* @param bitmap: image for extracting thumbnail
|
* @param bitmap: image for extracting thumbnail
|
||||||
* @param path: image path
|
* @param path: image path
|
||||||
* @param px: thumbnail dp
|
* @param pxW: thumbnail width in pixel
|
||||||
|
* @param pxH: thumbnail height in pixel
|
||||||
* @return Bitmap
|
* @return Bitmap
|
||||||
*/
|
*/
|
||||||
private static Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int px){
|
private static Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int pxW, int pxH){
|
||||||
|
|
||||||
Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
|
Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH);
|
||||||
|
|
||||||
// Rotate image, obeying exif tag
|
// Rotate image, obeying exif tag
|
||||||
thumbnail = BitmapUtils.rotateImage(thumbnail,path);
|
thumbnail = BitmapUtils.rotateImage(thumbnail,path);
|
||||||
|
@ -185,7 +210,180 @@ public class ThumbnailsCacheManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ThumbnailGenerationTask extends AsyncTask<Object, Void, Bitmap> {
|
public static class ResizedImageGenerationTask extends AsyncTask<Object, Void, Bitmap> {
|
||||||
|
private PreviewImageFragment previewImageFragment;
|
||||||
|
private FileDataStorageManager storageManager;
|
||||||
|
private Account account;
|
||||||
|
private WeakReference<ImageView> imageViewReference;
|
||||||
|
private OCFile file;
|
||||||
|
|
||||||
|
|
||||||
|
public ResizedImageGenerationTask(PreviewImageFragment previewImageFragment, ImageView imageView,
|
||||||
|
FileDataStorageManager storageManager, Account account)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
this.previewImageFragment = previewImageFragment;
|
||||||
|
imageViewReference = new WeakReference<>(imageView);
|
||||||
|
this.storageManager = storageManager;
|
||||||
|
this.account = account;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Bitmap doInBackground(Object... params) {
|
||||||
|
Bitmap thumbnail = null;
|
||||||
|
|
||||||
|
file = (OCFile) params[0];
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (account != null) {
|
||||||
|
OwnCloudAccount ocAccount = new OwnCloudAccount(account, MainApp.getAppContext());
|
||||||
|
mClient = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount,
|
||||||
|
MainApp.getAppContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
thumbnail = doResizedImageInBackground();
|
||||||
|
|
||||||
|
if (MimeTypeUtil.isVideo(file) && thumbnail != null) {
|
||||||
|
thumbnail = addVideoOverlay(thumbnail);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (OutOfMemoryError oome) {
|
||||||
|
System.gc();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
// the app should never break due to a problem with thumbnails
|
||||||
|
Log_OC.e(TAG, "Generation of thumbnail for " + file + " failed", t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return thumbnail;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bitmap doResizedImageInBackground() {
|
||||||
|
Bitmap thumbnail;
|
||||||
|
|
||||||
|
String imageKey = PREFIX_RESIZED_IMAGE + String.valueOf(file.getRemoteId());
|
||||||
|
|
||||||
|
// Check disk cache in background thread
|
||||||
|
thumbnail = getBitmapFromDiskCache(imageKey);
|
||||||
|
|
||||||
|
// Not found in disk cache
|
||||||
|
if (thumbnail == null || file.needsUpdateThumbnail()) {
|
||||||
|
Point p = getScreenDimension();
|
||||||
|
int pxW = p.x;
|
||||||
|
int pxH = p.y;
|
||||||
|
|
||||||
|
if (file.isDown()) {
|
||||||
|
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
|
||||||
|
file.getStoragePath(), pxW, pxH);
|
||||||
|
|
||||||
|
if (bitmap != null) {
|
||||||
|
// Handle PNG
|
||||||
|
if (file.getMimetype().equalsIgnoreCase("image/png")) {
|
||||||
|
bitmap = handlePNG(bitmap, pxW);
|
||||||
|
}
|
||||||
|
|
||||||
|
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), pxW, pxH);
|
||||||
|
|
||||||
|
file.setNeedsUpdateThumbnail(false);
|
||||||
|
storageManager.saveFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Download thumbnail from server
|
||||||
|
OwnCloudVersion serverOCVersion = AccountUtils.getServerVersion(account);
|
||||||
|
if (mClient != null && serverOCVersion != null) {
|
||||||
|
if (serverOCVersion.supportsRemoteThumbnails()) {
|
||||||
|
GetMethod getMethod = null;
|
||||||
|
try {
|
||||||
|
// resized image via gallery app
|
||||||
|
String uri = mClient.getBaseUri() + "" +
|
||||||
|
"/index.php/apps/gallery/api/preview/" +
|
||||||
|
Integer.parseInt(file.getRemoteId().substring(0, 8)) +
|
||||||
|
"/" + pxW + "/" + pxH;
|
||||||
|
Log_OC.d(TAG, "generate resizedImage: " + file.getFileName() +
|
||||||
|
" URI: " + uri);
|
||||||
|
getMethod = new GetMethod(uri);
|
||||||
|
getMethod.setRequestHeader("Cookie",
|
||||||
|
"nc_sameSiteCookielax=true;nc_sameSiteCookiestrict=true");
|
||||||
|
int status = mClient.executeMethod(getMethod);
|
||||||
|
if (status == HttpStatus.SC_OK) {
|
||||||
|
InputStream inputStream = getMethod.getResponseBodyAsStream();
|
||||||
|
thumbnail = BitmapFactory.decodeStream(inputStream);
|
||||||
|
} else {
|
||||||
|
mClient.exhaustResponse(getMethod.getResponseBodyAsStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle PNG
|
||||||
|
if (file.getMimetype().equalsIgnoreCase("image/png")) {
|
||||||
|
thumbnail = handlePNG(thumbnail, pxW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add thumbnail to cache
|
||||||
|
if (thumbnail != null) {
|
||||||
|
Log_OC.d(TAG, "add thumbnail to cache: " + file.getFileName());
|
||||||
|
addBitmapToCache(imageKey, thumbnail);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log_OC.d(TAG, e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
if (getMethod != null) {
|
||||||
|
getMethod.releaseConnection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log_OC.d(TAG, "Server too old");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return thumbnail;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onPostExecute(Bitmap bitmap) {
|
||||||
|
if (imageViewReference != null) {
|
||||||
|
final ImageView imageView = imageViewReference.get();
|
||||||
|
|
||||||
|
if (bitmap != null) {
|
||||||
|
final ResizedImageGenerationTask bitmapWorkerTask = getResizedImageGenerationWorkerTask(imageView);
|
||||||
|
|
||||||
|
if (this == bitmapWorkerTask) {
|
||||||
|
String tagId = String.valueOf(file.getFileId());
|
||||||
|
|
||||||
|
if (String.valueOf(imageView.getTag()).equals(tagId)) {
|
||||||
|
imageView.setImageBitmap(bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ConnectivityUtils.isAppConnected(MainApp.getAppContext())) {
|
||||||
|
previewImageFragment.setErrorPreviewMessage();
|
||||||
|
} else {
|
||||||
|
previewImageFragment.setNoConnectionErrorMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ThumbnailGenerationTaskObject {
|
||||||
|
private Object file;
|
||||||
|
private String imageKey;
|
||||||
|
|
||||||
|
public ThumbnailGenerationTaskObject(Object file, String imageKey) {
|
||||||
|
this.file = file;
|
||||||
|
this.imageKey = imageKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getImageKey() {
|
||||||
|
return imageKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ThumbnailGenerationTask extends AsyncTask<ThumbnailGenerationTaskObject, Void, Bitmap> {
|
||||||
private final WeakReference<ImageView> mImageViewReference;
|
private final WeakReference<ImageView> mImageViewReference;
|
||||||
private static Account mAccount;
|
private static Account mAccount;
|
||||||
private ArrayList<ThumbnailGenerationTask> mAsyncTasks = null;
|
private ArrayList<ThumbnailGenerationTask> mAsyncTasks = null;
|
||||||
|
@ -232,7 +430,7 @@ public class ThumbnailsCacheManager {
|
||||||
|
|
||||||
@SuppressFBWarnings("Dm")
|
@SuppressFBWarnings("Dm")
|
||||||
@Override
|
@Override
|
||||||
protected Bitmap doInBackground(Object... params) {
|
protected Bitmap doInBackground(ThumbnailGenerationTaskObject... params) {
|
||||||
Bitmap thumbnail = null;
|
Bitmap thumbnail = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -245,13 +443,12 @@ public class ThumbnailsCacheManager {
|
||||||
getClientFor(ocAccount, MainApp.getAppContext());
|
getClientFor(ocAccount, MainApp.getAppContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
mFile = params[0];
|
ThumbnailGenerationTaskObject object = params[0];
|
||||||
if (params.length == 2) {
|
mFile = object.getFile();
|
||||||
mImageKey = (String) params[1];
|
mImageKey = object.getImageKey();
|
||||||
}
|
|
||||||
|
|
||||||
if (mFile instanceof OCFile) {
|
if (mFile instanceof OCFile) {
|
||||||
thumbnail = doOCFileInBackground();
|
thumbnail = doThumbnailFromOCFileInBackground();
|
||||||
|
|
||||||
if (MimeTypeUtil.isVideo((OCFile) mFile) && thumbnail != null) {
|
if (MimeTypeUtil.isVideo((OCFile) mFile) && thumbnail != null) {
|
||||||
thumbnail = addVideoOverlay(thumbnail);
|
thumbnail = addVideoOverlay(thumbnail);
|
||||||
|
@ -300,42 +497,31 @@ public class ThumbnailsCacheManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private Bitmap doThumbnailFromOCFileInBackground() {
|
||||||
* Converts size of file icon from dp to pixel
|
Bitmap thumbnail;
|
||||||
* @return int
|
OCFile file = (OCFile) mFile;
|
||||||
*/
|
String imageKey = PREFIX_THUMBNAIL + String.valueOf(file.getRemoteId());
|
||||||
private int getThumbnailDimension(){
|
|
||||||
// Converts dp to pixel
|
|
||||||
Resources r = MainApp.getAppContext().getResources();
|
|
||||||
Double d = Math.pow(2,Math.floor(Math.log(r.getDimension(R.dimen.file_icon_size_grid))/Math.log(2)));
|
|
||||||
return d.intValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Bitmap doOCFileInBackground() {
|
|
||||||
OCFile file = (OCFile)mFile;
|
|
||||||
|
|
||||||
final String imageKey = String.valueOf(file.getRemoteId());
|
|
||||||
|
|
||||||
// Check disk cache in background thread
|
// Check disk cache in background thread
|
||||||
Bitmap thumbnail = getBitmapFromDiskCache(imageKey);
|
thumbnail = getBitmapFromDiskCache(imageKey);
|
||||||
|
|
||||||
// Not found in disk cache
|
// Not found in disk cache
|
||||||
if (thumbnail == null || file.needsUpdateThumbnail()) {
|
if (thumbnail == null || file.needsUpdateThumbnail()) {
|
||||||
|
int pxW;
|
||||||
int px = getThumbnailDimension();
|
int pxH;
|
||||||
|
pxW = pxH = getThumbnailDimension();
|
||||||
|
|
||||||
if (file.isDown()) {
|
if (file.isDown()) {
|
||||||
Bitmap temp = BitmapUtils.decodeSampledBitmapFromFile(
|
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
|
||||||
file.getStoragePath(), px, px);
|
file.getStoragePath(), pxW, pxH);
|
||||||
Bitmap bitmap = ThumbnailUtils.extractThumbnail(temp, px, px);
|
|
||||||
|
|
||||||
if (bitmap != null) {
|
if (bitmap != null) {
|
||||||
// Handle PNG
|
// Handle PNG
|
||||||
if (file.getMimetype().equalsIgnoreCase("image/png")) {
|
if (file.getMimetype().equalsIgnoreCase("image/png")) {
|
||||||
bitmap = handlePNG(bitmap, px);
|
bitmap = handlePNG(bitmap, pxW);
|
||||||
}
|
}
|
||||||
|
|
||||||
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), px);
|
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), pxW, pxH);
|
||||||
|
|
||||||
file.setNeedsUpdateThumbnail(false);
|
file.setNeedsUpdateThumbnail(false);
|
||||||
mStorageManager.saveFile(file);
|
mStorageManager.saveFile(file);
|
||||||
|
@ -348,10 +534,12 @@ public class ThumbnailsCacheManager {
|
||||||
if (serverOCVersion.supportsRemoteThumbnails()) {
|
if (serverOCVersion.supportsRemoteThumbnails()) {
|
||||||
getMethod = null;
|
getMethod = null;
|
||||||
try {
|
try {
|
||||||
|
// thumbnail
|
||||||
String uri = mClient.getBaseUri() + "" +
|
String uri = mClient.getBaseUri() + "" +
|
||||||
"/index.php/apps/files/api/v1/thumbnail/" +
|
"/index.php/apps/files/api/v1/thumbnail/" +
|
||||||
px + "/" + px + Uri.encode(file.getRemotePath(), "/");
|
pxW + "/" + pxH + Uri.encode(file.getRemotePath(), "/");
|
||||||
Log_OC.d("Thumbnail", "URI: " + uri);
|
Log_OC.d(TAG, "generate thumbnail: " + file.getFileName() +
|
||||||
|
" URI: " + uri);
|
||||||
getMethod = new GetMethod(uri);
|
getMethod = new GetMethod(uri);
|
||||||
getMethod.setRequestHeader("Cookie",
|
getMethod.setRequestHeader("Cookie",
|
||||||
"nc_sameSiteCookielax=true;nc_sameSiteCookiestrict=true");
|
"nc_sameSiteCookielax=true;nc_sameSiteCookiestrict=true");
|
||||||
|
@ -363,20 +551,22 @@ public class ThumbnailsCacheManager {
|
||||||
if (status == HttpStatus.SC_OK) {
|
if (status == HttpStatus.SC_OK) {
|
||||||
InputStream inputStream = getMethod.getResponseBodyAsStream();
|
InputStream inputStream = getMethod.getResponseBodyAsStream();
|
||||||
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
||||||
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
|
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH);
|
||||||
|
|
||||||
// Handle PNG
|
|
||||||
if (file.getMimetype().equalsIgnoreCase("image/png")) {
|
|
||||||
thumbnail = handlePNG(thumbnail, px);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add thumbnail to cache
|
|
||||||
if (thumbnail != null) {
|
|
||||||
addBitmapToCache(imageKey, thumbnail);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
mClient.exhaustResponse(getMethod.getResponseBodyAsStream());
|
mClient.exhaustResponse(getMethod.getResponseBodyAsStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle PNG
|
||||||
|
if (file.getMimetype().equalsIgnoreCase("image/png")) {
|
||||||
|
thumbnail = handlePNG(thumbnail, pxW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add thumbnail to cache
|
||||||
|
if (thumbnail != null) {
|
||||||
|
Log_OC.d(TAG, "add thumbnail to cache: " + file.getFileName());
|
||||||
|
addBitmapToCache(imageKey, thumbnail);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log_OC.d(TAG, e.getMessage(), e);
|
Log_OC.d(TAG, e.getMessage(), e);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -395,6 +585,18 @@ public class ThumbnailsCacheManager {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts size of file icon from dp to pixel
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private int getThumbnailDimension() {
|
||||||
|
// Converts dp to pixel
|
||||||
|
Resources r = MainApp.getAppContext().getResources();
|
||||||
|
Double d = Math.pow(2, Math.floor(Math.log(r.getDimension(R.dimen.file_icon_size_grid)) / Math.log(2)));
|
||||||
|
return d.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
private Bitmap doFileInBackground() {
|
private Bitmap doFileInBackground() {
|
||||||
File file = (File)mFile;
|
File file = (File)mFile;
|
||||||
|
|
||||||
|
@ -405,19 +607,22 @@ public class ThumbnailsCacheManager {
|
||||||
imageKey = String.valueOf(file.hashCode());
|
imageKey = String.valueOf(file.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// local file should always generate a thumbnail
|
||||||
|
mImageKey = PREFIX_THUMBNAIL + mImageKey;
|
||||||
|
|
||||||
// Check disk cache in background thread
|
// Check disk cache in background thread
|
||||||
Bitmap thumbnail = getBitmapFromDiskCache(imageKey);
|
Bitmap thumbnail = getBitmapFromDiskCache(imageKey);
|
||||||
|
|
||||||
// Not found in disk cache
|
// Not found in disk cache
|
||||||
if (thumbnail == null) {
|
if (thumbnail == null) {
|
||||||
|
int pxW;
|
||||||
|
int pxH;
|
||||||
|
pxW = pxH = getThumbnailDimension();
|
||||||
|
|
||||||
int px = getThumbnailDimension();
|
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(file.getAbsolutePath(), pxW, pxH);
|
||||||
|
|
||||||
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
|
|
||||||
file.getAbsolutePath(), px, px);
|
|
||||||
|
|
||||||
if (bitmap != null) {
|
if (bitmap != null) {
|
||||||
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px);
|
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), pxW, pxH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return thumbnail;
|
return thumbnail;
|
||||||
|
@ -514,7 +719,7 @@ public class ThumbnailsCacheManager {
|
||||||
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(file.getAbsolutePath(), px, px);
|
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(file.getAbsolutePath(), px, px);
|
||||||
|
|
||||||
if (bitmap != null) {
|
if (bitmap != null) {
|
||||||
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px);
|
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px, px);
|
||||||
}
|
}
|
||||||
} else if (Type.VIDEO.equals(type)) {
|
} else if (Type.VIDEO.equals(type)) {
|
||||||
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||||
|
@ -541,7 +746,7 @@ public class ThumbnailsCacheManager {
|
||||||
int max = Math.max(width, height);
|
int max = Math.max(width, height);
|
||||||
if (max > px) {
|
if (max > px) {
|
||||||
thumbnail = BitmapUtils.scaleBitmap(thumbnail, px, width, height, max);
|
thumbnail = BitmapUtils.scaleBitmap(thumbnail, px, width, height, max);
|
||||||
thumbnail = addThumbnailToCache(imageKey, thumbnail, file.getPath(), px);
|
thumbnail = addThumbnailToCache(imageKey, thumbnail, file.getPath(), px, px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -605,27 +810,6 @@ public class ThumbnailsCacheManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* Converts size of file icon from dp to pixel
|
||||||
* @return int
|
* @return int
|
||||||
|
@ -774,6 +958,17 @@ public class ThumbnailsCacheManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ResizedImageGenerationTask getResizedImageGenerationWorkerTask(ImageView imageView) {
|
||||||
|
if (imageView != null) {
|
||||||
|
final Drawable drawable = imageView.getDrawable();
|
||||||
|
if (drawable instanceof AsyncResizedImageDrawable) {
|
||||||
|
final AsyncResizedImageDrawable asyncDrawable = (AsyncResizedImageDrawable) drawable;
|
||||||
|
return asyncDrawable.getBitmapWorkerTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static Bitmap addVideoOverlay(Bitmap thumbnail){
|
public static Bitmap addVideoOverlay(Bitmap thumbnail){
|
||||||
Bitmap playButton = BitmapFactory.decodeResource(MainApp.getAppContext().getResources(),
|
Bitmap playButton = BitmapFactory.decodeResource(MainApp.getAppContext().getResources(),
|
||||||
R.drawable.view_play);
|
R.drawable.view_play);
|
||||||
|
@ -852,22 +1047,30 @@ public class ThumbnailsCacheManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AsyncMediaThumbnailDrawable extends BitmapDrawable {
|
public static class AsyncResizedImageDrawable extends BitmapDrawable {
|
||||||
private final WeakReference<MediaThumbnailGenerationTask> bitmapWorkerTaskReference;
|
private final WeakReference<ResizedImageGenerationTask> bitmapWorkerTaskReference;
|
||||||
|
|
||||||
public AsyncMediaThumbnailDrawable(
|
|
||||||
Resources res, Bitmap bitmap, MediaThumbnailGenerationTask bitmapWorkerTask
|
|
||||||
) {
|
|
||||||
|
|
||||||
|
public AsyncResizedImageDrawable(Resources res, Bitmap bitmap, ResizedImageGenerationTask bitmapWorkerTask) {
|
||||||
super(res, bitmap);
|
super(res, bitmap);
|
||||||
bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
|
bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MediaThumbnailGenerationTask getBitmapWorkerTask() {
|
private ResizedImageGenerationTask getBitmapWorkerTask() {
|
||||||
return bitmapWorkerTaskReference.get();
|
return bitmapWorkerTaskReference.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class AsyncMediaThumbnailDrawable extends BitmapDrawable {
|
||||||
|
private final WeakReference<MediaThumbnailGenerationTask> bitmapWorkerTaskReference;
|
||||||
|
|
||||||
|
public AsyncMediaThumbnailDrawable(Resources res, Bitmap bitmap,
|
||||||
|
MediaThumbnailGenerationTask bitmapWorkerTask) {
|
||||||
|
|
||||||
|
super(res, bitmap);
|
||||||
|
bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class AsyncAvatarDrawable extends BitmapDrawable {
|
public static class AsyncAvatarDrawable extends BitmapDrawable {
|
||||||
private final WeakReference<AvatarGenerationTask> avatarWorkerTaskReference;
|
private final WeakReference<AvatarGenerationTask> avatarWorkerTaskReference;
|
||||||
|
|
||||||
|
@ -897,4 +1100,22 @@ public class ThumbnailsCacheManager {
|
||||||
|
|
||||||
return resultBitmap;
|
return resultBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void generateResizedImage(OCFile file) {
|
||||||
|
Point p = getScreenDimension();
|
||||||
|
int pxW = p.x;
|
||||||
|
int pxH = p.y;
|
||||||
|
String imageKey = PREFIX_RESIZED_IMAGE + String.valueOf(file.getRemoteId());
|
||||||
|
|
||||||
|
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(file.getStoragePath(), pxW, pxH);
|
||||||
|
|
||||||
|
if (bitmap != null) {
|
||||||
|
// Handle PNG
|
||||||
|
if (file.getMimetype().equalsIgnoreCase("image/png")) {
|
||||||
|
bitmap = handlePNG(bitmap, pxW);
|
||||||
|
}
|
||||||
|
|
||||||
|
addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), pxW, pxH);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1071,11 +1071,10 @@ public class FileUploader extends Service
|
||||||
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
|
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
|
||||||
new ThumbnailsCacheManager.ThumbnailGenerationTask(mStorageManager, mCurrentAccount);
|
new ThumbnailsCacheManager.ThumbnailGenerationTask(mStorageManager, mCurrentAccount);
|
||||||
|
|
||||||
Object[] params = new Object[2];
|
File file = new File(mCurrentUpload.getOriginalStoragePath());
|
||||||
params[0] = new File(mCurrentUpload.getOriginalStoragePath());
|
String remoteId = mCurrentUpload.getFile().getRemoteId();
|
||||||
params[1] = mCurrentUpload.getFile().getRemoteId();
|
|
||||||
|
|
||||||
task.execute(params);
|
task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, remoteId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
package com.owncloud.android.operations;
|
package com.owncloud.android.operations;
|
||||||
|
|
||||||
import com.owncloud.android.datamodel.OCFile;
|
import com.owncloud.android.datamodel.OCFile;
|
||||||
|
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
|
||||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
||||||
|
@ -75,6 +76,9 @@ public class RemoveFileOperation extends SyncOperation {
|
||||||
|
|
||||||
mFileToRemove = getStorageManager().getFileByPath(mRemotePath);
|
mFileToRemove = getStorageManager().getFileByPath(mRemotePath);
|
||||||
|
|
||||||
|
// store resized image
|
||||||
|
ThumbnailsCacheManager.generateResizedImage(mFileToRemove);
|
||||||
|
|
||||||
boolean localRemovalFailed = false;
|
boolean localRemovalFailed = false;
|
||||||
if (!mOnlyLocalCopy) {
|
if (!mOnlyLocalCopy) {
|
||||||
RemoveRemoteFileOperation operation = new RemoveRemoteFileOperation(mRemotePath);
|
RemoveRemoteFileOperation operation = new RemoveRemoteFileOperation(mRemotePath);
|
||||||
|
|
|
@ -918,7 +918,7 @@ public class UploadFileOperation extends SyncOperation {
|
||||||
// generate new Thumbnail
|
// generate new Thumbnail
|
||||||
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
|
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
|
||||||
new ThumbnailsCacheManager.ThumbnailGenerationTask(getStorageManager(), mAccount);
|
new ThumbnailsCacheManager.ThumbnailGenerationTask(getStorageManager(), mAccount);
|
||||||
task.execute(file);
|
task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, file.getRemoteId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOCFile(OCFile file, RemoteFile remoteFile) {
|
private void updateOCFile(OCFile file, RemoteFile remoteFile) {
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* ownCloud Android client application
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Tobias Kaminsky
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public
|
||||||
|
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.owncloud.android.providers;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.content.ContentProvider;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.MatrixCursor;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.provider.OpenableColumns;
|
||||||
|
|
||||||
|
import com.owncloud.android.MainApp;
|
||||||
|
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.lib.common.utils.Log_OC;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
|
||||||
|
public class DiskLruImageCacheFileProvider extends ContentProvider {
|
||||||
|
public static final String AUTHORITY = "org.nextcloud.imageCache.provider";
|
||||||
|
public static final String TAG = DiskLruImageCacheFileProvider.class.getSimpleName();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreate() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OCFile getFile(Uri uri) {
|
||||||
|
Account account = AccountUtils.getCurrentOwnCloudAccount(MainApp.getAppContext());
|
||||||
|
FileDataStorageManager fileDataStorageManager = new FileDataStorageManager(account,
|
||||||
|
MainApp.getAppContext().getContentResolver());
|
||||||
|
|
||||||
|
return fileDataStorageManager.getFileByPath(uri.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
|
||||||
|
OCFile ocFile = getFile(uri);
|
||||||
|
|
||||||
|
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
|
||||||
|
String.valueOf(ThumbnailsCacheManager.PREFIX_RESIZED_IMAGE + ocFile.getRemoteId()));
|
||||||
|
|
||||||
|
// fallback to thumbnail
|
||||||
|
if (thumbnail == null) {
|
||||||
|
thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
|
||||||
|
String.valueOf(ThumbnailsCacheManager.PREFIX_THUMBNAIL + ocFile.getRemoteId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback to default image
|
||||||
|
if (thumbnail == null) {
|
||||||
|
thumbnail = ThumbnailsCacheManager.mDefaultImg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a file to write bitmap data
|
||||||
|
File f = new File(MainApp.getAppContext().getCacheDir(), ocFile.getFileName());
|
||||||
|
try {
|
||||||
|
f.createNewFile();
|
||||||
|
|
||||||
|
//Convert bitmap to byte array
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, bos);
|
||||||
|
byte[] bitmapData = bos.toByteArray();
|
||||||
|
|
||||||
|
//write the bytes in file
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
try {
|
||||||
|
fos = new FileOutputStream(f);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
fos.write(bitmapData);
|
||||||
|
fos.flush();
|
||||||
|
fos.close();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log_OC.e(TAG, "Error opening file: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType(Uri uri) {
|
||||||
|
OCFile ocFile = getFile(uri);
|
||||||
|
return ocFile.getMimetype();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor query(Uri uri, String[] arg1, String arg2, String[] arg3, String arg4) {
|
||||||
|
MatrixCursor cursor = null;
|
||||||
|
|
||||||
|
OCFile ocFile = getFile(uri);
|
||||||
|
File file = new File(MainApp.getAppContext().getCacheDir(), ocFile.getFileName());
|
||||||
|
if (file.exists()) {
|
||||||
|
cursor = new MatrixCursor(new String[] {
|
||||||
|
OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE });
|
||||||
|
cursor.addRow(new Object[] { uri.getLastPathSegment(),
|
||||||
|
file.length() });
|
||||||
|
}
|
||||||
|
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Uri insert(Uri uri, ContentValues values) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -449,7 +449,8 @@ public class ExpandableUploadListAdapter extends BaseExpandableListAdapter imple
|
||||||
task
|
task
|
||||||
);
|
);
|
||||||
fileIcon.setImageDrawable(asyncDrawable);
|
fileIcon.setImageDrawable(asyncDrawable);
|
||||||
task.execute(fakeFileToCheatThumbnailsCacheManagerInterface);
|
task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(
|
||||||
|
fakeFileToCheatThumbnailsCacheManagerInterface, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,7 +486,7 @@ public class ExpandableUploadListAdapter extends BaseExpandableListAdapter imple
|
||||||
task
|
task
|
||||||
);
|
);
|
||||||
fileIcon.setImageDrawable(asyncDrawable);
|
fileIcon.setImageDrawable(asyncDrawable);
|
||||||
task.execute(file);
|
task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, null));
|
||||||
Log_OC.v(TAG, "Executing task to generate a new thumbnail");
|
Log_OC.v(TAG, "Executing task to generate a new thumbnail");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -343,7 +343,9 @@ public class FileListListAdapter extends BaseAdapter {
|
||||||
if (!file.isFolder()) {
|
if (!file.isFolder()) {
|
||||||
if ((MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file)) && file.getRemoteId() != null) {
|
if ((MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file)) && file.getRemoteId() != null) {
|
||||||
// Thumbnail in Cache?
|
// Thumbnail in Cache?
|
||||||
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(file.getRemoteId());
|
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
|
||||||
|
ThumbnailsCacheManager.PREFIX_THUMBNAIL + String.valueOf(file.getRemoteId())
|
||||||
|
);
|
||||||
if (thumbnail != null && !file.needsUpdateThumbnail()) {
|
if (thumbnail != null && !file.needsUpdateThumbnail()) {
|
||||||
|
|
||||||
if (MimeTypeUtil.isVideo(file)) {
|
if (MimeTypeUtil.isVideo(file)) {
|
||||||
|
@ -375,7 +377,8 @@ public class FileListListAdapter extends BaseAdapter {
|
||||||
);
|
);
|
||||||
fileIcon.setImageDrawable(asyncDrawable);
|
fileIcon.setImageDrawable(asyncDrawable);
|
||||||
asyncTasks.add(task);
|
asyncTasks.add(task);
|
||||||
task.execute(file);
|
task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file,
|
||||||
|
file.getRemoteId()));
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
Log_OC.d(TAG, "ThumbnailGenerationTask : " + e.getMessage());
|
Log_OC.d(TAG, "ThumbnailGenerationTask : " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,7 +204,7 @@ public class LocalFileListAdapter extends BaseAdapter implements FilterableListA
|
||||||
if (MimeTypeUtil.isImage(file)){
|
if (MimeTypeUtil.isImage(file)){
|
||||||
// Thumbnail in Cache?
|
// Thumbnail in Cache?
|
||||||
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
|
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
|
||||||
String.valueOf(file.hashCode())
|
ThumbnailsCacheManager.PREFIX_THUMBNAIL + String.valueOf(file.hashCode())
|
||||||
);
|
);
|
||||||
if (thumbnail != null){
|
if (thumbnail != null){
|
||||||
fileIcon.setImageBitmap(thumbnail);
|
fileIcon.setImageBitmap(thumbnail);
|
||||||
|
@ -226,7 +226,7 @@ public class LocalFileListAdapter extends BaseAdapter implements FilterableListA
|
||||||
task
|
task
|
||||||
);
|
);
|
||||||
fileIcon.setImageDrawable(asyncDrawable);
|
fileIcon.setImageDrawable(asyncDrawable);
|
||||||
task.execute(file);
|
task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, null));
|
||||||
Log_OC.v(TAG, "Executing task to generate a new thumbnail");
|
Log_OC.v(TAG, "Executing task to generate a new thumbnail");
|
||||||
|
|
||||||
} // else, already being generated, don't restart it
|
} // else, already being generated, don't restart it
|
||||||
|
|
|
@ -122,7 +122,7 @@ public class UploaderAdapter extends SimpleAdapter {
|
||||||
task
|
task
|
||||||
);
|
);
|
||||||
fileIcon.setImageDrawable(asyncDrawable);
|
fileIcon.setImageDrawable(asyncDrawable);
|
||||||
task.execute(file);
|
task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, file.getRemoteId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -339,14 +339,10 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case R.id.action_send_file: {
|
case R.id.action_send_file: {
|
||||||
// Obtain the file
|
if (getFile().isDown()) {
|
||||||
if (!getFile().isDown()) { // Download the file
|
|
||||||
Log_OC.d(TAG, getFile().getRemotePath() + " : File must be downloaded");
|
|
||||||
((FileDisplayActivity) mContainerActivity).startDownloadForSending(getFile(),
|
|
||||||
OCFileListFragment.DOWNLOAD_SEND);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
|
mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
|
||||||
|
} else {
|
||||||
|
mContainerActivity.getFileOperationsHelper().sendCachedImage(getFile());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -508,7 +504,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener,
|
||||||
task
|
task
|
||||||
);
|
);
|
||||||
iv.setImageDrawable(asyncDrawable);
|
iv.setImageDrawable(asyncDrawable);
|
||||||
task.execute(file);
|
task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, file.getRemoteId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -970,14 +970,21 @@ public class OCFileListFragment extends ExtendedListFragment implements OCFileLi
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case R.id.action_send_file: {
|
case R.id.action_send_file: {
|
||||||
// Obtain the file
|
if (MimeTypeUtil.isImage(singleFile) && !singleFile.isDown()) {
|
||||||
if (!singleFile.isDown()) { // Download the file
|
mContainerActivity.getFileOperationsHelper().sendCachedImage(singleFile);
|
||||||
Log_OC.d(TAG, singleFile.getRemotePath() + " : File must be downloaded");
|
return true;
|
||||||
((FileDisplayActivity) mContainerActivity).startDownloadForSending(singleFile, DOWNLOAD_SEND);
|
|
||||||
} else {
|
} else {
|
||||||
mContainerActivity.getFileOperationsHelper().sendDownloadedFile(singleFile);
|
// Obtain the file
|
||||||
|
if (!singleFile.isDown()) { // Download the file
|
||||||
|
Log_OC.d(TAG, singleFile.getRemotePath() + " : File must be downloaded");
|
||||||
|
((FileDisplayActivity) mContainerActivity).startDownloadForSending(singleFile,
|
||||||
|
DOWNLOAD_SEND);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
mContainerActivity.getFileOperationsHelper().sendDownloadedFile(singleFile);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
case R.id.action_set_as_wallpaper: {
|
case R.id.action_set_as_wallpaper: {
|
||||||
if (singleFile.isDown()) {
|
if (singleFile.isDown()) {
|
||||||
|
|
|
@ -44,6 +44,7 @@ import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
import com.owncloud.android.lib.resources.shares.OCShare;
|
import com.owncloud.android.lib.resources.shares.OCShare;
|
||||||
import com.owncloud.android.lib.resources.shares.ShareType;
|
import com.owncloud.android.lib.resources.shares.ShareType;
|
||||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
||||||
|
import com.owncloud.android.providers.DiskLruImageCacheFileProvider;
|
||||||
import com.owncloud.android.services.OperationsService;
|
import com.owncloud.android.services.OperationsService;
|
||||||
import com.owncloud.android.services.observer.FileObserverService;
|
import com.owncloud.android.services.observer.FileObserverService;
|
||||||
import com.owncloud.android.ui.activity.FileActivity;
|
import com.owncloud.android.ui.activity.FileActivity;
|
||||||
|
@ -495,6 +496,21 @@ public class FileOperationsHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendCachedImage(OCFile file) {
|
||||||
|
if (file != null) {
|
||||||
|
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
||||||
|
// set MimeType
|
||||||
|
sendIntent.setType(file.getMimetype());
|
||||||
|
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + DiskLruImageCacheFileProvider.AUTHORITY +
|
||||||
|
file.getRemotePath()));
|
||||||
|
sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action
|
||||||
|
|
||||||
|
mFileActivity.startActivity(Intent.createChooser(sendIntent, "Send"));
|
||||||
|
} else {
|
||||||
|
Log_OC.wtf(TAG, "Trying to send a NULL OCFile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setPictureAs(OCFile file) {
|
public void setPictureAs(OCFile file) {
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
if (file.isDown()) {
|
if (file.isDown()) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ public class ImageViewCustom extends AppCompatImageView {
|
||||||
private long mMovieDuration;
|
private long mMovieDuration;
|
||||||
private long mMovieRunDuration;
|
private long mMovieRunDuration;
|
||||||
private long mLastTick;
|
private long mLastTick;
|
||||||
|
protected PreviewImageFragment previewImageFragment;
|
||||||
|
|
||||||
public ImageViewCustom(Context context) {
|
public ImageViewCustom(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
@ -143,4 +144,7 @@ public class ImageViewCustom extends AppCompatImageView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPreviewImageFragment(PreviewImageFragment previewImageFragment) {
|
||||||
|
this.previewImageFragment = previewImageFragment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ public class PreviewImageActivity extends FileActivity implements
|
||||||
}
|
}
|
||||||
|
|
||||||
mPreviewImagePagerAdapter = new PreviewImagePagerAdapter(getSupportFragmentManager(),
|
mPreviewImagePagerAdapter = new PreviewImagePagerAdapter(getSupportFragmentManager(),
|
||||||
parentFolder, getAccount(), getStorageManager(), MainApp.isOnlyOnDevice());
|
parentFolder, getAccount(), getStorageManager(), MainApp.isOnlyOnDevice(), getBaseContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
mViewPager = (ExtendedViewPager) findViewById(R.id.fragmentPager);
|
mViewPager = (ExtendedViewPager) findViewById(R.id.fragmentPager);
|
||||||
|
@ -323,7 +323,7 @@ public class PreviewImageActivity extends FileActivity implements
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requestForDownload(OCFile file) {
|
public void requestForDownload(OCFile file) {
|
||||||
if (mDownloaderBinder == null) {
|
if (mDownloaderBinder == null) {
|
||||||
Log_OC.d(TAG, "requestForDownload called without binder to download service");
|
Log_OC.d(TAG, "requestForDownload called without binder to download service");
|
||||||
|
|
||||||
|
@ -352,10 +352,6 @@ public class PreviewImageActivity extends FileActivity implements
|
||||||
OCFile currentFile = mPreviewImagePagerAdapter.getFileAt(position);
|
OCFile currentFile = mPreviewImagePagerAdapter.getFileAt(position);
|
||||||
getSupportActionBar().setTitle(currentFile.getFileName());
|
getSupportActionBar().setTitle(currentFile.getFileName());
|
||||||
setDrawerIndicatorEnabled(false);
|
setDrawerIndicatorEnabled(false);
|
||||||
if (!currentFile.isDown()
|
|
||||||
&& !mPreviewImagePagerAdapter.pendingErrorAt(position)) {
|
|
||||||
requestForDownload(currentFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call to reset image zoom to initial state
|
// Call to reset image zoom to initial state
|
||||||
((PreviewImagePagerAdapter) mViewPager.getAdapter()).resetZoom();
|
((PreviewImagePagerAdapter) mViewPager.getAdapter()).resetZoom();
|
||||||
|
@ -454,6 +450,10 @@ public class PreviewImageActivity extends FileActivity implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void switchToFullScreen() {
|
||||||
|
hideSystemUI(mFullScreenAnchorView);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onAccountSet(boolean stateWasRecovered) {
|
protected void onAccountSet(boolean stateWasRecovered) {
|
||||||
super.onAccountSet(stateWasRecovered);
|
super.onAccountSet(stateWasRecovered);
|
||||||
|
|
|
@ -36,6 +36,7 @@ import android.os.Process;
|
||||||
import android.support.annotation.DrawableRes;
|
import android.support.annotation.DrawableRes;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.StringRes;
|
import android.support.annotation.StringRes;
|
||||||
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -53,8 +54,10 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import com.caverock.androidsvg.SVG;
|
import com.caverock.androidsvg.SVG;
|
||||||
import com.caverock.androidsvg.SVGParseException;
|
import com.caverock.androidsvg.SVGParseException;
|
||||||
|
import com.owncloud.android.MainApp;
|
||||||
import com.owncloud.android.R;
|
import com.owncloud.android.R;
|
||||||
import com.owncloud.android.datamodel.OCFile;
|
import com.owncloud.android.datamodel.OCFile;
|
||||||
|
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
|
||||||
import com.owncloud.android.files.FileMenuFilter;
|
import com.owncloud.android.files.FileMenuFilter;
|
||||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||||
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
|
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
|
||||||
|
@ -88,7 +91,7 @@ public class PreviewImageFragment extends FileFragment {
|
||||||
|
|
||||||
private static final String ARG_FILE = "FILE";
|
private static final String ARG_FILE = "FILE";
|
||||||
private static final String ARG_IGNORE_FIRST = "IGNORE_FIRST";
|
private static final String ARG_IGNORE_FIRST = "IGNORE_FIRST";
|
||||||
|
private static final String ARG_SHOW_RESIZED_IMAGE = "SHOW_RESIZED_IMAGE";
|
||||||
private static final String SCREEN_NAME = "Image Preview";
|
private static final String SCREEN_NAME = "Image Preview";
|
||||||
|
|
||||||
private TouchImageViewCustom mImageView;
|
private TouchImageViewCustom mImageView;
|
||||||
|
@ -100,6 +103,8 @@ public class PreviewImageFragment extends FileFragment {
|
||||||
protected ImageView mMultiListIcon;
|
protected ImageView mMultiListIcon;
|
||||||
protected ProgressBar mMultiListProgress;
|
protected ProgressBar mMultiListProgress;
|
||||||
|
|
||||||
|
private Boolean mShowResizedImage = false;
|
||||||
|
|
||||||
public Bitmap mBitmap = null;
|
public Bitmap mBitmap = null;
|
||||||
|
|
||||||
private static final String TAG = PreviewImageFragment.class.getSimpleName();
|
private static final String TAG = PreviewImageFragment.class.getSimpleName();
|
||||||
|
@ -122,11 +127,14 @@ public class PreviewImageFragment extends FileFragment {
|
||||||
* {@link FragmentStatePagerAdapter}
|
* {@link FragmentStatePagerAdapter}
|
||||||
* ; TODO better solution
|
* ; TODO better solution
|
||||||
*/
|
*/
|
||||||
public static PreviewImageFragment newInstance(@NonNull OCFile imageFile, boolean ignoreFirstSavedState) {
|
public static PreviewImageFragment newInstance(@NonNull OCFile imageFile, boolean ignoreFirstSavedState,
|
||||||
|
boolean showResizedImage) {
|
||||||
PreviewImageFragment frag = new PreviewImageFragment();
|
PreviewImageFragment frag = new PreviewImageFragment();
|
||||||
|
frag.mShowResizedImage = showResizedImage;
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putParcelable(ARG_FILE, imageFile);
|
args.putParcelable(ARG_FILE, imageFile);
|
||||||
args.putBoolean(ARG_IGNORE_FIRST, ignoreFirstSavedState);
|
args.putBoolean(ARG_IGNORE_FIRST, ignoreFirstSavedState);
|
||||||
|
args.putBoolean(ARG_SHOW_RESIZED_IMAGE, showResizedImage);
|
||||||
frag.setArguments(args);
|
frag.setArguments(args);
|
||||||
return frag;
|
return frag;
|
||||||
}
|
}
|
||||||
|
@ -158,6 +166,7 @@ public class PreviewImageFragment extends FileFragment {
|
||||||
// not right now
|
// not right now
|
||||||
|
|
||||||
mIgnoreFirstSavedState = args.getBoolean(ARG_IGNORE_FIRST);
|
mIgnoreFirstSavedState = args.getBoolean(ARG_IGNORE_FIRST);
|
||||||
|
mShowResizedImage = args.getBoolean(ARG_SHOW_RESIZED_IMAGE);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +180,7 @@ public class PreviewImageFragment extends FileFragment {
|
||||||
super.onCreateView(inflater, container, savedInstanceState);
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
View view = inflater.inflate(R.layout.preview_image_fragment, container, false);
|
View view = inflater.inflate(R.layout.preview_image_fragment, container, false);
|
||||||
mImageView = (TouchImageViewCustom) view.findViewById(R.id.image);
|
mImageView = (TouchImageViewCustom) view.findViewById(R.id.image);
|
||||||
|
mImageView.setPreviewImageFragment(this);
|
||||||
mImageView.setVisibility(View.GONE);
|
mImageView.setVisibility(View.GONE);
|
||||||
|
|
||||||
view.setOnClickListener(new OnClickListener() {
|
view.setOnClickListener(new OnClickListener() {
|
||||||
|
@ -197,6 +207,14 @@ public class PreviewImageFragment extends FileFragment {
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void switchToFullScreen() {
|
||||||
|
((PreviewImageActivity) getActivity()).switchToFullScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void downloadFile() {
|
||||||
|
((PreviewImageActivity) getActivity()).requestForDownload(getFile());
|
||||||
|
}
|
||||||
|
|
||||||
protected void setupMultiView(View view) {
|
protected void setupMultiView(View view) {
|
||||||
mMultiListContainer = (LinearLayout) view.findViewById(R.id.empty_list_view);
|
mMultiListContainer = (LinearLayout) view.findViewById(R.id.empty_list_view);
|
||||||
mMultiListMessage = (TextView) view.findViewById(R.id.empty_list_view_text);
|
mMultiListMessage = (TextView) view.findViewById(R.id.empty_list_view_text);
|
||||||
|
@ -233,11 +251,63 @@ public class PreviewImageFragment extends FileFragment {
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
if (getFile() == null || !getFile().isDown()) {
|
if (getFile() != null) {
|
||||||
showErrorMessage(R.string.preview_image_error_no_local_file);
|
mImageView.setTag(getFile().getFileId());
|
||||||
|
|
||||||
|
if (mShowResizedImage) {
|
||||||
|
Bitmap resizedImage = ThumbnailsCacheManager.getBitmapFromDiskCache(
|
||||||
|
String.valueOf(ThumbnailsCacheManager.PREFIX_RESIZED_IMAGE + getFile().getRemoteId()));
|
||||||
|
|
||||||
|
if (resizedImage != null && !getFile().needsUpdateThumbnail()) {
|
||||||
|
mImageView.setImageBitmap(resizedImage);
|
||||||
|
mImageView.setVisibility(View.VISIBLE);
|
||||||
|
mBitmap = resizedImage;
|
||||||
|
} else {
|
||||||
|
// show thumbnail while loading resized image
|
||||||
|
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
|
||||||
|
String.valueOf(ThumbnailsCacheManager.PREFIX_THUMBNAIL + getFile().getRemoteId()));
|
||||||
|
|
||||||
|
if (thumbnail != null) {
|
||||||
|
mImageView.setImageBitmap(thumbnail);
|
||||||
|
mImageView.setVisibility(View.VISIBLE);
|
||||||
|
mBitmap = thumbnail;
|
||||||
|
} else {
|
||||||
|
thumbnail = ThumbnailsCacheManager.mDefaultImg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate new resized image
|
||||||
|
if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(getFile(), mImageView) &&
|
||||||
|
mContainerActivity.getStorageManager() != null) {
|
||||||
|
final ThumbnailsCacheManager.ResizedImageGenerationTask task =
|
||||||
|
new ThumbnailsCacheManager.ResizedImageGenerationTask(PreviewImageFragment.this,
|
||||||
|
mImageView,
|
||||||
|
mContainerActivity.getStorageManager(),
|
||||||
|
mContainerActivity.getStorageManager().getAccount());
|
||||||
|
if (resizedImage == null) {
|
||||||
|
resizedImage = thumbnail;
|
||||||
|
}
|
||||||
|
final ThumbnailsCacheManager.AsyncResizedImageDrawable asyncDrawable =
|
||||||
|
new ThumbnailsCacheManager.AsyncResizedImageDrawable(
|
||||||
|
MainApp.getAppContext().getResources(),
|
||||||
|
resizedImage,
|
||||||
|
task
|
||||||
|
);
|
||||||
|
mImageView.setImageDrawable(asyncDrawable);
|
||||||
|
task.execute(getFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mMultiView.setVisibility(View.GONE);
|
||||||
|
if (getResources() != null) {
|
||||||
|
mImageView.setBackgroundColor(getResources().getColor(R.color.black));
|
||||||
|
}
|
||||||
|
mImageView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
mLoadBitmapTask = new LoadBitmapTask(mImageView);
|
||||||
|
mLoadBitmapTask.execute(getFile());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mLoadBitmapTask = new LoadBitmapTask(mImageView);
|
showErrorMessage(R.string.preview_image_error_no_local_file);
|
||||||
mLoadBitmapTask.execute(getFile());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,9 +438,15 @@ public class PreviewImageFragment extends FileFragment {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case R.id.action_send_file:
|
case R.id.action_send_file:
|
||||||
mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
|
if (MimeTypeUtil.isImage(getFile()) && !getFile().isDown()) {
|
||||||
return true;
|
mContainerActivity.getFileOperationsHelper().sendCachedImage(getFile());
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case R.id.action_download_file:
|
||||||
case R.id.action_sync_file:
|
case R.id.action_sync_file:
|
||||||
mContainerActivity.getFileOperationsHelper().syncFile(getFile());
|
mContainerActivity.getFileOperationsHelper().syncFile(getFile());
|
||||||
return true;
|
return true;
|
||||||
|
@ -665,6 +741,24 @@ public class PreviewImageFragment extends FileFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setErrorPreviewMessage() {
|
||||||
|
Snackbar.make(mMultiView, R.string.resized_image_not_possible, Snackbar.LENGTH_INDEFINITE)
|
||||||
|
.setAction(R.string.common_yes, new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
downloadFile();
|
||||||
|
}
|
||||||
|
}).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNoConnectionErrorMessage() {
|
||||||
|
try {
|
||||||
|
Snackbar.make(getView(), R.string.auth_no_net_conn_title, Snackbar.LENGTH_LONG).show();
|
||||||
|
} catch (NullPointerException npe) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to test if an {@link OCFile} can be passed to a {@link PreviewImageFragment}
|
* Helper method to test if an {@link OCFile} can be passed to a {@link PreviewImageFragment}
|
||||||
* to be previewed.
|
* to be previewed.
|
||||||
|
@ -691,19 +785,22 @@ public class PreviewImageFragment extends FileFragment {
|
||||||
getFile().getMimetype().equalsIgnoreCase("image/svg+xml")) && getActivity() != null
|
getFile().getMimetype().equalsIgnoreCase("image/svg+xml")) && getActivity() != null
|
||||||
&& getActivity() instanceof PreviewImageActivity && getResources() != null) {
|
&& getActivity() instanceof PreviewImageActivity && getResources() != null) {
|
||||||
PreviewImageActivity previewImageActivity = (PreviewImageActivity) getActivity();
|
PreviewImageActivity previewImageActivity = (PreviewImageActivity) getActivity();
|
||||||
LayerDrawable layerDrawable = (LayerDrawable) mImageView.getDrawable();
|
|
||||||
Drawable layerOne;
|
|
||||||
|
|
||||||
if (previewImageActivity.getSystemUIVisible()) {
|
if (mImageView.getDrawable() instanceof LayerDrawable) {
|
||||||
layerOne = getResources().getDrawable(R.color.white);
|
LayerDrawable layerDrawable = (LayerDrawable) mImageView.getDrawable();
|
||||||
} else {
|
Drawable layerOne;
|
||||||
layerOne = getResources().getDrawable(R.drawable.backrepeat);
|
|
||||||
|
if (previewImageActivity.getSystemUIVisible()) {
|
||||||
|
layerOne = getResources().getDrawable(R.color.white);
|
||||||
|
} else {
|
||||||
|
layerOne = getResources().getDrawable(R.drawable.backrepeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
layerDrawable.setDrawableByLayerId(layerDrawable.getId(0), layerOne);
|
||||||
|
|
||||||
|
mImageView.setImageDrawable(layerDrawable);
|
||||||
|
mImageView.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
layerDrawable.setDrawableByLayerId(layerDrawable.getId(0), layerOne);
|
|
||||||
|
|
||||||
mImageView.setImageDrawable(layerDrawable);
|
|
||||||
mImageView.invalidate();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package com.owncloud.android.ui.preview;
|
package com.owncloud.android.ui.preview;
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
|
import android.content.Context;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.support.v4.app.FragmentStatePagerAdapter;
|
import android.support.v4.app.FragmentStatePagerAdapter;
|
||||||
|
@ -50,6 +51,7 @@ public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter {
|
||||||
private Set<Integer> mObsoletePositions;
|
private Set<Integer> mObsoletePositions;
|
||||||
private Set<Integer> mDownloadErrors;
|
private Set<Integer> mDownloadErrors;
|
||||||
private FileDataStorageManager mStorageManager;
|
private FileDataStorageManager mStorageManager;
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
private Map<Integer, FileFragment> mCachedFragments;
|
private Map<Integer, FileFragment> mCachedFragments;
|
||||||
|
|
||||||
|
@ -63,7 +65,7 @@ public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter {
|
||||||
*/
|
*/
|
||||||
public PreviewImagePagerAdapter(FragmentManager fragmentManager, OCFile parentFolder,
|
public PreviewImagePagerAdapter(FragmentManager fragmentManager, OCFile parentFolder,
|
||||||
Account account, FileDataStorageManager storageManager,
|
Account account, FileDataStorageManager storageManager,
|
||||||
boolean onlyOnDevice) {
|
boolean onlyOnDevice, Context context) {
|
||||||
super(fragmentManager);
|
super(fragmentManager);
|
||||||
|
|
||||||
if (fragmentManager == null) {
|
if (fragmentManager == null) {
|
||||||
|
@ -76,6 +78,7 @@ public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter {
|
||||||
throw new IllegalArgumentException("NULL storage manager");
|
throw new IllegalArgumentException("NULL storage manager");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mContext = context;
|
||||||
mAccount = account;
|
mAccount = account;
|
||||||
mStorageManager = storageManager;
|
mStorageManager = storageManager;
|
||||||
mImageFiles = mStorageManager.getFolderImages(parentFolder, onlyOnDevice);
|
mImageFiles = mStorageManager.getFolderImages(parentFolder, onlyOnDevice);
|
||||||
|
@ -140,16 +143,18 @@ public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter {
|
||||||
OCFile file = mImageFiles.get(i);
|
OCFile file = mImageFiles.get(i);
|
||||||
Fragment fragment;
|
Fragment fragment;
|
||||||
if (file.isDown()) {
|
if (file.isDown()) {
|
||||||
fragment = PreviewImageFragment.newInstance(file, mObsoletePositions.contains(i));
|
fragment = PreviewImageFragment.newInstance(file, mObsoletePositions.contains(i), false);
|
||||||
|
|
||||||
} else if (mDownloadErrors.contains(i)) {
|
|
||||||
fragment = FileDownloadFragment.newInstance(file, mAccount, true);
|
|
||||||
((FileDownloadFragment)fragment).setError(true);
|
|
||||||
mDownloadErrors.remove(i);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fragment = FileDownloadFragment.newInstance(file, mAccount, mObsoletePositions.contains(i));
|
if (mDownloadErrors.contains(i)) {
|
||||||
|
fragment = FileDownloadFragment.newInstance(file, mAccount, true);
|
||||||
|
((FileDownloadFragment) fragment).setError(true);
|
||||||
|
mDownloadErrors.remove(i);
|
||||||
|
} else {
|
||||||
|
fragment = PreviewImageFragment.newInstance(file, mObsoletePositions.contains(i), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mObsoletePositions.remove(i);
|
mObsoletePositions.remove(i);
|
||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import android.os.Build.VERSION;
|
||||||
import android.os.Build.VERSION_CODES;
|
import android.os.Build.VERSION_CODES;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.support.design.widget.Snackbar;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.GestureDetector;
|
import android.view.GestureDetector;
|
||||||
|
@ -35,6 +36,7 @@ import android.view.animation.AccelerateDecelerateInterpolator;
|
||||||
import android.widget.OverScroller;
|
import android.widget.OverScroller;
|
||||||
import android.widget.Scroller;
|
import android.widget.Scroller;
|
||||||
|
|
||||||
|
import com.owncloud.android.R;
|
||||||
import com.owncloud.android.ui.preview.ImageViewCustom;
|
import com.owncloud.android.ui.preview.ImageViewCustom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -888,9 +890,13 @@ public class TouchImageViewCustom extends ImageViewCustom {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
|
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
|
||||||
|
private boolean snackShown = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
||||||
setState(State.ZOOM);
|
setState(State.ZOOM);
|
||||||
|
|
||||||
|
previewImageFragment.switchToFullScreen();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,6 +904,10 @@ public class TouchImageViewCustom extends ImageViewCustom {
|
||||||
public boolean onScale(ScaleGestureDetector detector) {
|
public boolean onScale(ScaleGestureDetector detector) {
|
||||||
scaleImage(detector.getScaleFactor(), detector.getFocusX(), detector.getFocusY(), true);
|
scaleImage(detector.getScaleFactor(), detector.getFocusX(), detector.getFocusY(), true);
|
||||||
|
|
||||||
|
if (!snackShown && getCurrentZoom() > 2 && !previewImageFragment.getFile().isDown()) {
|
||||||
|
showDownloadSnackbar();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// OnTouchImageViewListener is set: TouchImageView pinch zoomed by user.
|
// OnTouchImageViewListener is set: TouchImageView pinch zoomed by user.
|
||||||
//
|
//
|
||||||
|
@ -907,6 +917,20 @@ public class TouchImageViewCustom extends ImageViewCustom {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showDownloadSnackbar() {
|
||||||
|
snackShown = true;
|
||||||
|
|
||||||
|
Snackbar.make(getRootView(), R.string.resized_images_download_full_image, Snackbar.LENGTH_LONG)
|
||||||
|
.setCallback(new Snackbar.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onDismissed(Snackbar snackbar, int event) {
|
||||||
|
super.onDismissed(snackbar, event);
|
||||||
|
snackShown = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setAction(R.string.common_yes, v -> previewImageFragment.downloadFile()).show();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onScaleEnd(ScaleGestureDetector detector) {
|
public void onScaleEnd(ScaleGestureDetector detector) {
|
||||||
super.onScaleEnd(detector);
|
super.onScaleEnd(detector);
|
||||||
|
|
|
@ -709,6 +709,10 @@
|
||||||
<string name="push_notifications_old_login">No push notifications due to outdated login session. Please consider re-adding your account.</string>
|
<string name="push_notifications_old_login">No push notifications due to outdated login session. Please consider re-adding your account.</string>
|
||||||
<string name="push_notifications_temp_error">Push notifications currently not available.</string>
|
<string name="push_notifications_temp_error">Push notifications currently not available.</string>
|
||||||
<string name="date_unknown">Unknown</string>
|
<string name="date_unknown">Unknown</string>
|
||||||
|
|
||||||
|
<string name="resized_image_not_possible">No resized image possible. Download full image?</string>
|
||||||
|
<string name="resized_images_download_full_image">Download full image?</string>
|
||||||
|
|
||||||
<string name="store_short_desc">The Nextcloud Android app allows you to access all your files on your Nextcloud</string>
|
<string name="store_short_desc">The Nextcloud Android app allows you to access all your files on your Nextcloud</string>
|
||||||
<string name="store_full_desc">The Open Source Nextcloud Android app allows you to access all your files on your Nextcloud.\n\nFeatures:\n* Easy, modern interface, fully themed in alignment with your server\'s theming\n* Upload your files to your Nextcloud server\n* Share your files with others\n* Keep your favorite files and folders synced\n* Search across all folders on your server\n* Auto Upload for photos and videos taken by your device\n* Keep up to date with notifications\n* Multi-account support\n* Secure access to your data with fingerprint or pin\n* Integration with DAVdroid for easy setup of Calendar & Contacts synchronization\n\nPlease report all issues at https://github.com/nextcloud/android/issues and discuss this app at https://help.nextcloud.com/c/clients/android\n\nNew to Nextcloud? Nextcloud is a private file sync & share and communication server. It is fully open source and you can host it yourself or pay a company to do it for you. That way, you are in control of your photos, your calendar and contact data, your documents and everything else.\n\nCheck out Nextcloud at https://nextcloud.com</string>
|
<string name="store_full_desc">The Open Source Nextcloud Android app allows you to access all your files on your Nextcloud.\n\nFeatures:\n* Easy, modern interface, fully themed in alignment with your server\'s theming\n* Upload your files to your Nextcloud server\n* Share your files with others\n* Keep your favorite files and folders synced\n* Search across all folders on your server\n* Auto Upload for photos and videos taken by your device\n* Keep up to date with notifications\n* Multi-account support\n* Secure access to your data with fingerprint or pin\n* Integration with DAVdroid for easy setup of Calendar & Contacts synchronization\n\nPlease report all issues at https://github.com/nextcloud/android/issues and discuss this app at https://help.nextcloud.com/c/clients/android\n\nNew to Nextcloud? Nextcloud is a private file sync & share and communication server. It is fully open source and you can host it yourself or pay a company to do it for you. That way, you are in control of your photos, your calendar and contact data, your documents and everything else.\n\nCheck out Nextcloud at https://nextcloud.com</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue