package com.gnod.geekr.tool.manager;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.util.Log;
import com.gnod.geekr.BuildConfig;
public class ImageFetcher extends ImageResizer {
private static final String TAG = ImageFetcher.class.getSimpleName();
private static final long HTTP_CACHE_SIZE = 10 * 1024 * 1024; //10MB
private static final int IO_BUFFER_SIZE = 8 * 1024;
private static final String HTTP_CACHE_DIR = "http";
private static final int DISK_CACHE_INDEX = 0;
private File mHttpCacheDir;
private final Object mHttpDiskCacheLock = new Object();
private DiskLruCache mHttpDiskCache;
private boolean mHttpDiskCacheStarting = true;
public ImageFetcher(Context context, ImageCache imageCache, int imageSize) {
this(context, imageCache, imageSize, imageSize);
}
public ImageFetcher(Context context, ImageCache imageCache, int imageWidth,
int imageHeight) {
super(context, imageCache, imageWidth, imageHeight);
init(context);
}
private void init(Context context) {
checkConnection(context);
mHttpCacheDir = ImageCache.getDiskCacheDir(context, HTTP_CACHE_DIR);
}
@Override
protected void initDiskCacheInternal() {
super.initDiskCacheInternal();
initHttpDiskCache();
}
private void initHttpDiskCache() {
if (!mHttpCacheDir.exists()) {
mHttpCacheDir.mkdirs();
}
synchronized (mHttpDiskCacheLock) {
if (ImageCache.getUsableSpace(mHttpCacheDir) > HTTP_CACHE_SIZE) {
try {
mHttpDiskCache = DiskLruCache.open(mHttpCacheDir, 1, 1, HTTP_CACHE_SIZE);
} catch (IOException e) {
mHttpDiskCache = null;
}
}
mHttpDiskCacheStarting = false;
mHttpDiskCacheLock.notifyAll();
}
}
@Override
protected Bitmap processBitmap(Object data) {
return processBitmap(String.valueOf(data));
}
private Bitmap processBitmap(String data) {
if (BuildConfig.DEBUG) {
Log.d(TAG, "processBitmap - " + data);
}
final String key = ImageCache.hashKeyForDisk(data);
FileDescriptor fd = null;
FileInputStream fileInputStream = null;
DiskLruCache.Snapshot snapshot;
synchronized (mHttpDiskCacheLock) {
while (mHttpDiskCacheStarting) {
try {
mHttpDiskCacheLock.wait();
} catch (InterruptedException e) {
}
}
if (mHttpDiskCache != null) {
try {
snapshot = mHttpDiskCache.get(key);
if (snapshot == null) {
if (BuildConfig.DEBUG) {
Log.d(TAG, "processBitmap, not found in http cache, downloading...");
}
DiskLruCache.Editor editor = mHttpDiskCache.edit(key);
if (editor != null) {
if (downloadUrlToStream(data, editor.newOutputStream(DISK_CACHE_INDEX))) {
editor.commit();
} else {
editor.abort();
}
}
snapshot = mHttpDiskCache.get(key);
} else {
if (BuildConfig.DEBUG) {
Log.d(TAG, "processBitmap, found in http disk cache");
}
}
if (snapshot != null) {
fileInputStream = (FileInputStream) snapshot.getInputStream(DISK_CACHE_INDEX);
fd = fileInputStream.getFD();
}
} catch (IOException e) {
Log.e(TAG, "processBitmap - " + e);
} catch (IllegalStateException e) {
Log.e(TAG, "processBitmap - " + e);
} finally {
if (fd == null && fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {}
}
}
}
}
Bitmap bitmap = null;
if (fd != null) {
bitmap = decodeSampledBitmapFromDescriptor(fd, mImageWidth, mImageHeight, getImageCache());
}
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {}
}
return bitmap;
}
private boolean downloadUrlToStream(String data,
OutputStream newOutputStream) {
disableConnectionReuseIfNecessary();
HttpURLConnection urlConnection = null;
BufferedInputStream input = null;
BufferedOutputStream output = null;
try {
final URL url = new URL(data);
// DefaultHttpClient httpClient = new DefaultHttpClient();
// HttpGet request = new HttpGet(url);
// HttpResponse response = httpClient.execute(request);
// InputStream inputStream = response.getEntity().getContent();
// bitmap = BitmapFactory.decodeStream(inputStream);
// inputStream.close();
urlConnection = (HttpURLConnection) url.openConnection();
input = new BufferedInputStream(urlConnection.getInputStream(), IO_BUFFER_SIZE);
output = new BufferedOutputStream(newOutputStream, IO_BUFFER_SIZE);
int b;
while ((b = input.read()) != -1) {
output.write(b);
}
return true;
} catch (final IOException e) {
Log.e(TAG, "Error in downloadBitmap - " + e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
try {
if (output != null) {
output.close();
}
if (input != null) {
input.close();
}
} catch (final IOException e) {}
}
return false;
}
/**
* Workaround for bug pre-Froyo, see here for more info:
* http://android-developers.blogspot.com/2011/09/androids-http-clients.html
*/
public static void disableConnectionReuseIfNecessary() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) {
System.setProperty("http.keepAlive", "false");
}
}
@Override
protected void clearCacheInternal() {
super.clearCacheInternal();
synchronized (mHttpDiskCacheLock) {
if (mHttpDiskCache != null && !mHttpDiskCache.isClosed()) {
try {
mHttpDiskCache.delete();
if (BuildConfig.DEBUG) {
Log.d(TAG, "HTTP cache cleared");
}
} catch (IOException e) {
Log.e(TAG, "clearCacheInternal - " + e);
}
mHttpDiskCache = null;
mHttpDiskCacheStarting = true;
initHttpDiskCache();
}
}
}
@Override
protected void flushCacheInternal() {
super.flushCacheInternal();
synchronized (mHttpDiskCacheLock) {
if (mHttpDiskCache != null) {
try {
mHttpDiskCache.flush();
if (BuildConfig.DEBUG) {
Log.d(TAG, "HTTP cache flushed");
}
} catch (IOException e) {
Log.e(TAG, "flush - " + e);
}
}
}
}
@Override
protected void closeCacheInternal() {
super.closeCacheInternal();
synchronized (mHttpDiskCacheLock) {
if (mHttpDiskCache != null) {
try {
if (!mHttpDiskCache.isClosed()) {
mHttpDiskCache.close();
mHttpDiskCache = null;
if (BuildConfig.DEBUG) {
Log.d(TAG, "HTTP cache closed");
}
}
} catch (IOException e) {
Log.e(TAG, "closeCacheInternal - " + e);
}
}
}
}
private void checkConnection(Context context) {
final ConnectivityManager mgr =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo info = mgr.getActiveNetworkInfo();
if (info == null || !info.isConnectedOrConnecting()) {
Log.e(TAG, "checkConnection - no connection found");
}
}
}