aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrsudev <rasch@munin-soft.de>2012-05-12 16:19:00 +0200
committerrsudev <rasch@munin-soft.de>2012-05-12 16:19:00 +0200
commitb4dc24ad4b9d8a747d9db3cacc3dffd30b6dc5bf (patch)
tree4acaf8759079510ff6db7c6b3ae219a63aac6c13
parent55947617aa1a12b2126237741e250822694342f2 (diff)
downloadcgeo-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.xml38
-rw-r--r--main/res/values/strings.xml8
-rw-r--r--main/src/cgeo/geocaching/Settings.java15
-rw-r--r--main/src/cgeo/geocaching/SettingsActivity.java17
-rw-r--r--main/src/cgeo/geocaching/cgData.java67
-rw-r--r--main/src/cgeo/geocaching/cgeoapplication.java31
-rw-r--r--main/src/cgeo/geocaching/files/LocalStorage.java22
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");
}
/**