From 239bd72cf945e2433c06b21ba8dc861ebe5a31ad Mon Sep 17 00:00:00 2001 From: Sonal Yadav Date: Sun, 17 Aug 2025 10:36:08 +0530 Subject: [PATCH] Fix Crash --- .../commons/upload/ImageProcessingService.kt | 54 +++++++++---------- .../nrw/commons/upload/worker/UploadWorker.kt | 12 ++++- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.kt b/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.kt index 476c926c8..98f5042a7 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.kt @@ -128,39 +128,35 @@ class ImageProcessingService @Inject constructor( * @return IMAGE_DUPLICATE or IMAGE_OK */ fun checkIfFileAlreadyExists(originalFilePath: Uri, modifiedFilePath: Uri): Single { - return Single.zip( - // Handle SecurityException for picker URIs that have lost permission - Single.defer { - try { - val inputStream = appContext.contentResolver.openInputStream(originalFilePath) - if (inputStream != null) { - checkDuplicateImage(inputStream = inputStream) - } else { - Single.just(IMAGE_OK) - } - } catch (e: SecurityException) { - Timber.w(e, "Security exception accessing picker URI - permission lost after app restart") - Single.just(IMAGE_OK) - } catch (e: Exception) { - Timber.e(e, "Error accessing original file URI") - Single.just(IMAGE_OK) + // Safely open the original (picker) URI. If permission is gone after app restart, + // skip this leg and proceed with the modified file check to avoid crashing. + val originalCheck: Single = + Single.fromCallable { appContext.contentResolver.openInputStream(originalFilePath) } + .flatMap { inputStream -> + if (inputStream != null) checkDuplicateImage(inputStream) else Single.just(IMAGE_OK) } - }, - // Handle exceptions for modified file path - Single.defer { - try { - checkDuplicateImage(inputStream = fileUtilsWrapper.getFileInputStream(modifiedFilePath.path)) - } catch (e: Exception) { - Timber.e(e, "Error accessing modified file") - Single.just(IMAGE_OK) + .onErrorReturn { t -> + Timber.w(t, "Skipping original URI duplicate check (no permission or not found)") + IMAGE_OK } - } - ) { resultForOriginal, resultForDuplicate -> + .subscribeOn(Schedulers.io()) + + // Safely open the modified file stream as well; be defensive in case the temp/cached file + // was cleaned up while the app was backgrounded. + val modifiedCheck: Single = + Single.fromCallable { fileUtilsWrapper.getFileInputStream(modifiedFilePath.path) } + .flatMap { inputStream -> + if (inputStream != null) checkDuplicateImage(inputStream) else Single.just(IMAGE_OK) + } + .onErrorReturn { t -> + Timber.w(t, "Skipping modified file duplicate check (file missing)") + IMAGE_OK + } + .subscribeOn(Schedulers.io()) + + return Single.zip(originalCheck, modifiedCheck) { resultForOriginal, resultForDuplicate -> return@zip if (resultForOriginal == IMAGE_DUPLICATE || resultForDuplicate == IMAGE_DUPLICATE) IMAGE_DUPLICATE else IMAGE_OK - }.onErrorReturn { error -> - Timber.e(error, "Error during duplicate file check") - IMAGE_OK } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/worker/UploadWorker.kt b/app/src/main/java/fr/free/nrw/commons/upload/worker/UploadWorker.kt index feed1fdac..587f05a1f 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/worker/UploadWorker.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/worker/UploadWorker.kt @@ -612,7 +612,17 @@ class UploadWorker( private fun saveIntoUploadedStatus(contribution: Contribution) { contribution.contentUri?.let { val imageSha1 = contribution.imageSHA1.toString() - val modifiedSha1 = fileUtilsWrapper.getSHA1(fileUtilsWrapper.getFileInputStream(contribution.localUri?.path)) + + // The local modified file might be gone after app restart. + // Be defensive: if the file is missing or cannot be opened, fall back to imageSha1. + val modifiedSha1: String = try { + val modifiedStream = fileUtilsWrapper.getFileInputStream(contribution.localUri?.path) + if (modifiedStream != null) fileUtilsWrapper.getSHA1(modifiedStream) else imageSha1 + } catch (e: Exception) { + Timber.w(e, "Skipping modified SHA1 calculation (file missing/unavailable)") + imageSha1 + } + CoroutineScope(Dispatchers.IO).launch { uploadedStatusDao.insertUploaded( UploadedStatus(