From ac27de20e6ff3d3ac271d5fd0758a2473e13ce3a Mon Sep 17 00:00:00 2001 From: k3b <1374583+k3b@users.noreply.github.com> Date: Sat, 6 Feb 2021 17:28:20 +0100 Subject: [PATCH] #155: Android10 support: Fix sql insert if in android-contentprovider but not in local DB: do update intead --- .../ImageDetailActivityViewPager.java | 4 +- .../androFotoFinder/queries/FotoSql.java | 33 ++++++++++++- .../queries/IMediaRepositoryApi.java | 9 ++-- .../queries/MediaDBRepository.java | 10 +--- .../queries/MergedMediaRepository.java | 26 ++++++++-- .../PhotoPropertiesMediaFilesScanner.java | 49 +++++++++---------- ...oPropertiesMediaFilesScannerAsyncTask.java | 6 +-- 7 files changed, 90 insertions(+), 47 deletions(-) diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImageDetailActivityViewPager.java b/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImageDetailActivityViewPager.java index 3a851e15..8e0ed653 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImageDetailActivityViewPager.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImageDetailActivityViewPager.java @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2011, 2012 Chris Banes. - * Copyright (c) 2015-2020 by k3b. + * Copyright (c) 2015-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -553,7 +553,7 @@ protected void onActivityResult(final int requestCode, IFile orgiginalFileToScan = getCurrentIFile(); if (orgiginalFileToScan != null) { - PhotoPropertiesMediaFilesScanner.getInstance(this).updateMediaDatabase_Android42( + PhotoPropertiesMediaFilesScanner.getInstance(this).updateMediaDatabaseAndroid42( this, null, orgiginalFileToScan); } } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/queries/FotoSql.java b/app/src/main/java/de/k3b/android/androFotoFinder/queries/FotoSql.java index 57284602..47baa3b3 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/queries/FotoSql.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/queries/FotoSql.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 by k3b. + * Copyright (c) 2015-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -1121,6 +1121,37 @@ public static Long getId(Uri uriWithId) { return imageID; } + /** get imageID from file-path */ + public static Long getId(String dbgContext, String fullPath) { + return getId(dbgContext, mediaDBApi, fullPath); + } + + /** get imageID from file-path */ + public static Long getId(String _dbgContext, IMediaRepositoryApi mediaDBApi, String fullPath) { + String dbgContext = _dbgContext+" FotoSql.getId('" + fullPath + "')"; + if (fullPath != null) { + QueryParameter query = new QueryParameter() + .setID(QUERY_TYPE_UNDEFINED) + .addColumn(SQL_COL_PK) + .addFrom(SQL_TABLE_EXTERNAL_CONTENT_URI_FILE_NAME) + .addWhere(SQL_COL_PATH + "= ?", fullPath); + Cursor c = null; + + try { + c = mediaDBApi.createCursorForQuery(null, dbgContext, query, null, null); + if (c.moveToNext()) { + return c.getLong(0); + } + } catch (Exception ex) { + Log.e(FotoSql.LOG_TAG, dbgContext + fullPath + "') error :", ex); + } finally { + if (c != null) c.close(); + } + } + return null; + + } + public static void addDateAdded(ContentValues values) { long now = new Date().getTime(); values.put(SQL_COL_DATE_ADDED, now / LAST_MODIFIED_FACTOR);//sec diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/queries/IMediaRepositoryApi.java b/app/src/main/java/de/k3b/android/androFotoFinder/queries/IMediaRepositoryApi.java index b82e1d5f..7807600f 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/queries/IMediaRepositoryApi.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/queries/IMediaRepositoryApi.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 by k3b. + * Copyright (c) 2019-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -38,15 +38,16 @@ Cursor createCursorForQuery(StringBuilder out_debugMessage, String dbgContext, f final String[] sqlWhereParameters, final String sqlSortOrder, CancellationSignal cancellationSignal, final String... sqlSelectColums); + /** return numbner of modified items */ int execUpdate(String dbgContext, long id, ContentValues values); + /** return numbner of modified items */ int execUpdate(String dbgContext, String path, ContentValues values, VISIBILITY visibility); + /** return numbner of modified items */ int exexUpdateImpl(String dbgContext, ContentValues values, String sqlWhere, String[] selectionArgs); - /** - * return id of inserted item - */ + /** return id of inserted item or updateSuccessValue if update */ Long insertOrUpdateMediaDatabase(String dbgContext, String dbUpdateFilterJpgFullPathName, ContentValues values, VISIBILITY visibility, diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/queries/MediaDBRepository.java b/app/src/main/java/de/k3b/android/androFotoFinder/queries/MediaDBRepository.java index 09475844..2c48d694 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/queries/MediaDBRepository.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/queries/MediaDBRepository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 by k3b. + * Copyright (c) 2015-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -156,13 +156,7 @@ public int execUpdate(String dbgContext, String path, ContentValues values, VISI } /** - * return id of inserted item - * - * @param dbgContext - * @param dbUpdateFilterJpgFullPathName - * @param values - * @param visibility - * @param updateSuccessValue + * return id of inserted item or updateSuccessValue if update */ @Override public Long insertOrUpdateMediaDatabase(String dbgContext, String dbUpdateFilterJpgFullPathName, diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/queries/MergedMediaRepository.java b/app/src/main/java/de/k3b/android/androFotoFinder/queries/MergedMediaRepository.java index f8f31800..840ad15b 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/queries/MergedMediaRepository.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/queries/MergedMediaRepository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020 by k3b. + * Copyright (c) 2019-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -20,6 +20,7 @@ import android.content.ContentValues; import android.net.Uri; +import android.util.Log; import de.k3b.io.VISIBILITY; @@ -31,6 +32,8 @@ * Therefore apm uses a copy of contentprovider MediaStore.Images with same column names and same pk. */ public class MergedMediaRepository extends MediaRepositoryApiWrapper { + private static final String LOG_TAG = MediaDBRepository.LOG_TAG; + private final IMediaRepositoryApi database; private final IMediaRepositoryApi contentProvider; @@ -101,10 +104,27 @@ public Long insertOrUpdateMediaDatabase(String dbgContext, String dbUpdateFilter */ @Override public Uri execInsert(String dbgContext, ContentValues values) { + // insert into android-contentprovider Uri result = super.execInsert(dbgContext, values); + if (result == null) { + dbgContext = dbgContext + "-insert into Contentprovider failed"; + // not inserted because in android-contentprovider may already exist. + // get id from android-contentprovider + String path = values.getAsString(FotoSql.SQL_COL_PATH); + Long id = FotoSql.getId(dbgContext, getWriteChild(), path); - // insert with same pk as contentprovider does - values.put(FotoSql.SQL_COL_PK, FotoSql.getId(result)); + if (id == null) { + Log.i(LOG_TAG, dbgContext + " Path '" + path + "' not found. Aborted."); + return null; + } + values.put(FotoSql.SQL_COL_PK, id); + super.execUpdate(dbgContext + + "- Updating id=" + id +" instead ",id, values); + result = FotoSql.getUri(id); + } else { + // insert with same pk as contentprovider does + values.put(FotoSql.SQL_COL_PK, FotoSql.getId(result)); + } database.execInsert(dbgContext, values); values.remove(FotoSql.SQL_COL_PK); return result; diff --git a/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScanner.java b/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScanner.java index 5d72ffa8..7c30d226 100644 --- a/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScanner.java +++ b/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 by k3b. + * Copyright (c) 2015-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -53,7 +53,6 @@ import de.k3b.geo.api.IGeoPointInfo; import de.k3b.io.FileUtils; import de.k3b.io.VISIBILITY; -import de.k3b.io.filefacade.FileFacade; import de.k3b.io.filefacade.IFile; import de.k3b.media.IPhotoProperties; import de.k3b.media.PhotoPropertiesChainReader; @@ -70,7 +69,7 @@ * * Created by k3b on 14.09.2015. */ -abstract public class PhotoPropertiesMediaFilesScanner { +public abstract class PhotoPropertiesMediaFilesScanner { protected static final String CONTEXT = "PhotoPropertiesMediaFilesScanner."; /* the DB_XXXX fields are updated by the scanner via ExifInterfaceEx @@ -90,7 +89,7 @@ abstract public class PhotoPropertiesMediaFilesScanner { private static final String DB_SIZE = FotoSql.SQL_COL_SIZE; public static final int DEFAULT_SCAN_DEPTH = 22; - public static final String MEDIA_IGNORE_FILENAME = FileUtils.MEDIA_IGNORE_FILENAME; // MediaStore.MEDIA_IGNORE_FILENAME; + public static final String MEDIA_IGNORE_FILENAME = FileUtils.MEDIA_IGNORE_FILENAME; /** * singelton @@ -182,7 +181,7 @@ public static int hideFolderMedia(Activity context, String path) { return result; } - public int updateMediaDatabase_Android42(Context context, IFile[] oldPathNames, IFile... newPathNames) { + public int updateMediaDatabaseAndroid42(Context context, IFile[] oldPathNames, IFile... newPathNames) { IMediaRepositoryApi api = FotoSql.getMediaDBApi(); try { api.beginTransaction(); @@ -193,7 +192,7 @@ public int updateMediaDatabase_Android42(Context context, IFile[] oldPathNames, if (hasNew && hasOld) { result = renameInMediaDatabase(context, oldPathNames, newPathNames); } else if (hasOld) { - result = deleteInMediaDatabase(context, oldPathNames); + result = deleteInMediaDatabase(oldPathNames); } if (hasNew) { result = insertIntoMediaDatabase(context, newPathNames); @@ -246,12 +245,12 @@ private int insertIntoMediaDatabase(Context context, IFile[] newPathNames) { Long id = inMediaDb.get(fileName.getAbsolutePath()); if (id != null) { // already exists - modifyCount += update_Android42("PhotoPropertiesMediaFilesScanner.insertIntoMediaDatabase already existing " - , context, id, fileName); + modifyCount += updateAndroid42("PhotoPropertiesMediaFilesScanner.insertIntoMediaDatabase already existing " + , id, fileName); } else { - modifyCount += insert_Android42( + modifyCount += insertAndroid42( "PhotoPropertiesMediaFilesScanner.insertIntoMediaDatabase new item ", - context, fileName); + fileName); } } } @@ -262,7 +261,7 @@ private int insertIntoMediaDatabase(Context context, IFile[] newPathNames) { /** * delete oldPathNames from media database */ - private int deleteInMediaDatabase(Context context, IFile[] oldPathNames) { + private int deleteInMediaDatabase(IFile[] oldPathNames) { int modifyCount = 0; if ((oldPathNames != null) && (oldPathNames.length > 0)) { @@ -309,7 +308,7 @@ private int renameInMediaDatabase(Context context, IFile[] oldPathNames, IFile.. } int modifyCount = - deleteInMediaDatabase(context, deleteFileNames.toArray(new IFile[deleteFileNames.size()])) + deleteInMediaDatabase(deleteFileNames.toArray(new IFile[deleteFileNames.size()])) + renameInMediaDatabase(context, old2NewFileNames) + insertIntoMediaDatabase(context, insertFileNames.toArray(new IFile[insertFileNames.size()])); return modifyCount; @@ -440,14 +439,14 @@ protected IGeoPointInfo getPositionFromMeta(String absoluteJpgPath, String id, I return null; } - abstract protected IPhotoProperties loadNonMediaValues(ContentValues destinationValues, IFile jpgFile, IPhotoProperties xmpContent); + protected abstract IPhotoProperties loadNonMediaValues(ContentValues destinationValues, IFile jpgFile, IPhotoProperties xmpContent); /** @return number of copied properties */ protected int getExifValues(PhotoPropertiesMediaDBContentValues dest, IPhotoProperties src) { return PhotoPropertiesUtil.copyNonEmpty(dest, src); } - abstract public IGeoPointInfo getPositionFromFile(String absolutePath, String id); + public abstract IGeoPointInfo getPositionFromFile(String absolutePath, String id); public int updatePathRelatedFields(Context context, Cursor cursor, String newAbsolutePath) { int columnIndexPk = cursor.getColumnIndex(FotoSql.SQL_COL_PK); int columnIndexPath = cursor.getColumnIndex(FotoSql.SQL_COL_PATH); @@ -488,7 +487,7 @@ private static void setFieldIfNeccessary(ContentValues values, String fieldName, } } - private int update_Android42(String dbgContext, Context context, long id, IFile file) { + private int updateAndroid42(String dbgContext, long id, IFile file) { if ((file != null) && file.exists() && file.canRead()) { ContentValues values = createDefaultContentValues(); getExifFromFile(values, file); @@ -500,7 +499,7 @@ private int update_Android42(String dbgContext, Context context, long id, IFile protected ContentValues createDefaultContentValues() { ContentValues contentValues = new ContentValues(); - // to allow set null becyuse copy does not setNull if already has null (not found) + // to allow set null because copy does not setNull if already has null (not found) contentValues.putNull(DB_TITLE); contentValues.putNull(FotoSql.SQL_COL_LON); contentValues.putNull(FotoSql.SQL_COL_LAT); @@ -510,7 +509,7 @@ protected ContentValues createDefaultContentValues() { return contentValues; } - private int insert_Android42(String dbgContext, Context context, IFile file) { + private int insertAndroid42(String dbgContext, IFile file) { if ((file != null) && file.exists() && file.canRead()) { ContentValues values = createDefaultContentValues(); FotoSql.addDateAdded(values); @@ -521,22 +520,20 @@ private int insert_Android42(String dbgContext, Context context, IFile file) { return 0; } - @NonNull // generates a title based on file name - protected static String generateTitleFromFilePath(String _filePath) { - String filePath = generateDisplayNameFromFilePath(_filePath); + protected static String generateTitleFromFilePath(String filePath) { + String currentFilePath = generateDisplayNameFromFilePath(filePath); - if (filePath != null) { + if (currentFilePath != null) { // truncate the file extension (if any) - int lastDot = filePath.lastIndexOf('.'); + int lastDot = currentFilePath.lastIndexOf('.'); if (lastDot > 0) { - filePath = filePath.substring(0, lastDot); + currentFilePath = currentFilePath.substring(0, lastDot); } } - return filePath; + return currentFilePath; } - @NonNull // generates a title based on file name public static String generateDisplayNameFromFilePath(String filePath) { if (filePath != null) { @@ -555,7 +552,7 @@ public static String generateDisplayNameFromFilePath(String filePath) { /** update media db via android-s native scanner. * Requires android-4.4 and up to support single files */ - public static void updateMediaDB_Androd44(Context context, String[] pathNames) { + public static void updateMediaDBAndrod44(Context context, String[] pathNames) { if (Global.debugEnabled) { Log.i(Global.LOG_CONTEXT, CONTEXT + "updateMediaDB_Androd44(" + pathNames.length + " files " + pathNames[0] + "..."); } diff --git a/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScannerAsyncTask.java b/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScannerAsyncTask.java index d46bb5c5..4a2c328d 100644 --- a/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScannerAsyncTask.java +++ b/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScannerAsyncTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 by k3b. + * Copyright (c) 2016-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -48,7 +48,7 @@ public PhotoPropertiesMediaFilesScannerAsyncTask(PhotoPropertiesMediaFilesScanne @Override protected Integer doInBackground(IFile[]... pathNames) { if (pathNames.length != 2) throw new IllegalArgumentException(CONTEXT + ".execute(oldFileNames, newFileNames)"); - return mScanner.updateMediaDatabase_Android42(mContext, pathNames[0], pathNames[1]); + return mScanner.updateMediaDatabaseAndroid42(mContext, pathNames[0], pathNames[1]); } private static void notifyIfThereAreChanges(Integer modifyCount, Context context, String why) { @@ -71,7 +71,7 @@ public static void updateMediaDBInBackground( scanTask.execute(oldPathNames, newPathNames); } else { // Continute in background task - int modifyCount = scanner.updateMediaDatabase_Android42(context.getApplicationContext(), oldPathNames, newPathNames); + int modifyCount = scanner.updateMediaDatabaseAndroid42(context.getApplicationContext(), oldPathNames, newPathNames); notifyIfThereAreChanges(modifyCount, context, why + " within current non-gui-task"); } }