Skip to content

Commit

Permalink
#169: Update exif-file-info also updates mediadb without changing med…
Browse files Browse the repository at this point in the history
…iadb-id
  • Loading branch information
k3b committed Dec 10, 2020
1 parent 1f51e1c commit 461b889
Show file tree
Hide file tree
Showing 11 changed files with 266 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,29 @@
import android.util.Log;

import java.io.IOException;
import java.util.Date;

import de.k3b.android.androFotoFinder.Global;
import de.k3b.android.androFotoFinder.queries.FotoSql;
import de.k3b.android.androFotoFinder.tagDB.TagSql;
import de.k3b.io.FileUtils;
import de.k3b.io.VISIBILITY;
import de.k3b.io.collections.SelectedFiles;
import de.k3b.io.filefacade.IFile;
import de.k3b.media.ExifInterfaceEx;
import de.k3b.media.PhotoPropertiesUtil;

/**
* Android specific Version of {@link ExifInterfaceEx} that updates the
* Database, when saving exif changes.
*/
public class AndroidExifInterfaceEx extends ExifInterfaceEx {
public static boolean DBG_ENABLED = true;

private boolean overwriteOriginal;
private String inPath;
private String outPath;
private Boolean hasXmp;

public static void init() {
setFactory(new Factory() {
Expand All @@ -29,14 +37,21 @@ public ExifInterfaceEx create() {
});
}

@Override
public void saveAttributes(IFile inFile, IFile outFile,
boolean deleteInFileOnFinish, Boolean hasXmp) throws IOException {
super.saveAttributes(inFile, outFile, deleteInFileOnFinish, hasXmp);
this.hasXmp = hasXmp;
}

@Override
protected IFile renameSouraceFileBeforeReplaceOrThrow(IFile oldSourcefile, String newName) throws IOException {
debugIdPaths("renameSouraceFileBeforeReplaceOrThrow begin", oldSourcefile.getAbsolutePath(), newName);
this.overwriteOriginal = true;
this.inPath = oldSourcefile.getAbsolutePath();
this.outPath = this.inPath + TMP_FILE_SUFFIX;

if (!renameInDatabase(":renameSouraceFileBeforeReplaceOrThrow", this.inPath, this.outPath)) {
if (!renameInDatabase(":renameSouraceFileBeforeReplaceOrThrow", this.inPath, this.outPath, false)) {
this.outPath = null; // failed
}

Expand All @@ -48,16 +63,33 @@ protected IFile renameSouraceFileBeforeReplaceOrThrow(IFile oldSourcefile, Strin
@Override
protected void beforeCloseSaveOutputStream() {
if (this.outPath != null) {
renameInDatabase(":beforeCloseSaveOutputStream", this.outPath, this.inPath);
renameInDatabase(":beforeCloseSaveOutputStream", this.outPath, this.inPath, true);
this.outPath = null;
}
super.beforeCloseSaveOutputStream();
}

private boolean renameInDatabase(String dbgContext, String fromPath, String toPath) {
debugIdPaths(dbgContext + " renameInDatabase begin", fromPath, toPath);
// TODO additional database parameters (see scanner)
// DateLastModified, xmpDate, ....
private boolean renameInDatabase(String dbgContext, String fromPath, String toPath, boolean thransferExif) {
ContentValues values = new ContentValues();
if (thransferExif) {
PhotoPropertiesMediaDBContentValues mediaValueAdapter = new PhotoPropertiesMediaDBContentValues().set(values, null);

PhotoPropertiesUtil.copyNonEmpty(mediaValueAdapter, this);

Date lastModified = new Date();
TagSql.setFileModifyDate(values, lastModified);
if (this.hasXmp != null) {
if (this.hasXmp) {
TagSql.setXmpFileModifyDate(values, lastModified);
} else {
TagSql.setXmpFileModifyDate(values, TagSql.EXT_LAST_EXT_SCAN_NO_XMP);
}
}
}
values.put(FotoSql.SQL_COL_PATH, toPath);
debugIdPaths(dbgContext + " renameInDatabase begin", fromPath, toPath);
final int execResultCount = FotoSql.getMediaDBApi().
execUpdate(this.getClass().getSimpleName() + dbgContext, fromPath, values, null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ private void updateDB(String dbgContext, String _path, long xmlLastFileModifyDat
TagSql.setXmpFileModifyDate(dbValues, xmlLastFileModifyDate);
}

TagSql.setFileModifyDate(dbValues, new Date().getTime() / 1000);
TagSql.setFileModifyDate(dbValues, new Date());

mUpdateCount += TagSql.execUpdate(dbgContext, path, xmlLastFileModifyDate, dbValues, VISIBILITY.PRIVATE_PUBLIC);
mItemCount++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void clearMediaCopy() {
public void rebuild(Context context, IProgessListener progessListener) {
long start = new Date().getTime();
clearMediaCopy();
MediaDBRepository.Impl.updateMedaiCopy(context, writableDatabase, null, progessListener);
MediaDBRepository.Impl.updateMediaCopy(context, writableDatabase, null, progessListener);
start = (new Date().getTime() - start) / 1000;
final String text = "load db " + start + " secs";
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public class MediaDBRepository implements IMediaRepositoryApi {
// #155
public static final boolean debugEnabledSqlRefresh = true;

private static final String MODUL_NAME = MediaContentproviderRepositoryImpl.class.getName();
private static final String MODUL_NAME = MediaDBRepository.class.getSimpleName();
private static String currentUpdateReason = null;
private static long currentUpdateId = 1;
private static int transactionNumber = 0;
Expand Down Expand Up @@ -360,6 +360,41 @@ public void endTransaction() {
db.endTransaction();
}

/**
* generic method to get values from current MediaDBApi-Implementation
*
* @param fullFilePathFilter
* @param destination
* @param dbgContext
* @return
*/
public static ContentValues getContentValues(String fullFilePathFilter, ContentValues destination, String dbgContext) {
final String meldung = MODUL_NAME + ".getContentValues(" + dbgContext + "," + fullFilePathFilter + ")";
QueryParameter query = new QueryParameter().addColumn(MediaDBRepository.Impl.USED_MEDIA_COLUMNS);
query.removeFirstColumnThatContains(FotoSql.SQL_COL_PK);
FotoSql.setWhereFileNames(query, fullFilePathFilter);

Cursor c = null;

try {
c = FotoSql.getMediaDBApi().createCursorForQuery(null, meldung, query, null, null);
if (c.moveToNext()) {
if (destination == null) {
destination = new ContentValues();
}
return Impl.getContentValues(c, destination);
}
} catch (Exception ex) {
Log.e(LOG_TAG, meldung +
" error :", ex);
} finally {
if (c != null) c.close();
}

return null;
}


public static class Impl {
/**
* SQL to create copy of contentprovider MediaStore.Images.
Expand Down Expand Up @@ -561,7 +596,7 @@ public static void clearMedaiCopy(SQLiteDatabase db) {
}


public static int updateMedaiCopy(Context context, SQLiteDatabase db, Date lastUpdate, IProgessListener progessListener) {
public static int updateMediaCopy(Context context, SQLiteDatabase db, Date lastUpdate, IProgessListener progessListener) {
int progress = 0;
java.util.Date startTime = new java.util.Date();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,12 @@ public static void setFileModifyDate(ContentValues values, String path) {
}
}

public static void setFileModifyDate(ContentValues values, Date fileModifyDate) {
if (fileModifyDate != null) {
setFileModifyDate(values, fileModifyDate.getTime() / 1000);
}
}

public static void setFileModifyDate(ContentValues values, long fileModifyDateSecs) {
if (fileModifyDateSecs != 0) {
values.put(SQL_COL_LAST_MODIFIED, fileModifyDateSecs);
Expand Down
5 changes: 2 additions & 3 deletions app/src/main/java/de/k3b/android/io/AndroidFileCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
import de.k3b.android.widget.FilePermissionActivity;
import de.k3b.database.QueryParameter;
import de.k3b.io.DirectoryFormatter;
import de.k3b.io.FileCommands;
import de.k3b.io.FileUtils;
import de.k3b.io.IDirectory;
import de.k3b.io.IProgessListener;
Expand All @@ -78,10 +77,10 @@
/**
* Api to manipulate files/photos.
* Same as FileCommands with update media database.
*
* <p>
* Created by k3b on 03.08.2015.
*/
public class AndroidFileCommands extends FileCommands {
public class AndroidFileCommands extends AndroidFileCommandsDbImpl {
private static final String SETTINGS_KEY_LAST_COPY_TO_PATH = "last_copy_to_path";
private static final String mDebugPrefix = "AndroidFileCommands.";
private boolean isInBackground = false;
Expand Down
138 changes: 138 additions & 0 deletions app/src/main/java/de/k3b/android/io/AndroidFileCommandsDbImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* Copyright (c) 2015-2020 by k3b.
*
* This file is part of AndroFotoFinder / #APhotoManager.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>
*/

package de.k3b.android.io;

import android.content.ContentValues;
import android.net.Uri;

import java.io.File;

import de.k3b.android.androFotoFinder.queries.FotoSql;
import de.k3b.android.androFotoFinder.queries.MediaDBRepository;
import de.k3b.io.FileCommands;
import de.k3b.io.filefacade.IFile;
import de.k3b.media.PhotoPropertiesUtil;

/**
* Api to manipulate files/photos.
* Same as FileCommands with update media database.
* <p>
* Created by k3b on 03.08.2015.
*/
public class AndroidFileCommandsDbImpl extends FileCommands {
/**
* copies a file from the sourceFullPath path to the target path.
* Android specific: also updates database.
*
* @param sourceFullPath the path of the file that shall be copied including the file name with ending
* @param targetFullPath the path of the file that shall be written to with filename
*/
@Override
protected boolean osFileCopy(IFile targetFullPath, IFile sourceFullPath) {
//!!! TODO muss noch getestet werden
final String srcPath = sourceFullPath.getAbsolutePath();
String toPath = null;
boolean dbSuccess = false;
if (PhotoPropertiesUtil.isImage(srcPath, PhotoPropertiesUtil.IMG_TYPE_ALL)) {
toPath = new File(targetFullPath.getFile(), targetFullPath.getName()).getAbsolutePath();
dbSuccess = (null != copyInDatabase("osFileCopy", srcPath, toPath));
}

if (dbSuccess) {
dbSuccess = super.osFileCopy(targetFullPath, sourceFullPath);
}
return dbSuccess;
}

/**
* Moves a file from the sourceFullPath path to the target path.
* Android specific: also updates database.
*
* @param sourceFullPath the path of the file that shall be copied including the file name with ending
* @param targetFullPath the path of the file that shall be written to with filename
*/
@Override
protected boolean osFileMove(IFile targetFullPath, IFile sourceFullPath) {
final String srcPath = sourceFullPath.getAbsolutePath();
String toPath = null;
boolean dbSuccess = false;
// Database update must be done before super.osFileMove to avoid deleting/recreating old file entry
if (PhotoPropertiesUtil.isImage(srcPath, PhotoPropertiesUtil.IMG_TYPE_ALL)) {
toPath = new File(targetFullPath.getFile(), targetFullPath.getName()).getAbsolutePath();
dbSuccess = renameInDatabase("osFileMove", srcPath, toPath);
}
final boolean osSuccess = super.osFileMove(targetFullPath, sourceFullPath);
if (!osSuccess && dbSuccess) {
// os falled. Rollback
renameInDatabase("osFileMove-rollback", toPath, srcPath);
}
return osSuccess;
}

/**
* Renames a file from the sourceFullPath path to the target path.
* Android specific: also updates database.
*
* @param sourceFullPath the path of the file that shall be copied including the file name with ending
* @param targetFullPath the path of the file that shall be written to with filename
*/
@Override
protected boolean osRenameTo(IFile targetFullPath, IFile sourceFullPath) {
final String srcPath = sourceFullPath.getAbsolutePath();
String toPath = null;
boolean dbSuccess = false;
if (PhotoPropertiesUtil.isImage(srcPath, PhotoPropertiesUtil.IMG_TYPE_ALL)) {
toPath = targetFullPath.getAbsolutePath();
dbSuccess = renameInDatabase("osRenameTo", srcPath, toPath);
}
final boolean osSuccess = super.osRenameTo(targetFullPath, sourceFullPath);
if (!osSuccess && dbSuccess) {
// os falled. Rollback
renameInDatabase("osRenameTo-rollback", toPath, srcPath);
}
return osSuccess;
}

@Override
protected boolean osDeleteFile(IFile file) {
return super.osDeleteFile(file);
}

private boolean renameInDatabase(String dbgContext, String fromPath, String toPath) {
ContentValues values = new ContentValues();
values.put(FotoSql.SQL_COL_PATH, toPath);
final int execResultCount = FotoSql.getMediaDBApi().
execUpdate(this.getClass().getSimpleName() + dbgContext, fromPath, values, null);

return 1 == execResultCount;
}

private Uri copyInDatabase(String dbgContext, String fromPath, String toPath) {
ContentValues values = MediaDBRepository.getContentValues(fromPath, null, dbgContext);
if (values != null) {
values.put(FotoSql.SQL_COL_PATH, toPath);
return FotoSql.getMediaDBApi().
execInsert(this.getClass().getSimpleName() + dbgContext, values);
}
return null;
}

}

Loading

0 comments on commit 461b889

Please sign in to comment.