Improve image pre-caching

This commit is contained in:
David-Development 2014-08-31 10:05:07 +02:00
parent d98f9fca9b
commit 5ee44f5acb
8 changed files with 54 additions and 274 deletions

View file

@ -534,10 +534,9 @@ public class NewsReaderListActivity extends MenuUtilsFragmentActivity implements
case R.id.menu_StartImageCaching: case R.id.menu_StartImageCaching:
DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(this); DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(this);
long highestItemId = dbConn.getLowestRssItemIdUnread();//TODO needs testing! long highestItemId = dbConn.getLowestRssItemIdUnread();
Intent service = new Intent(this, DownloadImagesService.class); Intent service = new Intent(this, DownloadImagesService.class);
service.putExtra(DownloadImagesService.LAST_ITEM_ID, highestItemId); service.putExtra(DownloadImagesService.LAST_ITEM_ID, highestItemId);
//service.putExtra(DownloadImagesService.DOWNLOAD_FAVICONS_EXCLUSIVE, true);
startService(service); startService(service);
break; break;

View file

@ -143,7 +143,7 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
int newItemsCount = mPrefs.getInt(Constants.LAST_UPDATE_NEW_ITEMS_COUNT_STRING, 0); int newItemsCount = mPrefs.getInt(Constants.LAST_UPDATE_NEW_ITEMS_COUNT_STRING, 0);
if(newItemsCount > 0) { if(newItemsCount > 0) {
MessageBar messageBar = new MessageBar(getActivity(), true); MessageBar messageBar = new MessageBar(getActivity(), true);
TextMessage textMessage = new TextMessage( newItemsCount + " " + getString(R.string.message_bar_new_articles_available), getString(R.string.message_bar_reload), R.drawable.ic_menu_refresh); TextMessage textMessage = new TextMessage(newItemsCount + " " + getString(R.string.message_bar_new_articles_available), getString(R.string.message_bar_reload), R.drawable.ic_menu_refresh);
textMessage.setClickListener(mListener); textMessage.setClickListener(mListener);
messageBar.show(textMessage); messageBar.show(textMessage);
} }

View file

