ionic-team / ionic-team/capacitor-camera

[Bug]: IONCAMRLoadingActivity stuck forever when picking small/fast-processing images via chooseFromGallery on Android

Open
#55 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
4
Forks
1
Avg merge
2d 1h
Merged PRs (30d)
2

Description

### Current Behavior

When calling `Camera.chooseFromGallery()` and selecting a small image (fast to process), `IONCAMRLoadingActivity` launches and never dismisses — leaving a permanent native loading overlay that the user cannot close except by pressing the hardware back button.

The root cause is a race condition: small images process so fast that the result delivery via `onActivityResult` completes (and fails) before `IONCAMRLoadingActivity` finishes initializing and registers its result listener. The result is lost, and the activity waits forever for a signal that will never come.

The failure point is visible in logcat:
```
ActivityThread E fail in deliverResultsIfNeeded java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
```
followed by:
```
D Unable to find a Capacitor plugin to handle requestCode, trying Cordova plugins XXXXXXXXX
I START cz.nagram.app/io.ionic.libs.ioncameralib.view.IONCAMRLoadingActivity
```
After this, IONCAMRLoadingActivity never finishes.

### Expected Behavior

`IONCAMRLoadingActivity` should always call finish() after image processing completes, regardless of how fast the image was processed. If the result bundle is null or result delivery fails, the activity should still dismiss itself.

### Reproduction

N/A

### Screenshots / Media

1. Call `Camera.chooseFromGallery()` on Android
2. Select a small image (e.g. under ~**400px** dimensions, downloaded from the web)
3. Observe `IONCAMRLoadingActivity` appears and never dismisses
4. Large images (e.g. camera photos 3000x4000px) work fine — they take long enough to process that the activity initializes before the result arrives

### Environment Details

```Shell
OS version: Android 11, 12, 13 (reproduced on all)
@capacitor/camera: 8.2.0
@capacitor/core: 8.3.4
@capacitor/android: 8.3.4
```

### Versions Affected

8.2.0

### Platforms Affected

- [ ] iOS
- [x] Android
- [ ] Web

### Notes / Comments

Tested on 3 devices:
- Realme RMX3201 (Android 11, ColorOS) — stuck on every small image
- Samsung (Android 12) — stuck on every small image
- Xiaomi (Android 13, new Photo Picker) — stuck on every small image

Root cause deep dive:

IONCAMROpenPhotoPickerActivity launches the photo picker via startActivityForResult(intent, requestCode).
For small/fast images, by the time Android calls onActivityResult(), IONCAMROpenPhotoPickerActivity
is already finishing — so the result is delivered to MainActivity instead, which has no knowledge
of the camera plugin's pending requestCode.

Capacitor's plugin registry on MainActivity can't match the requestCode → bundle arrives null →
deliverResultsIfNeeded throws NPE → result delivery aborts → IONCAMRLoadingActivity never receives
finish() signal → stuck forever.

For large images, processing takes long enough that IONCAMROpenPhotoPickerActivity is still alive
to receive its own onActivityResult() → result delivered correctly → IONCAMRLoadingActivity finishes normally.

The fix should be in IONCAMROpenPhotoPickerActivity — it should not finish/teardown until it has
confirmed the result has been delivered, OR IONCAMRLoadingActivity should check on onResume()
whether it already has a result and call finish() immediately if the result was already processed.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.