Skip to content

Commit

Permalink
* #190: Backup/Restore lat/long/tags/rating in local DB
Browse files Browse the repository at this point in the history
  • Loading branch information
k3b committed Apr 17, 2021
1 parent e9f477a commit 6d7a3a4
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ public boolean onOptionsItemSelected(MenuItem item) {
if (0 != onDbUpdateCommand(item))
notifyPhotoChanged();
return true;

case R.id.cmd_db_backup:
onDbBackup();
return true;

case R.id.cmd_more:
new Handler().postDelayed(new Runnable() {
public void run() {
Expand All @@ -227,6 +232,10 @@ public void run() {

}

private void onDbBackup() {
AndroFotoFinderApp.getMediaContent2DbUpdateService().createBackup();
}

private int onDbUpdateCommand(MenuItem item) {
Activity activity = this;
int count = AndroFotoFinderApp.getMediaContent2DbUpdateService().update(this, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,19 @@
package de.k3b.android.androFotoFinder.queries;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

import java.io.File;

import de.k3b.android.androFotoFinder.Global;
import de.k3b.android.androFotoFinder.transactionlog.TransactionLogSql;
import de.k3b.android.util.DatabaseContext;

import static de.k3b.android.androFotoFinder.queries.FotoSql.LOG_TAG;

/**
* Created by k3b on 22.02.2017.
*/
Expand Down Expand Up @@ -68,8 +72,53 @@ private static DatabaseHelper getInstance(Context context) {
}


public static void version2Upgrade_RecreateMediDbCopy(final SQLiteDatabase db) {
for (String sql : MediaDBRepository.Impl.DDL) {
public static void version2Upgrade_ReCreateMediaDbTable(final SQLiteDatabase db) {
execSql(db, "(Re)CreateMediaDbTable:", MediaDBRepository.Impl.DDL);
}

public static void createBackup(SQLiteDatabase db) {
if (tableExists(db, MediaDBRepository.Impl.DATABASE_TABLE_NAME)) {
// see https://www.techonthenet.com/sqlite/tables/create_table_as.php

if (!tableExists(db, MediaDBRepository.Impl.DATABASE_TABLE_NAME_BACKUP)) {
execSql(db, "create Backup:", MediaDBRepository.Impl.CREATE_BACKUP);
} else {
execSql(db, "update Backup:", MediaDBRepository.Impl.UPDATE_BACKUP);
}
}
}

public static void restoreFromBackup(SQLiteDatabase db) {
if (tableExists(db, MediaDBRepository.Impl.DATABASE_TABLE_NAME_BACKUP)) {
// see https://stackoverflow.com/questions/19270259/update-with-join-in-sqlite
execSql(db, "restoreFromBackup:", MediaDBRepository.Impl.RESTORE_FROM_BACKUP);
}
}

// from https://stackoverflow.com/questions/1601151/how-do-i-check-in-sqlite-whether-a-table-exists
private static boolean tableExists(SQLiteDatabase db, String tableName) {
if (tableName == null || db == null || !db.isOpen()) {
return false;
}
Cursor cursor = db.rawQuery(
"SELECT COUNT(*) FROM sqlite_master WHERE type = ? AND name = ?",
new String[]{"table", tableName}
);
if (!cursor.moveToFirst()) {
cursor.close();
return false;
}
int count = cursor.getInt(0);
cursor.close();
return count > 0;
}

private static void execSql(SQLiteDatabase db, String dbgContext, String... ddlStatements) {

for (String sql : ddlStatements) {
if (Global.debugEnabledSql) {
Log.i(LOG_TAG, "DatabaseHelper-" + dbgContext + sql);
}
db.execSQL(sql);
}
}
Expand All @@ -79,9 +128,9 @@ public static void version2Upgrade_RecreateMediDbCopy(final SQLiteDatabase db) {
*/
@Override
public void onCreate(final SQLiteDatabase db) {
db.execSQL(TransactionLogSql.CREATE_TABLE);
execSql(db, "First Create DB: ", TransactionLogSql.CREATE_TABLE);

this.version2Upgrade_RecreateMediDbCopy(db);
version2Upgrade_ReCreateMediaDbTable(db);
}

@Override
Expand All @@ -90,7 +139,7 @@ public void onUpgrade(final SQLiteDatabase db, final int oldVersion,
Log.w(this.getClass().toString(), "Upgrading database from version "
+ oldVersion + " to " + newVersion + ". (Old data is kept.)");
if (oldVersion < DatabaseHelper.DATABASE_VERSION_2_MEDIA_DB_COPY) {
this.version2Upgrade_RecreateMediDbCopy(db);
version2Upgrade_ReCreateMediaDbTable(db);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,33 @@ public MediaContent2DBUpdateService(Context context, SQLiteDatabase writableData
}

public void clearMediaCopy() {
DatabaseHelper.version2Upgrade_RecreateMediDbCopy(writableDatabase);
DatabaseHelper.version2Upgrade_ReCreateMediaDbTable(writableDatabase);
}

public int rebuild(Context context, IProgessListener progessListener) {
long start = new Date().getTime();
if (progessListener != null)
progessListener.onProgress(0, 0, "Create Backup of tags, lat, lon, rating");
createBackup();
if (progessListener != null) progessListener.onProgress(0, 0, "Recreate Database");
clearMediaCopy();
if (progessListener != null)
progessListener.onProgress(0, 0, "Copy from Android Media Database");
int changeCount = MediaDBRepository.Impl.updateMediaCopy(context, writableDatabase, null, null, progessListener);
if (progessListener != null)
progessListener.onProgress(0, 0, "Restore tags, lat, lon, rating from Backup");
DatabaseHelper.restoreFromBackup(writableDatabase);
long timeInSecs = (new Date().getTime() - start) / 1000;
final String text = "load db " + timeInSecs + " secs";
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
if (progessListener != null) progessListener.onProgress(0, 0, text);
return changeCount;
}

public void createBackup() {
DatabaseHelper.createBackup(writableDatabase);
}

public int update(Context context, IProgessListener progessListener) {
long start = new Date().getTime();
int changeCount = MediaDBRepository.Impl.updateMediaCopy(context, writableDatabase, progessListener);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -412,13 +412,14 @@ public static ContentValues getContentValues(String fullFilePathFilter, ContentV

public static class Impl {
public static final String DATABASE_TABLE_NAME = "files";
public static final String DATABASE_TABLE_NAME_BACKUP = "backup";
/**
* SQL to create copy of contentprovider MediaStore.Images.
* copied from android-4.4 android database. Removed columns not used
*/
protected static final String[] DDL = new String[]{
"DROP TABLE IF EXISTS \"files\"",
"CREATE TABLE \"files\" (\n" +
"DROP TABLE IF EXISTS \"" + DATABASE_TABLE_NAME + "\"",
"CREATE TABLE \"" + DATABASE_TABLE_NAME + "\" (\n" +
"\t_id INTEGER PRIMARY KEY AUTOINCREMENT,\n" +
"\t_size INTEGER,\n" +
"\tdate_added INTEGER,\n" +
Expand All @@ -441,11 +442,37 @@ public static class Impl {
"\tlatitude DOUBLE,\n" +
"\tlongitude DOUBLE\n" +
"\t )",
"CREATE INDEX media_type_index ON files(media_type)",
"CREATE INDEX path_index ON files(_data)",
"CREATE INDEX sort_index ON files(datetaken ASC, _id ASC)",
"CREATE INDEX title_idx ON files(title)",
"CREATE INDEX media_type_index ON " + DATABASE_TABLE_NAME + "(media_type)",
"CREATE INDEX path_index ON " + DATABASE_TABLE_NAME + "(_data)",
"CREATE INDEX sort_index ON " + DATABASE_TABLE_NAME + "(datetaken ASC, _id ASC)",
"CREATE INDEX title_idx ON " + DATABASE_TABLE_NAME + "(title)",
};
protected static final String[] RESTORE_FROM_BACKUP = new String[]{
"UPDATE " + DATABASE_TABLE_NAME + "\n" +
"SET latitude = (SELECT latitude FROM " + DATABASE_TABLE_NAME_BACKUP + " WHERE _data = " + DATABASE_TABLE_NAME + "._data)\n" +
", latitude = (SELECT latitude FROM " + DATABASE_TABLE_NAME_BACKUP + " WHERE _data = " + DATABASE_TABLE_NAME + "._data)\n" +
", longitude = (SELECT longitude FROM " + DATABASE_TABLE_NAME_BACKUP + " WHERE _data = " + DATABASE_TABLE_NAME + "._data)\n" +
", tags = (SELECT tags FROM " + DATABASE_TABLE_NAME_BACKUP + " WHERE _data = " + DATABASE_TABLE_NAME + "._data)\n" +
", duration = (SELECT duration FROM " + DATABASE_TABLE_NAME_BACKUP + " WHERE _data = " + DATABASE_TABLE_NAME + "._data)\n" +
", title = (SELECT title FROM " + DATABASE_TABLE_NAME_BACKUP + " WHERE _data = " + DATABASE_TABLE_NAME + "._data)\n" +
", description = (SELECT description FROM " + DATABASE_TABLE_NAME_BACKUP + " WHERE _data = " + DATABASE_TABLE_NAME + "._data)\n" +
", bookmark = (SELECT bookmark FROM " + DATABASE_TABLE_NAME_BACKUP + " WHERE _data = " + DATABASE_TABLE_NAME + "._data)",
};
private static final String HAS_DATA = "latitude is not null or tags is not null or bookmark is not null";
private static final String MY_COLUMNS = " _id, _data, latitude, longitude, tags, duration, bookmark, title, description ";
private static final String SELECT_FROM_FILES = " SELECT" + MY_COLUMNS + " from " + DATABASE_TABLE_NAME + "" + " where " + HAS_DATA;
protected static final String[] CREATE_BACKUP = new String[]{
"DROP TABLE IF EXISTS \"" + DATABASE_TABLE_NAME_BACKUP + "\"",
"CREATE TABLE \"" + DATABASE_TABLE_NAME_BACKUP + "\" AS" + SELECT_FROM_FILES,
"CREATE INDEX bu_path_index ON " + DATABASE_TABLE_NAME_BACKUP + "(_data)",
};
protected static final String[] UPDATE_BACKUP = new String[]{
"DELETE FROM " + DATABASE_TABLE_NAME_BACKUP + " where exists " +
"(select _data from " + DATABASE_TABLE_NAME +
" WHERE _data = " + DATABASE_TABLE_NAME_BACKUP + "._data" + " AND (" + HAS_DATA + "))",
"INSERT INTO " + DATABASE_TABLE_NAME_BACKUP + "(" + MY_COLUMNS + ")" + SELECT_FROM_FILES,
};

private static final int COL_INT_MIN = 0;
// same colum order as in DDL
private static final String[] USED_MEDIA_COLUMNS = new String[]{
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/menu/menu_gallery_ao10.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@
android:title="@string/update_db_menu_title"
android:visible="true" />

<item
android:id="@+id/cmd_db_backup"
android:orderInCategory="9900"
android:showAsAction="never"
android:title="@string/backup_db_menu_title"
android:visible="true" />

</menu>
</item>
</menu>
1 change: 1 addition & 0 deletions app/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ der SD-Karte oder des USB-Sticks aus.</p>
<string name="load_db_menu_title">Mediendatenbank (neu) laden</string>

<string name="update_db_menu_title">Mediendatenbank aktualisieren</string>
<string name="backup_db_menu_title">Backup lat,long,tags,... in Mediendatenbank</string>

<!-- #173: incremental media scanner -->
<string name="scanner_menu_title">Media-Scanner</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ of SD-Card or USB-Stick.</p>
<string name="database_menu_title">Mediadatabase ...</string>
<string name="load_db_menu_title">(Re)Load Mediadatabase</string>
<string name="update_db_menu_title">Update Mediadatabase</string>
<string name="backup_db_menu_title">Backup lat,long,tags,... in Mediadatabase</string>

<!-- #173: incremental media scanner -->
<string name="scanner_menu_title">Mediafile scanner</string>
Expand Down
1 change: 1 addition & 0 deletions fastlane/metadata/android/en-US/changelogs/49.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ Changes from 0.8.4 to ???
* #155: Android-10 support (experimental)
* #173: incremental media scanner
* #173: Ao10-performance-Optimized-Mediacanner
* #190: Backup/Restore lat/long/tags/rating

0 comments on commit 6d7a3a4

Please sign in to comment.