@ -42,7 +42,7 @@ import de.luhmer.owncloudnewsreader.helper.BitmapDrawableLruCache;
import de.luhmer.owncloudnewsreader.helper.ImageDownloadFinished; import de.luhmer.owncloudnewsreader.helper.ImageDownloadFinished;
import de.luhmer.owncloudnewsreader.helper.ImageHandler; import de.luhmer.owncloudnewsreader.helper.ImageHandler;
public class GetImageAsyncTask extends AsyncTask<Void, Void, String> public class GetImageAsyncTask extends AsyncTask<Void, Void, Bitmap>
{ {
private static final String TAG = "GetImageAsyncTask"; private static final String TAG = "GetImageAsyncTask";
@ -54,17 +54,16 @@ public class GetImageAsyncTask extends AsyncTask<Void, Void, String>
private String rootPath; private String rootPath;
private Context cont; private Context cont;
private BitmapDrawableLruCache lruCache;
public Long feedID = null; public Long feedID = null;
public boolean scaleImage = false; public boolean scaleImage = false;
public int dstHeight; // height in pixels public int dstHeight; // height in pixels
public int dstWidth; // width in pixels public int dstWidth; // width in pixels
Bitmap bmp;
//private ImageView imgView; //private ImageView imgView;
//private WeakReference<ImageView> imageViewReference; //private WeakReference<ImageView> imageViewReference;
public GetImageAsyncTask(String WEB_URL_TO_FILE, ImageDownloadFinished imgDownloadFinished, int AsynkTaskId, String rootPath, Context cont/*, ImageView imageView*/, BitmapDrawableLruCache lruCache) { public GetImageAsyncTask(String WEB_URL_TO_FILE, ImageDownloadFinished imgDownloadFinished, int AsynkTaskId, String rootPath, Context cont, Long feedId) {
try try
{ {
this.WEB_URL_TO_FILE = new URL(WEB_URL_TO_FILE); this.WEB_URL_TO_FILE = new URL(WEB_URL_TO_FILE);
@ -74,7 +73,8 @@ public class GetImageAsyncTask extends AsyncTask<Void, Void, String>
Log.d(TAG, ex.getLocalizedMessage() + " - URL: " + WEB_URL_TO_FILE); Log.d(TAG, ex.getLocalizedMessage() + " - URL: " + WEB_URL_TO_FILE);
//ex.printStackTrace(); //ex.printStackTrace();
} }
this.lruCache = lruCache;
this.feedID = feedID;
this.cont = cont; this.cont = cont;
imageDownloadFinished = imgDownloadFinished; imageDownloadFinished = imgDownloadFinished;
this.AsyncTaskId = AsynkTaskId; this.AsyncTaskId = AsynkTaskId;
@ -83,9 +83,9 @@ public class GetImageAsyncTask extends AsyncTask<Void, Void, String>
} }
@Override @Override
protected void onPostExecute(String result) { protected void onPostExecute(Bitmap result) {
if(imageDownloadFinished != null) if(imageDownloadFinished != null)
imageDownloadFinished.DownloadFinished(AsyncTaskId, result, lruCache); imageDownloadFinished.DownloadFinished(AsyncTaskId, feedID, result);
//imgView.setImageDrawable(GetFavIconFromCache(WEB_URL_TO_FILE.toString(), context)); //imgView.setImageDrawable(GetFavIconFromCache(WEB_URL_TO_FILE.toString(), context));
super.onPostExecute(result); super.onPostExecute(result);
} }
@ -93,7 +93,7 @@ public class GetImageAsyncTask extends AsyncTask<Void, Void, String>
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@SuppressLint("NewApi") @SuppressLint("NewApi")
@Override @Override
protected String doInBackground(Void... params) { protected Bitmap doInBackground(Void... params) {
try try
{ {
File cacheFile = ImageHandler.getFullPathOfCacheFile(WEB_URL_TO_FILE.toString(), rootPath); File cacheFile = ImageHandler.getFullPathOfCacheFile(WEB_URL_TO_FILE.toString(), rootPath);
@ -127,71 +127,25 @@ public class GetImageAsyncTask extends AsyncTask<Void, Void, String>
baf.append((byte) current); baf.append((byte) current);
} }
if(lruCache != null) { bmp = BitmapFactory.decodeByteArray(baf.toByteArray(), 0, baf.length());
if(lruCache.get(feedID) == null) {
Bitmap bmp = BitmapFactory.decodeByteArray(baf.toByteArray(), 0, baf.length()); //If the file is not empty
if(feedID != null && bmp != null) if(baf.length() > 0) {
lruCache.put(feedID, new BitmapDrawable(bmp)); FileOutputStream fos = new FileOutputStream(cacheFile);
} fos.write(baf.toByteArray());
fos.close();
} }
/* Convert the Bytes read to a String. */
FileOutputStream fos = new FileOutputStream(cacheFile);
fos.write(baf.toByteArray());
fos.close();
/*
FileOutputStream fOut = new FileOutputStream(cacheFile);
Bitmap mBitmap = BitmapFactory.decodeStream(WEB_URL_TO_FILE.openStream());
Log.d(TAG, "Downloading image: " + WEB_URL_TO_FILE.toString());
if(mBitmap != null) {
if(scaleImage)
mBitmap = Bitmap.createScaledBitmap(mBitmap, dstWidth, dstHeight, true);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
}
fOut.close();
*/
/*
count++;
if(count >= 25)//Check every 25 images the cache size
{
count = 0;
HashMap<File, Long> files;
long size = ImageHandler.getFolderSize(new File(ImageHandler.getPath(cont)));
size = (long) (size / 1024d / 1024d);
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(cont);
int max_allowed_size = Integer.parseInt(mPrefs.getString(SettingsActivity.SP_MAX_CACHE_SIZE, "1000"));//Default is 1Gb --> 1000mb
if(size > max_allowed_size)
{
files = new HashMap<File, Long>();
for(File file : ImageHandler.getFilesFromDir(new File(ImageHandler.getPathImageCache(cont))))
{
files.put(file, file.lastModified());
}
for(Object itemObj : sortHashMapByValuesD(files).entrySet())
{
File file = (File) itemObj;
file.delete();
size -= file.length();
if(size < max_allowed_size)
break;
}
}
} */
} }
return cacheFile.getPath(); //return cacheFile.getPath();
} }
catch(Exception ex) catch(Exception ex)
{ {
//ex.printStackTrace(); //ex.printStackTrace();
} }
return null; return bmp;
} }

