Skip to content

fix: Prevent crash (maybe) when cropping images#2172

Merged
nikclayton merged 1 commit intopachli:mainfrom
nikclayton:file-path-share
Mar 17, 2026
Merged

fix: Prevent crash (maybe) when cropping images#2172
nikclayton merged 1 commit intopachli:mainfrom
nikclayton:file-path-share

Conversation

@nikclayton
Copy link
Copy Markdown
Contributor

The image cropper is sometimes crashing in production with this error:

Exception java.lang.SecurityException: Only content:// URIs are allowed for security reasons. Received: file://
  at com.canhub.cropper.BitmapUtils.validateOutputUri$cropper_release (BitmapUtils.kt:437)
  at com.canhub.cropper.BitmapUtils.writeBitmapToUri (BitmapUtils.kt:476)
  at com.canhub.cropper.BitmapCroppingWorkerJob$start$1$1.invokeSuspend (BitmapCroppingWorkerJob.kt:96)

Not sure what's generating the file:// URL scheme, but the calling code looks like this:

val tempFile = createNewImageFile(this, if (isPng) ".png" else ".jpg")
val uriNew = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileprovider", tempFile)

viewModel.cropImageItemOld = item

cropImage.launch(
    CropImageContractOptions(
        uri = item.uri,
        cropImageOptions = CropImageOptions(
            customOutputUri = uriNew,
            outputCompressFormat = if (isPng) Bitmap.CompressFormat.PNG else Bitmap.CompressFormat.JPEG,
        ),
    ),
)

createNewImageFile(...) creates the new file in a directory obtained with context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), and according to https://developer.android.com/reference/androidx/core/content/FileProvider getExternalFilesDir is equivalent to <external-files-path ... /> in this XML file.

The existing <external-path ... /> is equivalent to getExternalStorageDirectory, which isn't used anywhere in Pachli.

The image cropper is sometimes crashing in production with this error:

Exception java.lang.SecurityException: Only content:// URIs are allowed for security reasons. Received: file://
  at com.canhub.cropper.BitmapUtils.validateOutputUri$cropper_release (BitmapUtils.kt:437)
  at com.canhub.cropper.BitmapUtils.writeBitmapToUri (BitmapUtils.kt:476)
  at com.canhub.cropper.BitmapCroppingWorkerJob$start$1$1.invokeSuspend (BitmapCroppingWorkerJob.kt:96)

Not sure what's generating the file:// URL scheme, but the calling code looks
like this:

```kotlin
val tempFile = createNewImageFile(this, if (isPng) ".png" else ".jpg")
val uriNew = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileprovider", tempFile)

viewModel.cropImageItemOld = item

cropImage.launch(
    CropImageContractOptions(
        uri = item.uri,
        cropImageOptions = CropImageOptions(
            customOutputUri = uriNew,
            outputCompressFormat = if (isPng) Bitmap.CompressFormat.PNG else Bitmap.CompressFormat.JPEG,
        ),
    ),
)
```

`createNewImageFile(...)` creates the new file in a directory obtained
with `context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)`, and
according to https://developer.android.com/reference/androidx/core/content/FileProvider
`getExternalFilesDir` is equivalent to `<external-files-path ... />` in
this XML file.

The existing `<external-path ... />` is equivalent to
`getExternalStorageDirectory`, which isn't used anywhere in Pachli.
@nikclayton nikclayton merged commit f35da43 into pachli:main Mar 17, 2026
27 checks passed
@nikclayton nikclayton deleted the file-path-share branch March 19, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant