diff options
Diffstat (limited to 'src')
7 files changed, 174 insertions, 43 deletions
diff --git a/src/com/android/gallery3d/data/LocalAlbum.java b/src/com/android/gallery3d/data/LocalAlbum.java index 6c5feb5c8..7b7015af6 100644 --- a/src/com/android/gallery3d/data/LocalAlbum.java +++ b/src/com/android/gallery3d/data/LocalAlbum.java @@ -20,6 +20,7 @@ import android.content.ContentResolver; import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; +import android.os.Environment; import android.provider.MediaStore; import android.provider.MediaStore.Images; import android.provider.MediaStore.Images.ImageColumns; @@ -29,9 +30,11 @@ import android.provider.MediaStore.Video.VideoColumns; import com.android.gallery3d.R; import com.android.gallery3d.app.GalleryApp; import com.android.gallery3d.common.Utils; +import com.android.gallery3d.util.BucketNames; import com.android.gallery3d.util.GalleryUtils; import com.android.gallery3d.util.MediaSetUtils; +import java.io.File; import java.util.ArrayList; // LocalAlbumSet lists all media items in one bucket on local storage. @@ -290,4 +293,33 @@ public class LocalAlbum extends MediaSet { return name; } } + + // Relative path is the absolute path minus external storage path + public static String getRelativePath(int bucketId) { + String relativePath = "/"; + if (bucketId == MediaSetUtils.CAMERA_BUCKET_ID) { + relativePath += BucketNames.CAMERA; + } else if (bucketId == MediaSetUtils.DOWNLOAD_BUCKET_ID) { + relativePath += BucketNames.DOWNLOAD; + } else if (bucketId == MediaSetUtils.IMPORTED_BUCKET_ID) { + relativePath += BucketNames.IMPORTED; + } else if (bucketId == MediaSetUtils.SNAPSHOT_BUCKET_ID) { + relativePath += BucketNames.SCREENSHOTS; + } else if (bucketId == MediaSetUtils.EDITED_ONLINE_PHOTOS_BUCKET_ID) { + relativePath += BucketNames.EDITED_ONLINE_PHOTOS; + } else { + // If the first few cases didn't hit the matching path, do a + // thorough search in the local directories. + File extStorage = Environment.getExternalStorageDirectory(); + String path = GalleryUtils.searchDirForPath(extStorage, bucketId); + if (path == null) { + Log.w(TAG, "Relative path for bucket id: " + bucketId + " is not found."); + relativePath = null; + } else { + relativePath = path.substring(extStorage.getAbsolutePath().length()); + } + } + return relativePath; + } + } diff --git a/src/com/android/gallery3d/gadget/WidgetConfigure.java b/src/com/android/gallery3d/gadget/WidgetConfigure.java index 3a1b52bdc..4818d261b 100644 --- a/src/com/android/gallery3d/gadget/WidgetConfigure.java +++ b/src/com/android/gallery3d/gadget/WidgetConfigure.java @@ -23,12 +23,18 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; +import android.util.Log; import android.widget.RemoteViews; import com.android.gallery3d.R; import com.android.gallery3d.app.AlbumPicker; import com.android.gallery3d.app.DialogPicker; +import com.android.gallery3d.app.GalleryApp; import com.android.gallery3d.common.ApiHelper; +import com.android.gallery3d.data.DataManager; +import com.android.gallery3d.data.LocalAlbum; +import com.android.gallery3d.data.MediaSet; +import com.android.gallery3d.data.Path; import com.android.gallery3d.filtershow.FilterShowActivity; import com.android.gallery3d.filtershow.CropExtras; @@ -158,8 +164,21 @@ public class WidgetConfigure extends Activity { String albumPath = data.getStringExtra(AlbumPicker.KEY_ALBUM_PATH); WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this); try { + String relativePath = null; + GalleryApp galleryApp = (GalleryApp) getApplicationContext(); + DataManager manager = galleryApp.getDataManager(); + Path path = Path.fromString(albumPath); + MediaSet mediaSet = (MediaSet) manager.getMediaObject(path); + if (mediaSet instanceof LocalAlbum) { + int bucketId = Integer.parseInt(path.getSuffix()); + // If the chosen album is a local album, find relative path + // Otherwise, leave the relative path field empty + relativePath = LocalAlbum.getRelativePath(bucketId); + Log.i(TAG, "Setting widget, album path: " + albumPath + + ", relative path: " + relativePath); + } helper.setWidget(mAppWidgetId, - WidgetDatabaseHelper.TYPE_ALBUM, albumPath); + WidgetDatabaseHelper.TYPE_ALBUM, albumPath, relativePath); updateWidgetAndFinish(helper.getEntry(mAppWidgetId)); } finally { helper.close(); @@ -174,7 +193,7 @@ public class WidgetConfigure extends Activity { } else if (widgetType == R.id.widget_type_shuffle) { WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this); try { - helper.setWidget(mAppWidgetId, WidgetDatabaseHelper.TYPE_SHUFFLE, null); + helper.setWidget(mAppWidgetId, WidgetDatabaseHelper.TYPE_SHUFFLE, null, null); updateWidgetAndFinish(helper.getEntry(mAppWidgetId)); } finally { helper.close(); diff --git a/src/com/android/gallery3d/gadget/WidgetDatabaseHelper.java b/src/com/android/gallery3d/gadget/WidgetDatabaseHelper.java index c411c365f..c0145843b 100644 --- a/src/com/android/gallery3d/gadget/WidgetDatabaseHelper.java +++ b/src/com/android/gallery3d/gadget/WidgetDatabaseHelper.java @@ -36,7 +36,9 @@ public class WidgetDatabaseHelper extends SQLiteOpenHelper { private static final String TAG = "PhotoDatabaseHelper"; private static final String DATABASE_NAME = "launcher.db"; - private static final int DATABASE_VERSION = 4; + // Increment the database version to 5. In version 5, we + // add a column in widgets table to record relative paths. + private static final int DATABASE_VERSION = 5; private static final String TABLE_WIDGETS = "widgets"; @@ -45,6 +47,7 @@ public class WidgetDatabaseHelper extends SQLiteOpenHelper { private static final String FIELD_PHOTO_BLOB = "photoBlob"; private static final String FIELD_WIDGET_TYPE = "widgetType"; private static final String FIELD_ALBUM_PATH = "albumPath"; + private static final String FIELD_RELATIVE_PATH = "relativePath"; public static final int TYPE_SINGLE_PHOTO = 0; public static final int TYPE_SHUFFLE = 1; @@ -52,12 +55,13 @@ public class WidgetDatabaseHelper extends SQLiteOpenHelper { private static final String[] PROJECTION = { FIELD_WIDGET_TYPE, FIELD_IMAGE_URI, FIELD_PHOTO_BLOB, FIELD_ALBUM_PATH, - FIELD_APPWIDGET_ID}; + FIELD_APPWIDGET_ID, FIELD_RELATIVE_PATH}; private static final int INDEX_WIDGET_TYPE = 0; private static final int INDEX_IMAGE_URI = 1; private static final int INDEX_PHOTO_BLOB = 2; private static final int INDEX_ALBUM_PATH = 3; private static final int INDEX_APPWIDGET_ID = 4; + private static final int INDEX_RELATIVE_PATH = 5; private static final String WHERE_APPWIDGET_ID = FIELD_APPWIDGET_ID + " = ?"; private static final String WHERE_WIDGET_TYPE = FIELD_WIDGET_TYPE + " = ?"; @@ -67,6 +71,7 @@ public class WidgetDatabaseHelper extends SQLiteOpenHelper { public String imageUri; public byte imageData[]; public String albumPath; + public String relativePath; private Entry() {} @@ -78,6 +83,7 @@ public class WidgetDatabaseHelper extends SQLiteOpenHelper { imageData = cursor.getBlob(INDEX_PHOTO_BLOB); } else if (type == TYPE_ALBUM) { albumPath = cursor.getString(INDEX_ALBUM_PATH); + relativePath = cursor.getString(INDEX_RELATIVE_PATH); } } @@ -97,7 +103,8 @@ public class WidgetDatabaseHelper extends SQLiteOpenHelper { + FIELD_WIDGET_TYPE + " INTEGER DEFAULT 0, " + FIELD_IMAGE_URI + " TEXT, " + FIELD_ALBUM_PATH + " TEXT, " - + FIELD_PHOTO_BLOB + " BLOB)"); + + FIELD_PHOTO_BLOB + " BLOB, " + + FIELD_RELATIVE_PATH + " TEXT)"); } private void saveData(SQLiteDatabase db, int oldVersion, ArrayList<Entry> data) { @@ -157,20 +164,27 @@ public class WidgetDatabaseHelper extends SQLiteOpenHelper { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - int version = oldVersion; - - if (version != DATABASE_VERSION) { + if (oldVersion < 4) { + // Table "photos" is renamed to "widget" in version 4 ArrayList<Entry> data = new ArrayList<Entry>(); saveData(db, oldVersion, data); Log.w(TAG, "destroying all old data."); - // Table "photos" is renamed to "widget" in version 4 db.execSQL("DROP TABLE IF EXISTS photos"); db.execSQL("DROP TABLE IF EXISTS " + TABLE_WIDGETS); onCreate(db); restoreData(db, data); } + // Add a column for relative path + if (oldVersion < DATABASE_VERSION) { + try { + db.execSQL("ALTER TABLE widgets ADD COLUMN relativePath TEXT"); + } catch (Throwable t) { + Log.e(TAG, "Failed to add the column for relative path."); + return; + } + } } /** @@ -201,12 +215,13 @@ public class WidgetDatabaseHelper extends SQLiteOpenHelper { } } - public boolean setWidget(int id, int type, String albumPath) { + public boolean setWidget(int id, int type, String albumPath, String relativePath) { try { ContentValues values = new ContentValues(); values.put(FIELD_APPWIDGET_ID, id); values.put(FIELD_WIDGET_TYPE, type); values.put(FIELD_ALBUM_PATH, Utils.ensureNotNull(albumPath)); + values.put(FIELD_RELATIVE_PATH, relativePath); getWritableDatabase().replaceOrThrow(TABLE_WIDGETS, null, values); return true; } catch (Throwable e) { @@ -223,7 +238,8 @@ public class WidgetDatabaseHelper extends SQLiteOpenHelper { WHERE_APPWIDGET_ID, new String[] {String.valueOf(appWidgetId)}, null, null, null); if (cursor == null || !cursor.moveToNext()) { - Log.e(TAG, "query fail: empty cursor: " + cursor); + Log.e(TAG, "query fail: empty cursor: " + cursor + " appWidgetId: " + + appWidgetId); return null; } return new Entry(appWidgetId, cursor); @@ -271,6 +287,7 @@ public class WidgetDatabaseHelper extends SQLiteOpenHelper { values.put(FIELD_ALBUM_PATH, entry.albumPath); values.put(FIELD_IMAGE_URI, entry.imageUri); values.put(FIELD_PHOTO_BLOB, entry.imageData); + values.put(FIELD_RELATIVE_PATH, entry.relativePath); getWritableDatabase().insert(TABLE_WIDGETS, null, values); } catch (Throwable e) { Log.e(TAG, "set widget fail", e); diff --git a/src/com/android/gallery3d/onetimeinitializer/GalleryWidgetMigrator.java b/src/com/android/gallery3d/onetimeinitializer/GalleryWidgetMigrator.java index 0187cba4b..ef26b1b97 100644 --- a/src/com/android/gallery3d/onetimeinitializer/GalleryWidgetMigrator.java +++ b/src/com/android/gallery3d/onetimeinitializer/GalleryWidgetMigrator.java @@ -18,11 +18,13 @@ package com.android.gallery3d.onetimeinitializer; import android.content.Context; import android.content.SharedPreferences; +import android.os.Build; import android.os.Environment; import android.preference.PreferenceManager; import android.util.Log; import com.android.gallery3d.app.GalleryApp; +import com.android.gallery3d.common.ApiHelper; import com.android.gallery3d.data.DataManager; import com.android.gallery3d.data.LocalAlbum; import com.android.gallery3d.data.MediaSet; @@ -36,34 +38,35 @@ import java.util.HashMap; import java.util.List; /** - * This one-timer migrates local-album gallery app widgets from pre-JB releases to JB (or later) - * due to bucket ID (i.e., directory hash) change in JB (as the external storage path is changed - * from /mnt/sdcard to /storage/sdcard0). + * This one-timer migrates local-album gallery app widgets from old paths from prior releases + * to updated paths in the current build version. This migration is needed because of + * bucket ID (i.e., directory hash) change in JB and JB MR1 (The external storage path has changed + * from /mnt/sdcard in pre-JB releases, to /storage/sdcard0 in JB, then again + * to /external/storage/sdcard/0 in JB MR1). */ public class GalleryWidgetMigrator { private static final String TAG = "GalleryWidgetMigrator"; - private static final String OLD_EXT_PATH = "/mnt/sdcard"; + private static final String PRE_JB_EXT_PATH = "/mnt/sdcard"; + private static final String JB_EXT_PATH = "/storage/sdcard0"; private static final String NEW_EXT_PATH = Environment.getExternalStorageDirectory().getAbsolutePath(); private static final int RELATIVE_PATH_START = NEW_EXT_PATH.length(); - private static final String KEY_MIGRATION_DONE = "gallery_widget_migration_done"; + private static final String KEY_EXT_PATH = "external_storage_path"; /** - * Migrates local-album gallery widgets from pre-JB releases to JB (or later) due to bucket ID - * (i.e., directory hash) change in JB. + * Migrates local-album gallery widgets from prior releases to current release + * due to bucket ID (i.e., directory hash) change. */ public static void migrateGalleryWidgets(Context context) { - // no migration needed if path of external storage is not changed - if (OLD_EXT_PATH.equals(NEW_EXT_PATH)) return; - - // only need to migrate once; the "done" bit is saved to SharedPreferences SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - boolean isDone = prefs.getBoolean(KEY_MIGRATION_DONE, false); + // Migration is only needed when external storage path has changed + String extPath = prefs.getString(KEY_EXT_PATH, null); + boolean isDone = NEW_EXT_PATH.equals(extPath); if (isDone) return; try { migrateGalleryWidgetsInternal(context); - prefs.edit().putBoolean(KEY_MIGRATION_DONE, true).commit(); + prefs.edit().putString(KEY_EXT_PATH, NEW_EXT_PATH).commit(); } catch (Throwable t) { // exception may be thrown if external storage is not available(?) Log.w(TAG, "migrateGalleryWidgets", t); @@ -77,39 +80,62 @@ public class GalleryWidgetMigrator { // only need to migrate local-album entries of type TYPE_ALBUM List<Entry> entries = dbHelper.getEntries(WidgetDatabaseHelper.TYPE_ALBUM); - if (entries != null) { - HashMap<Integer, Entry> localEntries = new HashMap<Integer, Entry>(entries.size()); - for (Entry entry : entries) { - Path path = Path.fromString(entry.albumPath); - MediaSet mediaSet = (MediaSet) manager.getMediaObject(path); - if (mediaSet instanceof LocalAlbum) { + if (entries == null) return; + + // Check each entry's relativePath. If exists, update bucket id using relative + // path combined with external storage path. Otherwise, iterate through old external + // storage paths to find the relative path that matches the old bucket id, and then update + // bucket id and relative path + HashMap<Integer, Entry> localEntries = new HashMap<Integer, Entry>(entries.size()); + for (Entry entry : entries) { + Path path = Path.fromString(entry.albumPath); + MediaSet mediaSet = (MediaSet) manager.getMediaObject(path); + if (mediaSet instanceof LocalAlbum) { + if (entry.relativePath != null && entry.relativePath.length() > 0) { + // update entry using relative path + external storage path + updateEntryUsingRelativePath(entry, dbHelper); + } else { int bucketId = Integer.parseInt(path.getSuffix()); localEntries.put(bucketId, entry); } } - if (!localEntries.isEmpty()) migrateLocalEntries(localEntries, dbHelper); } + if (!localEntries.isEmpty()) migrateLocalEntries(context, localEntries, dbHelper); } - private static void migrateLocalEntries( + private static void migrateLocalEntries(Context context, HashMap<Integer, Entry> entries, WidgetDatabaseHelper dbHelper) { - File root = Environment.getExternalStorageDirectory(); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + String oldExtPath = prefs.getString(KEY_EXT_PATH, null); + if (oldExtPath != null) { + migrateLocalEntries(entries, dbHelper, oldExtPath); + return; + } + // If old external storage path is unknown, it could be either Pre-JB or JB version + // we need to try both. + migrateLocalEntries(entries, dbHelper, PRE_JB_EXT_PATH); + if (!entries.isEmpty() && + Build.VERSION.SDK_INT > ApiHelper.VERSION_CODES.JELLY_BEAN) { + migrateLocalEntries(entries, dbHelper, JB_EXT_PATH); + } + } + private static void migrateLocalEntries(HashMap<Integer, Entry> entries, + WidgetDatabaseHelper dbHelper, String oldExtPath) { + File root = Environment.getExternalStorageDirectory(); // check the DCIM directory first; this should take care of 99% use cases - updatePath(new File(root, "DCIM"), entries, dbHelper); - + updatePath(new File(root, "DCIM"), entries, dbHelper, oldExtPath); // check other directories if DCIM doesn't cut it - if (!entries.isEmpty()) updatePath(root, entries, dbHelper); + if (!entries.isEmpty()) updatePath(root, entries, dbHelper, oldExtPath); } - - private static void updatePath( - File root, HashMap<Integer, Entry> entries, WidgetDatabaseHelper dbHelper) { + private static void updatePath(File root, HashMap<Integer, Entry> entries, + WidgetDatabaseHelper dbHelper, String oldExtStorage) { File[] files = root.listFiles(); if (files != null) { for (File file : files) { if (file.isDirectory() && !entries.isEmpty()) { String path = file.getAbsolutePath(); - String oldPath = OLD_EXT_PATH + path.substring(RELATIVE_PATH_START); + String oldPath = oldExtStorage + path.substring(RELATIVE_PATH_START); int oldBucketId = GalleryUtils.getBucketId(oldPath); Entry entry = entries.remove(oldBucketId); if (entry != null) { @@ -120,11 +146,24 @@ public class GalleryWidgetMigrator { .toString(); Log.d(TAG, "migrate from " + entry.albumPath + " to " + newAlbumPath); entry.albumPath = newAlbumPath; + // update entry's relative path + entry.relativePath = path.substring(RELATIVE_PATH_START); dbHelper.updateEntry(entry); } - updatePath(file, entries, dbHelper); // recursion + updatePath(file, entries, dbHelper, oldExtStorage); // recursion } } } } + + private static void updateEntryUsingRelativePath(Entry entry, WidgetDatabaseHelper dbHelper) { + String newPath = NEW_EXT_PATH + entry.relativePath; + int newBucketId = GalleryUtils.getBucketId(newPath); + String newAlbumPath = Path.fromString(entry.albumPath) + .getParent() + .getChild(newBucketId) + .toString(); + entry.albumPath = newAlbumPath; + dbHelper.updateEntry(entry); + } } diff --git a/src/com/android/gallery3d/util/BucketNames.java b/src/com/android/gallery3d/util/BucketNames.java index df7684a04..990dc8224 100644 --- a/src/com/android/gallery3d/util/BucketNames.java +++ b/src/com/android/gallery3d/util/BucketNames.java @@ -21,7 +21,9 @@ package com.android.gallery3d.util; */ public class BucketNames { + public static final String CAMERA = "DCIM/Camera"; public static final String IMPORTED = "Imported"; public static final String DOWNLOAD = "download"; public static final String EDITED_ONLINE_PHOTOS = "EditedOnlinePhotos"; + public static final String SCREENSHOTS = "Pictures/Screenshots"; } diff --git a/src/com/android/gallery3d/util/GalleryUtils.java b/src/com/android/gallery3d/util/GalleryUtils.java index 1e5d8d5fe..9245e2c5f 100644 --- a/src/com/android/gallery3d/util/GalleryUtils.java +++ b/src/com/android/gallery3d/util/GalleryUtils.java @@ -46,6 +46,7 @@ import com.android.gallery3d.ui.TiledScreenNail; import com.android.gallery3d.util.ThreadPool.CancelListener; import com.android.gallery3d.util.ThreadPool.JobContext; +import java.io.File; import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -309,6 +310,26 @@ public class GalleryUtils { return path.toLowerCase().hashCode(); } + // Return the local path that matches the given bucketId. If no match is + // found, return null + public static String searchDirForPath(File dir, int bucketId) { + File[] files = dir.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + String path = file.getAbsolutePath(); + if (GalleryUtils.getBucketId(path) == bucketId) { + return path; + } else { + path = searchDirForPath(file, bucketId); + if (path != null) return path; + } + } + } + } + return null; + } + // Returns a (localized) string for the given duration (in seconds). public static String formatDuration(final Context context, int duration) { int h = duration / 3600; diff --git a/src/com/android/gallery3d/util/MediaSetUtils.java b/src/com/android/gallery3d/util/MediaSetUtils.java index 83b6b320b..043800561 100644 --- a/src/com/android/gallery3d/util/MediaSetUtils.java +++ b/src/com/android/gallery3d/util/MediaSetUtils.java @@ -29,7 +29,8 @@ public class MediaSetUtils { public static final Comparator<MediaSet> NAME_COMPARATOR = new NameComparator(); public static final int CAMERA_BUCKET_ID = GalleryUtils.getBucketId( - Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera"); + Environment.getExternalStorageDirectory().toString() + "/" + + BucketNames.CAMERA); public static final int DOWNLOAD_BUCKET_ID = GalleryUtils.getBucketId( Environment.getExternalStorageDirectory().toString() + "/" + BucketNames.DOWNLOAD); @@ -41,7 +42,7 @@ public class MediaSetUtils { + BucketNames.IMPORTED); public static final int SNAPSHOT_BUCKET_ID = GalleryUtils.getBucketId( Environment.getExternalStorageDirectory().toString() + - "/Pictures/Screenshots"); + "/" + BucketNames.SCREENSHOTS); private static final Path[] CAMERA_PATHS = { Path.fromString("/local/all/" + CAMERA_BUCKET_ID), |