View file

@ -43,6 +43,12 @@ import de.luhmer.owncloudnewsreader.database.model.Feed;
public class FavIconHandler { public class FavIconHandler {
private static final String TAG = "FavIconHandler"; private static final String TAG = "FavIconHandler";
Context context;
public FavIconHandler(Context context) {
this.context = context;
}
public static Drawable GetFavIconFromCache(String URL_TO_PAGE, Context context, Long feedID) public static Drawable GetFavIconFromCache(String URL_TO_PAGE, Context context, Long feedID)
{ {
try try
@ -81,110 +87,29 @@ public class FavIconHandler {
} }
static SparseArray<FavIconCache> imageViewReferences = new SparseArray<FavIconCache>(); public void PreCacheFavIcon(String WEB_URL_TO_FILE, Long feedID) {
Long feedID;
static SparseArray<FavIconCache> favIconToFeedId = new SparseArray<FavIconCache>();
public static void PreCacheFavIcon(String WEB_URL_TO_FILE, Context context, Long feedID) {
FavIconCache favIconCache = new FavIconCache();
favIconCache.context = context;
favIconCache.WEB_URL_TO_FILE = WEB_URL_TO_FILE;
int key = feedID.intValue(); int key = feedID.intValue();
favIconToFeedId.put(key, favIconCache); GetImageAsyncTask giAsync = new GetImageAsyncTask(WEB_URL_TO_FILE, favIconDownloadFinished, key, FileUtils.getPathFavIcons(context), context, feedID);
GetImageAsyncTask giAsync = new GetImageAsyncTask(WEB_URL_TO_FILE, favIconDownloadFinished, key, FileUtils.getPathFavIcons(context), context, null);
giAsync.scaleImage = true; giAsync.scaleImage = true;
giAsync.dstHeight = 2*32; giAsync.dstHeight = 2*32;
giAsync.dstWidth = 2*32; giAsync.dstWidth = 2*32;
giAsync.feedID = feedID; giAsync.feedID = feedID;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
// Execute in parallel AsyncTaskHelper.StartAsyncTask(giAsync, ((Void)null));
giAsync.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ((Void)null));
else
giAsync.execute((Void)null);
} }
static ImageDownloadFinished favIconDownloadFinished = new ImageDownloadFinished() { ImageDownloadFinished favIconDownloadFinished = new ImageDownloadFinished() {
@Override @Override
public void DownloadFinished(int AsynkTaskId, String fileCachePath, BitmapDrawableLruCache lruCache) { public void DownloadFinished(int AsynkTaskId, Long feedId, Bitmap bitmap) {
FavIconCache favIconCache = favIconToFeedId.get(AsynkTaskId); if(bitmap != null) {
FavIconHandler.GetFavIconFromCache(favIconCache.WEB_URL_TO_FILE, favIconCache.context, (long) AsynkTaskId); DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(context);
imageViewReferences.remove(AsynkTaskId); Feed feed = dbConn.getFeedById(feedId);
String avg = ColourCalculator.ColourHexFromBitmap(bitmap);
feed.setAvgColour(avg);
dbConn.updateFeed(feed);
}
} }
}; };
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void GetImageAsync(ImageView imageView, String WEB_URL_TO_FILE, Context context, Long feedID, BitmapDrawableLruCache lruCache)
{
this.feedID = feedID;
boolean setImageAlready = false;
if(lruCache != null) {
if(lruCache.get(feedID) != null) {
if (imageView != null) {
imageView.setImageDrawable(lruCache.get(feedID));
setImageAlready = true;
}
}
}
if(!setImageAlready) {
WeakReference<ImageView> imageViewReference = new WeakReference<ImageView>(imageView);
FavIconCache favIconCache = new FavIconCache();
favIconCache.context = context;
favIconCache.WEB_URL_TO_FILE = WEB_URL_TO_FILE;
favIconCache.imageViewReference = imageViewReference;
int key = 0;
if(imageViewReferences.size() > 0)
key = imageViewReferences.keyAt(imageViewReferences.size() -1) + 1;
imageViewReferences.append(key, favIconCache);
imageView.setImageDrawable(null);
GetImageAsyncTask giAsync = new GetImageAsyncTask(WEB_URL_TO_FILE, imgDownloadFinished, key, FileUtils.getPathFavIcons(context), context/*, imageView*/, lruCache);
giAsync.scaleImage = true;
giAsync.dstHeight = 2*32;
giAsync.dstWidth = 2*32;
giAsync.feedID = feedID;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
giAsync.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ((Void)null));
else
giAsync.execute((Void)null);
}
}
ImageDownloadFinished imgDownloadFinished = new ImageDownloadFinished() {
@Override
public void DownloadFinished(int AsynkTaskId, String fileCachePath, BitmapDrawableLruCache lruCache) {
//WeakReference<ImageView> imageViewRef = imageViewReferences.get(AsynkTaskId);
FavIconCache favIconCache = imageViewReferences.get(AsynkTaskId);
WeakReference<ImageView> imageViewRef = favIconCache.imageViewReference;
if(imageViewRef != null)
{
ImageView imageView = imageViewRef.get();
if (imageView != null) {
BitmapDrawable bd = (BitmapDrawable) FavIconHandler.GetFavIconFromCache(favIconCache.WEB_URL_TO_FILE, favIconCache.context, feedID);
if(lruCache != null && feedID != null && bd != null)
lruCache.put(feedID, bd);
imageView.setImageDrawable(bd);
}
}
imageViewReferences.remove(AsynkTaskId);
}
};
static class FavIconCache
{
public WeakReference<ImageView> imageViewReference;
public String WEB_URL_TO_FILE;
public Context context;
}
} }

