-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resized images #1599
Resized images #1599
Changes from all commits
876fab3
f8a4776
8122ee8
49b7489
84976d1
7d901b1
d189859
04d4dbf
bab67ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -129,9 +129,9 @@ | |
android:name=".providers.FileContentProvider" | ||
android:authorities="@string/authority" | ||
android:enabled="true" | ||
android:exported="true" | ||
android:exported="false" | ||
android:label="@string/sync_string_files" | ||
android:syncable="true" /> | ||
android:syncable="false" /> | ||
|
||
<provider | ||
android:name=".providers.UsersAndGroupsSearchProvider" | ||
|
@@ -152,6 +152,12 @@ | |
</intent-filter> | ||
</provider> | ||
|
||
<provider | ||
android:name=".ui.adapter.DiskLruImageCacheFileProvider" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is a new exported provider needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is for sending cached images to other apps. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is a different functionality requiring specific tests. I will move it to a separate branch. Please, include in the description of the PR a summary of all the changes. Otherwise the test plans could not match the scope of the changes, since we don't keep an strict order for the tasks of reviewing code and defining tests - tasks that should be independent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm sorry, you already commented it in the description: "it can be used to send via whatsapp, or as a file to another app". I apologize. |
||
android:authorities="com.owncloud.imageCache.provider" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Self-note: check if should be in setup.xml |
||
android:exported="true"> | ||
</provider> | ||
|
||
<activity | ||
android:name=".authentication.AuthenticatorActivity" | ||
android:exported="true" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,18 +29,25 @@ | |
import org.apache.commons.httpclient.methods.GetMethod; | ||
|
||
import android.accounts.Account; | ||
import android.accounts.AccountManager; | ||
import android.content.Context; | ||
import android.content.res.Resources; | ||
import android.graphics.Bitmap; | ||
import android.graphics.Bitmap.CompressFormat; | ||
import android.graphics.BitmapFactory; | ||
import android.graphics.Point; | ||
import android.graphics.Canvas; | ||
import android.graphics.drawable.BitmapDrawable; | ||
import android.graphics.drawable.ColorDrawable; | ||
import android.graphics.drawable.Drawable; | ||
import android.media.ThumbnailUtils; | ||
import android.net.Uri; | ||
import android.os.AsyncTask; | ||
import android.view.Display; | ||
import android.view.View; | ||
import android.view.WindowManager; | ||
import android.widget.ImageView; | ||
import android.widget.ProgressBar; | ||
|
||
import com.owncloud.android.MainApp; | ||
import com.owncloud.android.R; | ||
|
@@ -58,27 +65,27 @@ | |
* Manager for concurrent access to thumbnails cache. | ||
*/ | ||
public class ThumbnailsCacheManager { | ||
|
||
private static final String TAG = ThumbnailsCacheManager.class.getSimpleName(); | ||
|
||
private static final String CACHE_FOLDER = "thumbnailCache"; | ||
|
||
private static final Object mThumbnailsDiskCacheLock = new Object(); | ||
private static DiskLruImageCache mThumbnailCache = null; | ||
private static boolean mThumbnailCacheStarting = true; | ||
|
||
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB | ||
private static final CompressFormat mCompressFormat = CompressFormat.JPEG; | ||
private static final int mCompressQuality = 70; | ||
private static OwnCloudClient mClient = null; | ||
|
||
public static Bitmap mDefaultImg = | ||
public static Bitmap mDefaultImg = | ||
BitmapFactory.decodeResource( | ||
MainApp.getAppContext().getResources(), | ||
R.drawable.file_image | ||
); | ||
|
||
|
||
public static class InitDiskCacheTask extends AsyncTask<File, Void, Void> { | ||
|
||
@Override | ||
|
@@ -88,17 +95,17 @@ protected Void doInBackground(File... params) { | |
|
||
if (mThumbnailCache == null) { | ||
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 | ||
final String cachePath = | ||
MainApp.getAppContext().getExternalCacheDir().getPath() + | ||
File.separator + CACHE_FOLDER; | ||
final String cachePath = | ||
MainApp.getAppContext().getExternalCacheDir().getPath() + | ||
File.separator + CACHE_FOLDER; | ||
Log_OC.d(TAG, "create dir: " + cachePath); | ||
final File diskCacheDir = new File(cachePath); | ||
mThumbnailCache = new DiskLruImageCache( | ||
diskCacheDir, | ||
DISK_CACHE_SIZE, | ||
mCompressFormat, | ||
diskCacheDir, | ||
DISK_CACHE_SIZE, | ||
mCompressFormat, | ||
mCompressQuality | ||
); | ||
} catch (Exception e) { | ||
|
@@ -112,8 +119,8 @@ protected Void doInBackground(File... params) { | |
return null; | ||
} | ||
} | ||
|
||
|
||
public static void addBitmapToCache(String key, Bitmap bitmap) { | ||
synchronized (mThumbnailsDiskCacheLock) { | ||
if (mThumbnailCache != null) { | ||
|
@@ -142,11 +149,12 @@ public static Bitmap getBitmapFromDiskCache(String key) { | |
|
||
public static class ThumbnailGenerationTask extends AsyncTask<Object, Void, Bitmap> { | ||
private final WeakReference<ImageView> mImageViewReference; | ||
private WeakReference<ProgressBar> mProgressWheelRef; | ||
private static Account mAccount; | ||
private Object mFile; | ||
private Boolean mIsThumbnail; | ||
private FileDataStorageManager mStorageManager; | ||
|
||
|
||
public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, | ||
Account account) { | ||
// Use a WeakReference to ensure the ImageView can be garbage collected | ||
|
@@ -157,6 +165,12 @@ public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager stora | |
mAccount = account; | ||
} | ||
|
||
public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, | ||
Account account, ProgressBar progressWheel) { | ||
this(imageView, storageManager, account); | ||
mProgressWheelRef = new WeakReference<ProgressBar>(progressWheel); | ||
} | ||
|
||
public ThumbnailGenerationTask(ImageView imageView) { | ||
// Use a WeakReference to ensure the ImageView can be garbage collected | ||
mImageViewReference = new WeakReference<ImageView>(imageView); | ||
|
@@ -177,21 +191,24 @@ protected Bitmap doInBackground(Object... params) { | |
} | ||
|
||
mFile = params[0]; | ||
|
||
mIsThumbnail = (Boolean) params[1]; | ||
|
||
|
||
if (mFile instanceof OCFile) { | ||
thumbnail = doOCFileInBackground(); | ||
thumbnail = doOCFileInBackground(mIsThumbnail); | ||
} else if (mFile instanceof File) { | ||
thumbnail = doFileInBackground(); | ||
//} else { do nothing | ||
thumbnail = doFileInBackground(mIsThumbnail); | ||
} else { | ||
// do nothing | ||
} | ||
|
||
}catch(Throwable t){ | ||
// the app should never break due to a problem with thumbnails | ||
Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t); | ||
if (t instanceof OutOfMemoryError) { | ||
System.gc(); | ||
} | ||
}catch(Throwable t){ | ||
// the app should never break due to a problem with thumbnails | ||
Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t); | ||
if (t instanceof OutOfMemoryError) { | ||
System.gc(); | ||
} | ||
} | ||
|
||
return thumbnail; | ||
} | ||
|
@@ -208,7 +225,14 @@ protected void onPostExecute(Bitmap bitmap){ | |
tagId = String.valueOf(mFile.hashCode()); | ||
} | ||
if (String.valueOf(imageView.getTag()).equals(tagId)) { | ||
if (mProgressWheelRef != null) { | ||
final ProgressBar progressWheel = mProgressWheelRef.get(); | ||
if (progressWheel != null) { | ||
progressWheel.setVisibility(View.GONE); | ||
} | ||
} | ||
imageView.setImageBitmap(bitmap); | ||
// imageView.setVisibility(View.VISIBLE); | ||
} | ||
} | ||
} | ||
|
@@ -219,12 +243,13 @@ protected void onPostExecute(Bitmap bitmap){ | |
* @param imageKey: thumb key | ||
* @param bitmap: image for extracting thumbnail | ||
* @param path: image path | ||
* @param px: thumbnail dp | ||
* @param pxW: thumbnail width | ||
* @param pxH: thumbnail height | ||
* @return Bitmap | ||
*/ | ||
private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int px){ | ||
private 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 | ||
thumbnail = BitmapUtils.rotateImage(thumbnail,path); | ||
|
@@ -245,31 +270,54 @@ private int getThumbnailDimension(){ | |
return Math.round(r.getDimension(R.dimen.file_icon_size_grid)); | ||
} | ||
|
||
private Bitmap doOCFileInBackground() { | ||
private Point getScreenDimension(){ | ||
WindowManager wm = (WindowManager) MainApp.getAppContext().getSystemService(Context.WINDOW_SERVICE); | ||
Display display = wm.getDefaultDisplay(); | ||
Point test = new Point(); | ||
display.getSize(test); | ||
return test; | ||
} | ||
|
||
private Bitmap doOCFileInBackground(Boolean isThumbnail) { | ||
Bitmap thumbnail = null; | ||
OCFile file = (OCFile)mFile; | ||
|
||
final String imageKey = String.valueOf(file.getRemoteId()); | ||
// distinguish between thumbnail and resized image | ||
String temp = String.valueOf(file.getRemoteId()); | ||
if (isThumbnail){ | ||
temp = "t" + temp; | ||
} else { | ||
temp = "r" + temp; | ||
} | ||
|
||
final String imageKey = temp; | ||
|
||
// Check disk cache in background thread | ||
Bitmap thumbnail = getBitmapFromDiskCache(imageKey); | ||
thumbnail = getBitmapFromDiskCache(imageKey); | ||
|
||
// Not found in disk cache | ||
if (thumbnail == null || file.needsUpdateThumbnail()) { | ||
|
||
int px = getThumbnailDimension(); | ||
int pxW = 0; | ||
int pxH = 0; | ||
if (mIsThumbnail) { | ||
pxW = pxH = getThumbnailDimension(); | ||
} else { | ||
Point p = getScreenDimension(); | ||
pxW = p.x; | ||
pxH = p.y; | ||
} | ||
|
||
if (file.isDown()) { | ||
Bitmap temp = BitmapUtils.decodeSampledBitmapFromFile( | ||
file.getStoragePath(), px, px); | ||
Bitmap bitmap = ThumbnailUtils.extractThumbnail(temp, px, px); | ||
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile( | ||
file.getStoragePath(), pxW, pxH); | ||
|
||
if (bitmap != null) { | ||
// Handle 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); | ||
mStorageManager.saveFile(file); | ||
|
@@ -284,18 +332,25 @@ private Bitmap doOCFileInBackground() { | |
try { | ||
String uri = mClient.getBaseUri() + "" + | ||
"/index.php/apps/files/api/v1/thumbnail/" + | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please, set a constant for this |
||
px + "/" + px + Uri.encode(file.getRemotePath(), "/"); | ||
pxW + "/" + pxH + Uri.encode(file.getRemotePath(), "/"); | ||
Log_OC.d("Thumbnail", "URI: " + uri); | ||
get = new GetMethod(uri); | ||
int status = mClient.executeMethod(get); | ||
if (status == HttpStatus.SC_OK) { | ||
InputStream inputStream = get.getResponseBodyAsStream(); | ||
Bitmap bitmap = BitmapFactory.decodeStream(inputStream); | ||
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px); | ||
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH); | ||
byte[] bytes = get.getResponseBody(); | ||
|
||
if (mIsThumbnail) { | ||
thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH); | ||
} else { | ||
thumbnail = bitmap; | ||
} | ||
|
||
// Handle PNG | ||
if (file.getMimetype().equalsIgnoreCase("image/png")) { | ||
thumbnail = handlePNG(thumbnail, px); | ||
thumbnail = handlePNG(thumbnail, pxW); | ||
} | ||
|
||
// Add thumbnail to cache | ||
|
@@ -336,24 +391,39 @@ private Bitmap handlePNG(Bitmap bitmap, int px){ | |
return resultBitmap; | ||
} | ||
|
||
private Bitmap doFileInBackground() { | ||
private Bitmap doFileInBackground(Boolean mIsThumbnail) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Self note: why not boolean? |
||
File file = (File)mFile; | ||
|
||
final String imageKey = String.valueOf(file.hashCode()); | ||
// distinguish between thumbnail and resized image | ||
String temp = String.valueOf(file.hashCode()); | ||
if (mIsThumbnail){ | ||
temp = "t" + temp; | ||
} else { | ||
temp = "r" + temp; | ||
} | ||
|
||
final String imageKey = temp; | ||
|
||
// Check disk cache in background thread | ||
Bitmap thumbnail = getBitmapFromDiskCache(imageKey); | ||
|
||
// Not found in disk cache | ||
if (thumbnail == null) { | ||
|
||
int px = getThumbnailDimension(); | ||
int pxW = 0; | ||
int pxH = 0; | ||
if (mIsThumbnail) { | ||
pxW = pxH = getThumbnailDimension(); | ||
} else { | ||
Point p = getScreenDimension(); | ||
pxW = p.x; | ||
pxH = p.y; | ||
} | ||
|
||
Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile( | ||
file.getAbsolutePath(), px, px); | ||
file.getAbsolutePath(), pxW, pxH); | ||
|
||
if (bitmap != null) { | ||
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px); | ||
thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), pxW, pxH); | ||
} | ||
} | ||
return thumbnail; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self-note: this was set to true with addition of Document Provider.