package com.marshalchen.common.uimodule.tileView.tileview.tiles;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.support.v4.util.LruCache;
import com.marshalchen.common.DiskLruCache.DiskLruCache;
import java.io.*;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class TileCache {
private static final int DISK_CACHE_CAPACITY = 8 * 1024;
private static final int IO_BUFFER_SIZE = 8 * 1024;
private static final int COMPRESSION_QUALITY = 40;
private static final BitmapFactory.Options BITMAPFACTORY_OPTIONS = new BitmapFactory.Options();
static {
BITMAPFACTORY_OPTIONS.inPreferredConfig = Bitmap.Config.RGB_565;
}
private MessageDigest digest;
private LruCache<String, Bitmap> memoryCache;
private DiskLruCache diskCache;
// TODO: register local broadcast receiver to destroy the cache during onDestroy of containing Activity
public TileCache( final Context context ) {
try {
digest = MessageDigest.getInstance( "MD5" );
} catch ( NoSuchAlgorithmException e1 ) {
}
// in memory cache
final int memory = (int) ( Runtime.getRuntime().maxMemory() / 1024 );
final int size = memory / 8;
memoryCache = new LruCache<String, Bitmap>( size ) {
@Override
protected int sizeOf( String key, Bitmap bitmap ) {
// The cache size will be measured in kilobytes rather than number of items.
// emulate bitmap.getByteCount for APIs less than 12
int byteCount = bitmap.getRowBytes() * bitmap.getHeight();
return byteCount / 1024;
}
};
// disk cache
new Thread(new Runnable(){
@Override
public void run(){
File cacheDirectory = new File( context.getCacheDir().getPath() + File.separator + "com/qozix/mapview" );
try {
diskCache = DiskLruCache.open( cacheDirectory, 1, 1, DISK_CACHE_CAPACITY );
} catch ( IOException e ) {
}
}
}).start();
}
public void addBitmap( String key, Bitmap bitmap ) {
addBitmapToMemoryCache( key, bitmap );
addBitmapToDiskCache( key, bitmap );
}
public Bitmap getBitmap( String key ) {
Bitmap bitmap = getBitmapFromMemoryCache( key );
if ( bitmap == null ) {
bitmap = getBitmapFromDiskCache( key );
}
return bitmap;
}
public void destroy(){
memoryCache.evictAll();
memoryCache = null;
new Thread(new Runnable(){
@Override
public void run(){
try {
diskCache.delete();
diskCache = null;
} catch ( IOException e ) {
}
}
}).start();
}
public void clear() {
memoryCache.evictAll();
new Thread(new Runnable(){
@Override
public void run(){
try {
diskCache.delete();
} catch ( IOException e ) {
}
}
}).start();
}
private void addBitmapToMemoryCache( String key, Bitmap bitmap ) {
if ( key == null || bitmap == null ) {
return;
}
if ( getBitmapFromMemoryCache( key ) == null ) {
memoryCache.put( key, bitmap );
}
}
private Bitmap getBitmapFromMemoryCache( String key ) {
return memoryCache.get( key );
}
private void addBitmapToDiskCache( String key, Bitmap bitmap ) {
if ( diskCache == null ) {
return;
}
key = getMD5( key );
DiskLruCache.Editor editor = null;
try {
editor = diskCache.edit( key );
if ( editor == null ) {
return;
}
OutputStream output = null;
try {
output = new BufferedOutputStream( editor.newOutputStream( 0 ), IO_BUFFER_SIZE );
boolean compressed = bitmap.compress( CompressFormat.JPEG, COMPRESSION_QUALITY, output );
if ( compressed ) {
diskCache.flush();
editor.commit();
} else {
editor.abort();
}
} finally {
if ( output != null ) {
output.close();
}
}
} catch ( IOException e ) {
try {
if ( editor != null ) {
editor.abort();
}
} catch ( IOException io ) {
}
}
}
private Bitmap getBitmapFromDiskCache( String key ) {
if ( diskCache == null ) {
return null;
}
key = getMD5( key );
Bitmap bitmap = null;
DiskLruCache.Snapshot snapshot = null;
try {
snapshot = diskCache.get( key );
if ( snapshot == null ) {
return null;
}
final InputStream input = snapshot.getInputStream( 0 );
if ( input != null ) {
BufferedInputStream buffered = new BufferedInputStream( input, IO_BUFFER_SIZE );
bitmap = BitmapFactory.decodeStream( buffered, null, BITMAPFACTORY_OPTIONS );
}
} catch ( IOException e ) {
} finally {
if ( snapshot != null ) {
snapshot.close();
}
}
return bitmap;
}
private String getMD5( String fileName ) {
if ( digest != null ) {
digest.update( fileName.getBytes(), 0, fileName.length() );
return new BigInteger( 1, digest.digest() ).toString( 16 );
}
// if digest is unavailable, at least make some attempt at an acceptable filename
return fileName.replace("[^a-z0-9_-]", "_");
}
}