View file

@ -22,6 +22,9 @@
package de.luhmer.owncloudnewsreader.helper; package de.luhmer.owncloudnewsreader.helper;
import android.graphics.Bitmap;
import android.support.annotation.NonNull;
public interface ImageDownloadFinished { public interface ImageDownloadFinished {
void DownloadFinished(int AsynkTaskId, String fileCachePath, BitmapDrawableLruCache lruCache); void DownloadFinished(int AsynkTaskId, @NonNull Long feedId, Bitmap bitmap);
} }

View file

@ -1,65 +0,0 @@
/**
* Android ownCloud News
*
* @author David Luhmer
* @copyright 2013 David Luhmer david-dev@live.de
*
* This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.luhmer.owncloudnewsreader.reader;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.util.SparseArray;
import de.luhmer.owncloudnewsreader.async_tasks.GetImageAsyncTask;
import de.luhmer.owncloudnewsreader.helper.BitmapDrawableLruCache;
import de.luhmer.owncloudnewsreader.helper.FileUtils;
import de.luhmer.owncloudnewsreader.helper.ImageDownloadFinished;
public class DownloadItemsToCache {
SparseArray<String> URLs;
Context context;
public DownloadItemsToCache(Context context) {
URLs = new SparseArray<String>();
this.context = context;
}
public void StartDownloadOfImage(String URL_TO_IMAGE)
{
int key = 0;
if(URLs.size() > 0)
key = URLs.keyAt(URLs.size() -1) + 1;
URLs.append(key, URL_TO_IMAGE);
GetImageAsyncTask getImageAsync = new GetImageAsyncTask(URL_TO_IMAGE, imgDownloadFinished, key, FileUtils.getPathImageCache(context), context, null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
getImageAsync.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ((Void) null));// Execute in parallel
else
getImageAsync.execute((Void)null);
}
ImageDownloadFinished imgDownloadFinished = new ImageDownloadFinished() {
@Override
public void DownloadFinished(int AsynkTaskId, String fileCachePath, BitmapDrawableLruCache lruCache) {
}
};
}

View file

@ -135,12 +135,12 @@ public class AsyncTask_GetItems extends AsyncTask_Reader {
listenerInstance.onAsyncTaskCompleted(task_id, ex); listenerInstance.onAsyncTaskCompleted(task_id, ex);
} }
if(ex != null) { if(ex == null && NetworkConnection.isNetworkAvailable(context)) {
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
if (mPrefs.getBoolean(SettingsActivity.CB_CACHE_IMAGES_OFFLINE_STRING, false)) { if (mPrefs.getBoolean(SettingsActivity.CB_CACHE_IMAGES_OFFLINE_STRING, false)) {
if (!NetworkConnection.isWLANConnected(context) && NetworkConnection.isNetworkAvailable(context)) if (!NetworkConnection.isWLANConnected(context))
ShowDownloadImageWithoutWifiQuestion(); ShowDownloadImageWithoutWifiQuestion();
else if (NetworkConnection.isNetworkAvailable(context)) else
StartDownloadingImages(context, highestItemIdBeforeSync, false); StartDownloadingImages(context, highestItemIdBeforeSync, false);
} else { } else {
StartDownloadingImages(context, highestItemIdBeforeSync, true); StartDownloadingImages(context, highestItemIdBeforeSync, true);
@ -150,6 +150,12 @@ public class AsyncTask_GetItems extends AsyncTask_Reader {
detach(); detach();
} }
/**
*
* @param context
* @param highestItemIdBeforeSync
* @param favIconsExclusive indicates if only favIcons should be downloaded
*/
public static void StartDownloadingImages(Context context, long highestItemIdBeforeSync, boolean favIconsExclusive) public static void StartDownloadingImages(Context context, long highestItemIdBeforeSync, boolean favIconsExclusive)
{ {
Intent service = new Intent(context, DownloadImagesService.class); Intent service = new Intent(context, DownloadImagesService.class);
@ -185,32 +191,5 @@ public class AsyncTask_GetItems extends AsyncTask_Reader {
notification.flags |= Notification.FLAG_AUTO_CANCEL; notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification); notificationManager.notify(0, notification);
//final Context contextDownloadImage = this.context;
/*
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
// set title
alertDialogBuilder.setTitle(contextDownloadImage.getString(R.string.no_wifi_available));
// set dialog message
alertDialogBuilder
.setMessage(contextDownloadImage.getString(R.string.do_you_want_to_download_without_wifi))
.setCancelable(true)
.setPositiveButton(contextDownloadImage.getString(android.R.string.yes) ,new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
StartDownloadingImages(contextDownloadImage);
}
})
.setNegativeButton(contextDownloadImage.getString(android.R.string.no) ,new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
*/
} }
} }

