Bug Report
Plugin version
@capacitor/camera 8.2.0 – 8.2.3 (still present on main)
Platform
Android (observed on Android 14/15/16)
Current Behavior
Opening the system photo picker via Camera.pickImages() / Camera.getPhoto() can crash the app when returning from the gallery.
Fatal crash:
java.lang.NullPointerException: Attempt to invoke virtual method
'void androidx.activity.result.ActivityResultLauncher.unregister()'
on a null object reference
at com.capacitorjs.plugins.camera.LegacyCameraFlow.lambda$openPhotos$3 (LegacyCameraFlow.java:349)
at androidx.activity.result.ActivityResultRegistry.register (ActivityResultRegistry.kt:177)
at com.capacitorjs.plugins.camera.LegacyCameraFlow.registerActivityResultLauncher (LegacyCameraFlow.java:301)
at com.capacitorjs.plugins.camera.LegacyCameraFlow.openPhotos (LegacyCameraFlow.java:324)
at com.capacitorjs.plugins.camera.LegacyCameraFlow.pickImages (LegacyCameraFlow.java:120)
at com.capacitorjs.plugins.camera.CameraPlugin.pickImages (CameraPlugin.kt:132)
Root cause
In LegacyCameraFlow.openPhotos, the activity-result callback calls pickMultipleMedia.unregister() / pickMedia.unregister() without a null check:
https://github.com/ionic-team/capacitor-camera/blob/main/android/src/main/java/com/capacitorjs/plugins/camera/LegacyCameraFlow.java#L349-L363
ActivityResultRegistry.register() can synchronously invoke the callback when a pending result exists (e.g. after the Activity was destroyed while the Photo Picker was open and later recreated). At that moment the field has not been assigned yet (pickMultipleMedia / pickMedia is still null), so unregister() NPEs.
Note: onDestroy() already null-checks before unregister(), but the callbacks in openPhotos do not.
Expected Behavior
Returning from the gallery after Activity recreation should not crash. Selected images should still be processed when possible.
Reproduction
- Capacitor app with
@capacitor/camera
- Android Developer Options → enable Don't keep activities
- Call
Camera.pickImages({ quality: 80, limit: 5 }) (or getPhoto / gallery source)
- Select photo(s) and return
- App crashes with the NPE above
Also reproducible on low-memory devices when the OS kills the Activity while the system Photo Picker is in the foreground.
Proposed Fix
Null-check before unregister in both callbacks (same pattern as onDestroy()):
if (pickMultipleMedia != null) {
pickMultipleMedia.unregister();
}
if (pickMedia != null) {
pickMedia.unregister();
}
A slightly more robust approach is to capture the launcher in a local final holder assigned before the callback can run, so unregister always targets the instance created by that register() call.
Related
Previously reported (wrong repo, closed without fix, redirected here):
ionic-team/capacitor-plugins#2537
Additional context
Affects production apps using the deprecated pickImages / getPhoto APIs that still go through LegacyCameraFlow on Android.
Bug Report
Plugin version
@capacitor/camera8.2.0 – 8.2.3 (still present onmain)Platform
Android (observed on Android 14/15/16)
Current Behavior
Opening the system photo picker via
Camera.pickImages()/Camera.getPhoto()can crash the app when returning from the gallery.Fatal crash:
Root cause
In
LegacyCameraFlow.openPhotos, the activity-result callback callspickMultipleMedia.unregister()/pickMedia.unregister()without a null check:https://github.com/ionic-team/capacitor-camera/blob/main/android/src/main/java/com/capacitorjs/plugins/camera/LegacyCameraFlow.java#L349-L363
ActivityResultRegistry.register()can synchronously invoke the callback when a pending result exists (e.g. after the Activity was destroyed while the Photo Picker was open and later recreated). At that moment the field has not been assigned yet (pickMultipleMedia/pickMediais stillnull), sounregister()NPEs.Note:
onDestroy()already null-checks beforeunregister(), but the callbacks inopenPhotosdo not.Expected Behavior
Returning from the gallery after Activity recreation should not crash. Selected images should still be processed when possible.
Reproduction
@capacitor/cameraCamera.pickImages({ quality: 80, limit: 5 })(orgetPhoto/ gallery source)Also reproducible on low-memory devices when the OS kills the Activity while the system Photo Picker is in the foreground.
Proposed Fix
Null-check before unregister in both callbacks (same pattern as
onDestroy()):A slightly more robust approach is to capture the launcher in a local
finalholder assigned before the callback can run, so unregister always targets the instance created by thatregister()call.Related
Previously reported (wrong repo, closed without fix, redirected here):
ionic-team/capacitor-plugins#2537
Additional context
Affects production apps using the deprecated
pickImages/getPhotoAPIs that still go throughLegacyCameraFlowon Android.