diff options
| author | rsudev <rasch@munin-soft.de> | 2012-05-12 16:19:00 +0200 |
|---|---|---|
| committer | rsudev <rasch@munin-soft.de> | 2012-05-12 16:19:00 +0200 |
| commit | b4dc24ad4b9d8a747d9db3cacc3dffd30b6dc5bf (patch) | |
| tree | 4acaf8759079510ff6db7c6b3ae219a63aac6c13 | |
| parent | 55947617aa1a12b2126237741e250822694342f2 (diff) | |
| download | cgeo-b4dc24ad4b9d8a747d9db3cacc3dffd30b6dc5bf.zip cgeo-b4dc24ad4b9d8a747d9db3cacc3dffd30b6dc5bf.tar.gz cgeo-b4dc24ad4b9d8a747d9db3cacc3dffd30b6dc5bf.tar.bz2 | |
Allow to move the c:geo database to the sdcard.
Partially implements issue #11
| -rw-r--r-- | main/res/layout/init.xml | 38 | ||||
| -rw-r--r-- | main/res/values/strings.xml | 8 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/Settings.java | 15 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/SettingsActivity.java | 17 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/cgData.java | 67 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/cgeoapplication.java | 31 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/files/LocalStorage.java | 22 |
7 files changed, 190 insertions, 8 deletions
diff --git a/main/res/layout/init.xml b/main/res/layout/init.xml index dd2ed0d..8e22668 100644 --- a/main/res/layout/init.xml +++ b/main/res/layout/init.xml @@ -872,6 +872,44 @@ <!-- ** --> <RelativeLayout style="@style/separator_horizontal_layout" > <View style="@style/separator_horizontal" /> + <TextView style="@style/separator_horizontal_headline" + android:text="@string/init_dbonsdcard_title" /> + </RelativeLayout> + <TextView android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="10dip" + android:layout_marginRight="10dip" + android:layout_marginBottom="5dip" + android:layout_gravity="left" + android:padding="3dip" + android:textSize="14dip" + android:textColor="?text_color" + android:textColorLink="?text_color_link" + android:linksClickable="true" + android:text="@string/init_dbonsdcard_note" /> + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" > + <CheckBox android:id="@+id/dbonsdcard" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="left" + android:padding="1px" + android:gravity="center" /> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:gravity="left" + android:paddingRight="3dip" + android:textSize="14dip" + android:textColor="?text_color" + android:text="@string/init_dbonsdcard" /> + </LinearLayout> +<!-- ** --> + <RelativeLayout style="@style/separator_horizontal_layout" > + <View style="@style/separator_horizontal" /> <TextView style="@style/separator_horizontal_headline" android:text="@string/init_debug_title" /> diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index d454513..9449a24 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -429,6 +429,14 @@ <string name="init_debug_title">Debug information</string> <string name="init_debug_note">c:geo can generate a lot of debugging information. While this information is generally not useful for c:geo users, developers may need to generate this information in order to analyze a bug. In this case, they will ask you to check the box below and send them the log file.</string> <string name="init_debug">Generate debug information</string> + <string name="init_dbonsdcard_title">Database location</string> + <string name="init_dbonsdcard_note">You may store the database of c:geo on the external storage medium. If you do so you will save internal memory, but you may loose a bit of performance and c:geo will not work if your sdcard is not available.</string> + <string name="init_dbonsdcard">Database on external storage</string> + <string name="init_dbmove">Moving Database</string> + <string name="init_dbmove_dbmove">Moving Database</string> + <string name="init_dbmove_running">Moving Database</string> + <string name="init_dbmove_success">Successfully moved the database.</string> + <string name="init_dbmove_failed">Failed to move database</string> <!-- map sources --> <string-array name="map_sources"> diff --git a/main/src/cgeo/geocaching/Settings.java b/main/src/cgeo/geocaching/Settings.java index 8f38db9..82ab132 100644 --- a/main/src/cgeo/geocaching/Settings.java +++ b/main/src/cgeo/geocaching/Settings.java @@ -87,6 +87,7 @@ public final class Settings { private static final String KEY_HIDE_LIVE_MAP_HINT = "hidelivemaphint"; private static final String KEY_LIVE_MAP_HINT_SHOW_COUNT = "livemaphintshowcount"; private static final String KEY_SETTINGS_VERSION = "settingsversion"; + private static final String KEY_DB_ON_SDCARD = "dbonsdcard"; private final static int unitsMetric = 1; @@ -1128,6 +1129,20 @@ public final class Settings { }); } + public static boolean isDbOnSDCard() { + return sharedPrefs.getBoolean(KEY_DB_ON_SDCARD, false); + } + + public static void setDbOnSDCard(final boolean dbOnSDCard) { + editSharedSettings(new PrefRunnable() { + + @Override + public void edit(Editor edit) { + edit.putBoolean(KEY_DB_ON_SDCARD, dbOnSDCard); + } + }); + } + public static String getPreferencesName() { // there is currently no Android API to get the file name of the shared preferences return cgeoapplication.getInstance().getPackageName() + "_preferences"; diff --git a/main/src/cgeo/geocaching/SettingsActivity.java b/main/src/cgeo/geocaching/SettingsActivity.java index 5253e81..bd5e0e1 100644 --- a/main/src/cgeo/geocaching/SettingsActivity.java +++ b/main/src/cgeo/geocaching/SettingsActivity.java @@ -676,6 +676,18 @@ public class SettingsActivity extends AbstractActivity { refreshBackupLabel(); + // Database location + refreshDbOnSDCardSetting(); + + final CheckBox dbOnSDCardButton = (CheckBox) findViewById(R.id.dbonsdcard); + dbOnSDCardButton.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + app.moveDatabase(SettingsActivity.this); + } + }); + // Debug settings final CheckBox debugButton = (CheckBox) findViewById(R.id.debug); debugButton.setChecked(Settings.isDebug()); @@ -736,6 +748,11 @@ public class SettingsActivity extends AbstractActivity { } } + private void refreshDbOnSDCardSetting() { + final CheckBox dbOnSDCardButton = (CheckBox) findViewById(R.id.dbonsdcard); + dbOnSDCardButton.setChecked(Settings.isDbOnSDCard()); + } + /** * @param view * unused here but needed since this method is referenced from XML layout diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java index 8d10fb7..8a460c8 100644 --- a/main/src/cgeo/geocaching/cgData.java +++ b/main/src/cgeo/geocaching/cgData.java @@ -19,10 +19,12 @@ import org.apache.commons.lang3.StringUtils; import android.content.ContentValues; import android.content.Context; +import android.content.ContextWrapper; import android.content.res.Resources; import android.database.Cursor; import android.database.DatabaseUtils.InsertHelper; import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteDoneException; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteStatement; @@ -263,7 +265,7 @@ public class cgData { if (databaseRW == null || !databaseRW.isOpen()) { try { if (dbHelper == null) { - dbHelper = new DbHelper(context); + dbHelper = new DbHelper(new DBContext(context)); } databaseRW = dbHelper.getWritableDatabase(); @@ -284,7 +286,7 @@ public class cgData { if (databaseRO == null || !databaseRO.isOpen()) { try { if (dbHelper == null) { - dbHelper = new DbHelper(context); + dbHelper = new DbHelper(new DBContext(context)); } databaseRO = dbHelper.getReadableDatabase(); @@ -314,7 +316,7 @@ public class cgData { cacheCache.removeAllFromCache(); initialized = false; - closePreparedStatements(); + clearPreparedStatements(); if (databaseRO != null) { path = databaseRO.getPath(); @@ -350,10 +352,11 @@ public class cgData { } } - private void closePreparedStatements() { + private void clearPreparedStatements() { for (SQLiteStatement statement : statements.values()) { statement.close(); } + statements.clear(); } private static File backupFile() { @@ -380,6 +383,39 @@ public class cgData { return target.getPath(); } + public boolean moveDatabase() { + if (!LocalStorage.isExternalStorageAvailable()) { + Log.w("Database was not moved: external memory not available"); + return false; + } + + final File target = Settings.isDbOnSDCard() ? internalDb() : externalDb(); + closeDb(); + final File source = new File(path); + final boolean moveDone = LocalStorage.copy(source, target); + if (moveDone) { + source.delete(); + Settings.setDbOnSDCard(!Settings.isDbOnSDCard()); + } + init(); + + if (!moveDone) { + Log.e("Database could not be moved to " + target); + return false; + } + + Log.i("Database was moved to " + target); + return true; + } + + public static File internalDb() { + return new File(LocalStorage.getInternalDbDirectory(), dbName); + } + + public static File externalDb() { + return new File(LocalStorage.getExternalDbDirectory(), dbName); + } + public static File isRestoreFile() { final File fileSourceFile = backupFile(); return fileSourceFile.exists() ? fileSourceFile : null; @@ -405,10 +441,31 @@ public class cgData { return restoreDone; } + private class DBContext extends ContextWrapper { + + public DBContext(Context base) { + super(base); + } + + /** + * We override the default open/create as it doesn't work on OS 1.6 and + * causes issues on other devices too. + */ + @Override + public SQLiteDatabase openOrCreateDatabase(String name, int mode, + CursorFactory factory) { + File f = new File(name); + f.getParentFile().mkdirs(); + SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory); + return db; + } + + } + private static class DbHelper extends SQLiteOpenHelper { DbHelper(Context context) { - super(context, dbName, null, dbVersion); + super(context, Settings.isDbOnSDCard() ? externalDb().getPath() : internalDb().getPath(), null, dbVersion); } @Override diff --git a/main/src/cgeo/geocaching/cgeoapplication.java b/main/src/cgeo/geocaching/cgeoapplication.java index 63e34a6..abbd85c 100644 --- a/main/src/cgeo/geocaching/cgeoapplication.java +++ b/main/src/cgeo/geocaching/cgeoapplication.java @@ -76,6 +76,37 @@ public class cgeoapplication extends Application { return storage.backupDatabase(); } + /** + * Move the database to/from external storage in a new thread, + * showing a progress window + * + * @param fromActivity + */ + public void moveDatabase(final Activity fromActivity) { + final Resources res = this.getResources(); + final ProgressDialog dialog = ProgressDialog.show(fromActivity, res.getString(R.string.init_dbmove_dbmove), res.getString(R.string.init_dbmove_running), true, false); + final AtomicBoolean atomic = new AtomicBoolean(false); + Thread moveThread = new Thread() { + final Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + dialog.dismiss(); + boolean success = atomic.get(); + String message = success ? res.getString(R.string.init_dbmove_success) : res.getString(R.string.init_dbmove_failed); + ActivityMixin.helpDialog(fromActivity, res.getString(R.string.init_dbmove_dbmove), message); + } + }; + + @Override + public void run() { + atomic.set(storage.moveDatabase()); + handler.sendMessage(handler.obtainMessage()); + } + }; + moveThread.start(); + } + + public static File isRestoreFile() { return cgData.isRestoreFile(); } diff --git a/main/src/cgeo/geocaching/files/LocalStorage.java b/main/src/cgeo/geocaching/files/LocalStorage.java index eea761b..14f60da 100644 --- a/main/src/cgeo/geocaching/files/LocalStorage.java +++ b/main/src/cgeo/geocaching/files/LocalStorage.java @@ -25,7 +25,7 @@ import java.io.OutputStream; */ public class LocalStorage { - /** Name of the local private directory to use to hold cached information */ + /** Name of the local private directory used to hold cached information */ public final static String cache = ".cgeo"; /** @@ -48,8 +48,24 @@ public class LocalStorage { private static File getStorageSpecific(boolean secondary) { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ^ secondary ? - new File(Environment.getExternalStorageDirectory(), LocalStorage.cache) : - new File(new File(new File(Environment.getDataDirectory(), "data"), "cgeo.geocaching"), LocalStorage.cache); + getExternalStorageBase() : + new File(getInternalStorageBase(), LocalStorage.cache); + } + + public static File getExternalDbDirectory() { + return getExternalStorageBase(); + } + + public static File getInternalDbDirectory() { + return new File(getInternalStorageBase(), "databases"); + } + + private static File getExternalStorageBase() { + return new File(Environment.getExternalStorageDirectory(), LocalStorage.cache); + } + + private static File getInternalStorageBase() { + return new File(new File(Environment.getDataDirectory(), "data"), "cgeo.geocaching"); } /** |