View file

@ -28,6 +28,7 @@ import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.util.SparseArray; import android.util.SparseArray;
@ -91,13 +92,6 @@ public class DownloadImagesService extends IntentService {
{ {
if(maxCount == 0) if(maxCount == 0)
notificationManager.cancel(NOTIFICATION_ID); notificationManager.cancel(NOTIFICATION_ID);
/*
else if(maxCount != count)
{
NotificationDownloadImages.setProgress(maxCount, count, false);
NotificationDownloadImages.setContentText("Stopped downloading images. Application was closed.");
notificationManager.notify(NOTIFICATION_ID, NotificationDownloadImages.build());
}*/
} }
super.onDestroy(); super.onDestroy();
} }
@ -116,7 +110,7 @@ public class DownloadImagesService extends IntentService {
for(int i = 0; i < linksFavIcons.size(); i++) { for(int i = 0; i < linksFavIcons.size(); i++) {
int key = linksFavIcons.keyAt(i); int key = linksFavIcons.keyAt(i);
String link = linksFavIcons.get(i); String link = linksFavIcons.get(i);
FavIconHandler.PreCacheFavIcon(link, this, (long) key); new FavIconHandler(this).PreCacheFavIcon(link, (long) key);
} }
@ -219,16 +213,7 @@ public class DownloadImagesService extends IntentService {
ImageDownloadFinished imgDownloadFinished = new ImageDownloadFinished() { ImageDownloadFinished imgDownloadFinished = new ImageDownloadFinished() {
@Override @Override
public void DownloadFinished(int AsynkTaskId, String fileCachePath, BitmapDrawableLruCache lruCache) { public void DownloadFinished(int AsynkTaskId, Long feedId, Bitmap bitmap) {
if(fileCachePath != null) {
File file = new File(fileCachePath);
long size = file.length();
//total_size += size;
if(size == 0)
file.delete();
}
count++; count++;
// Sets the progress indicator to a max value, the // Sets the progress indicator to a max value, the