package edu.mit.mitmobile2.mit150; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; public class MIT150DB { private static final int DATABASE_VERSION = 2; private static final String DATABASE_NAME = "mit150.db"; private static final String FEATURES_TABLE = "features"; private static final String MORE_THUMBS_TABLE = "more_thumbnails"; private static final String FEATURE_ID = "feature_id"; private static final String TITLE = "title"; private static final String SUBTITLE = "subtitle"; private static final String TINT_COLOR = "tint_color"; private static final String TITLE_COLOR = "title_color"; private static final String ARROW_COLOR = "arrow_color"; private static final String URL = "url"; private static final String PHOTO_URL = "photo_url"; private static final String BITMAP = "bitmap"; private static final String DIM_H = "dim_h"; private static final String DIM_W = "dim_w"; static String WHERE_URL = URL+"=?"; static String[] proj_thumb = {URL,BITMAP}; static String[] proj = {FEATURE_ID,TITLE,SUBTITLE,TINT_COLOR,TITLE_COLOR,ARROW_COLOR,URL,PHOTO_URL,BITMAP,DIM_H,DIM_W}; SQLiteOpenHelper mMIT150DBHelper; private static MIT150DB mit150DBInstance = null; public static MIT150DB getInstance(Context context) { if(mit150DBInstance == null) { mit150DBInstance = new MIT150DB(context); return mit150DBInstance; } else { return mit150DBInstance; } } private MIT150DB(Context context) { mMIT150DBHelper = new MIT150DatabaseHelper(context); } public ArrayList<MIT150FeatureItem> getCachedFeatures() { SQLiteDatabase db = mMIT150DBHelper.getReadableDatabase(); ArrayList<MIT150FeatureItem> fs = new ArrayList<MIT150FeatureItem>(); MIT150FeatureItem f; Cursor c = db.query(FEATURES_TABLE, proj, null, null, null, null, null); c.moveToFirst(); while(!c.isAfterLast()) { f = retrieveFeature(c); c.moveToNext(); fs.add(f); } c.close(); // FIXME need to keep same expected order in array.. use hash with title key? return fs; } public void updateFeatures(ArrayList<MIT150FeatureItem> fs) { SQLiteDatabase db = mMIT150DBHelper.getWritableDatabase(); // delete all old entries db.delete(FEATURES_TABLE, null, null); // insert all new replacements for (MIT150FeatureItem f : fs) { saveFeature(f); } } static MIT150FeatureItem retrieveFeature(Cursor cursor) { int feature_id_index = cursor.getColumnIndex(FEATURE_ID); int title_index = cursor.getColumnIndex(TITLE); int subtitle_index = cursor.getColumnIndex(SUBTITLE); int tint_index = cursor.getColumnIndex(TINT_COLOR); int title_color_index = cursor.getColumnIndex(TITLE_COLOR); int arrow_color_index = cursor.getColumnIndex(ARROW_COLOR); int url_index = cursor.getColumnIndex(URL); int photo_index = cursor.getColumnIndex(PHOTO_URL); int bitmap_index = cursor.getColumnIndex(BITMAP); int dim_h_index = cursor.getColumnIndex(DIM_H); int dim_w_index = cursor.getColumnIndex(DIM_W); MIT150FeatureItem item = new MIT150FeatureItem(); item.id = cursor.getString(feature_id_index); item.title = cursor.getString(title_index); item.subtitle = cursor.getString(subtitle_index); item.setTintColor(cursor.getInt(tint_index)); item.setTitleColor(cursor.getInt(title_color_index)); item.setArrowColor(cursor.getInt(arrow_color_index)); item.url = cursor.getString(url_index); item.photo_url = cursor.getString(photo_index); item.dim.height = cursor.getInt(dim_h_index); item.dim.width = cursor.getInt(dim_w_index); byte[] imageBytes = cursor.getBlob(bitmap_index); if (imageBytes!=null) { item.bm = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); assert(item.bm!=null); } return item; } public synchronized void saveFeature(MIT150FeatureItem featureItem) { ContentValues cv = new ContentValues(); cv.put(FEATURE_ID, featureItem.id); cv.put(TITLE, featureItem.title); cv.put(SUBTITLE, featureItem.subtitle); cv.put(TINT_COLOR, featureItem.getTintColor()); cv.put(TITLE_COLOR, featureItem.getTitleColor()); cv.put(ARROW_COLOR, featureItem.getArrowColor()); cv.put(URL, featureItem.url); cv.put(PHOTO_URL, featureItem.photo_url); ByteArrayOutputStream baos = new ByteArrayOutputStream(); cv.put(BITMAP, baos.toByteArray()); cv.put(DIM_H, featureItem.dim.height); cv.put(DIM_W, featureItem.dim.width); //db.update(FEATURES_TABLE, cv, MIT150FeatureItem._ID+"="+featureItem.row_id, null); } /*********************************************************************/ public synchronized void saveMoreThumbnail(MIT150MoreItem moreItem) { @SuppressWarnings("unused") boolean update; //assert(moreItem.bd!=null); if (moreItem.bd==null) { return; } SQLiteDatabase db = mMIT150DBHelper.getWritableDatabase(); // Does it already exist? String[] where_args = new String[]{moreItem.url}; Cursor cursor = db.query(MORE_THUMBS_TABLE, proj_thumb, WHERE_URL, where_args, null, null, null); if (cursor.getCount()==0) update = false; else update = true; cursor.close(); ContentValues cv = new ContentValues(); cv.put(URL, moreItem.url); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { baos.flush(); cv.put(BITMAP, baos.toByteArray()); baos.close(); } catch (IOException e) { e.printStackTrace(); } /* if (update) { int rows = db.update(MORE_THUMBS_TABLE, cv, WHERE_URL, where_args); } else { long row_id = db.insert(MORE_THUMBS_TABLE, null, cv); } */ } void retrieveMoreThumb(MIT150MoreItem item) { SQLiteDatabase db = mMIT150DBHelper.getReadableDatabase(); Cursor cursor = db.query(MORE_THUMBS_TABLE, proj_thumb, WHERE_URL, new String[]{item.url}, null, null, null); if (cursor.getCount()==0) { cursor.close(); return; } cursor.moveToFirst(); int bitmap_index = cursor.getColumnIndex(BITMAP); Bitmap bm; byte[] imageBytes = cursor.getBlob(bitmap_index); cursor.close(); if (imageBytes!=null) { bm = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); //assert(bm!=null); if (bm!=null) item.bd = new BitmapDrawable(bm); } } public void getCachedMoreThumbnails(ArrayList<MIT150MoreFeaturesItem> moreItems) { for (MIT150MoreFeaturesItem mfi : moreItems) { for (MIT150MoreItem mi : mfi.items) { retrieveMoreThumb(mi); } } } /*********************************************************************/ private static class MIT150DatabaseHelper extends SQLiteOpenHelper { MIT150DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + FEATURES_TABLE + " (" + FEATURE_ID + " TEXT," + TITLE + " TEXT," + SUBTITLE + " TEXT," + TINT_COLOR + " INTEGER," + TITLE_COLOR + " INTEGER," + ARROW_COLOR + " INTEGER," + URL + " TEXT," + PHOTO_URL + " TEXT," + BITMAP + " BLOB," + DIM_H + " INTEGER," + DIM_W + " INTEGER" + ");"); db.execSQL("CREATE TABLE " + MORE_THUMBS_TABLE + " (" + URL + " TEXT," + BITMAP + " BLOB" + ");"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // simplist migration possible delete old table, create new table db.execSQL("DROP TABLE " + FEATURES_TABLE + ";"); db.execSQL("DROP TABLE " + MORE_THUMBS_TABLE + ";"); onCreate(db); } } }