package edu.mit.mitmobile2;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.provider.BaseColumns;
import edu.mit.mitmobile2.about.Config;
public class WebImageCacheProvider extends ContentProvider {
public static final String AUTHORITY = Config.release_project_name + ".WebImageCacheProvider";
private static final String DATABASE_NAME = "imageCache.db";
private static final int DATABASE_VERSION = 1;
private static final String IMAGES_TABLE = "images";
public static class Columns implements BaseColumns {
public static final String IMAGE_ID = "_id";
public static final String URL = "url";
public static final String DATA = "data";
public static final String TIMESTAMP = "timestamp";
public static final String SIZE = "size";
}
private static final String URI_STRING = "content://" + AUTHORITY + "/" + IMAGES_TABLE;
public final static Uri CONTENT_URI = Uri.parse(URI_STRING);
private final static UriMatcher sUriMatcher;
private final static int IMAGE_QUERY = 1;
static {
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(AUTHORITY, IMAGES_TABLE, IMAGE_QUERY);
}
private static class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(
"CREATE TABLE " + IMAGES_TABLE + "( " +
Columns.IMAGE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
Columns.URL + " TEXT," +
Columns.DATA + " BLOB," +
Columns.TIMESTAMP + " INTEGER," +
Columns.SIZE + " INTEGER" +
");"
);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
@Override
public String getType(Uri uri) {
if(sUriMatcher.match(uri) == IMAGE_QUERY) {
return "vnd.android.cursor.item/webimage";
}
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
private static final String IMAGE_CACHE_SIZE_TOTAL_KEY = "cache_size_total";
private static final String PREFS_NAME = "WebImageCachePrefs";
private static final long MAX_BYTES = 20000000;
private SharedPreferences mSettings;
private DatabaseHelper mDBHelper;
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
@Override
synchronized public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = mDBHelper.getWritableDatabase();
int size = values.getAsByteArray(Columns.DATA).length;
values.put(Columns.SIZE, size);
values.put(Columns.TIMESTAMP, System.currentTimeMillis());
// prune db to limit the total size of all the cached images
long currentCacheTotal = mSettings.getLong(IMAGE_CACHE_SIZE_TOTAL_KEY, 0);
if(currentCacheTotal > MAX_BYTES) {
Cursor cursor = db.query(
IMAGES_TABLE,
new String[] { Columns.IMAGE_ID, Columns.SIZE },
null, null, null, null,
Columns.TIMESTAMP + " ASC"
);
int idIndex = cursor.getColumnIndex(Columns.IMAGE_ID);
int sizeIndex = cursor.getColumnIndex(Columns.SIZE);
if(cursor.moveToFirst()) {
do {
long imageId = cursor.getLong(idIndex);
long imageSize = cursor.getLong(sizeIndex);
db.delete(IMAGES_TABLE, Columns.IMAGE_ID + "=?", new String[] {Long.toString(imageId)});
currentCacheTotal -= imageSize;
cursor.moveToNext();
} while(currentCacheTotal > MAX_BYTES && !cursor.isAfterLast());
}
// clean up
cursor.close();
mSettings.edit()
.putLong(IMAGE_CACHE_SIZE_TOTAL_KEY, currentCacheTotal)
.commit();
}
db.insertOrThrow(IMAGES_TABLE, Columns.SIZE, values);
mSettings.edit()
.putLong(IMAGE_CACHE_SIZE_TOTAL_KEY, currentCacheTotal+size)
.commit();
// only want client code to access images by URL, so don't need to return ID info
return null;
}
@Override
public boolean onCreate() {
mDBHelper = new DatabaseHelper(getContext());
mSettings = getContext().getSharedPreferences(PREFS_NAME, 0);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
if(sUriMatcher.match(uri) == IMAGE_QUERY) {
SQLiteDatabase db = mDBHelper.getReadableDatabase();
return db.query(IMAGES_TABLE, projection, selection, selectionArgs, null, null, Columns.TIMESTAMP + " DESC", "1");
}
throw new IllegalArgumentException("Uknown URI" + uri);
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
throw new RuntimeException("Update not implemented for this content provider");
}
}