ionic-team / ionic-team/capacitor-camera
Android: chooseFromGallery crashes with EACCES permission denied on Android Scoped Storage (huawei)
- Dominant language
- TypeScript
- Stars
- 4
- Forks
- 1
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 2
Description
### Current Behavior
@capacitor/camera: 8.2.1
Camera.getPhoto() works correctly.
Camera.chooseFromGallery() crashes on Android Huawei devices. (IOS and web ok)
Environment:
- EMUI : 12.0.0
- Huawei P30 Pro
- modèle VOG-L29
Code:
Camera.chooseFromGallery({
quality: 80,
targetWidth: 600,
targetHeight: 600,
includeMetadata: false, (tried true)
})
Crash:
java.io.FileNotFoundException:
/storage/emulated/0/Pictures/IMG_20260119_112248.jpg:
open failed: EACCES (Permission denied)
Stacktrace:
IONCAMRMediaProcessor.createImageMediaResult
ExifInterface.
The plugin seems to access the absolute filesystem path instead of using ContentResolver/content:// URI.
---------------------
FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: com.xx.xxxx, PID: 32117
java.io.FileNotFoundException: /storage/emulated/0/Pictures/Screenshots/Screenshot_20260708_121645_com.huawei.android.launcher.jpg: open failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:496)
at java.io.FileInputStream.(FileInputStream.java:159)
at java.io.FileInputStream.(FileInputStream.java:115)
at android.media.ExifInterface.initForFilename(ExifInterface.java:2363)
at android.media.ExifInterface.(ExifInterface.java:1415)
at io.ionic.libs.ioncameralib.processor.IONCAMRMediaProcessor.createImageMediaResult(IONCAMRMediaProcessor.kt:81)
at io.ionic.libs.ioncameralib.processor.IONCAMRMediaProcessor.createImageMediaResult$default(IONCAMRMediaProcessor.kt:65)
at io.ionic.libs.ioncameralib.manager.IONCAMRGalleryManager.createMediaResult(IONCAMRGalleryManager.kt:240)
at io.ionic.libs.ioncameralib.manager.IONCAMRGalleryManager.onChooseFromGalleryResult(IONCAMRGalleryManager.kt:126)
at com.capacitorjs.plugins.camera.IonCameraFlow$processResultFromGallery$1.invokeSuspend(IonCameraFlow.kt:901)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:811)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:715)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:702)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@1efbba4, Dispatchers.Default]
Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Linux.open(Native Method)
at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8464)
at libcore.io.IoBridge.open(IoBridge.java:482)
... 15 more
-------------------- (with the addition of service tag on manifest.xml ):
FATAL EXCEPTION: DefaultDispatcher-worker-2
Process: com.xxx.xxxxx, PID: 3638
java.io.FileNotFoundException: /storage/emulated/0/Pictures/Screenshots/Screenshot_20260708_121645_com.huawei.android.launcher.jpg: open failed: EACCES (Permission denied)
at libcore.io.IoBridge.open(IoBridge.java:496)
at java.io.FileInputStream.(FileInputStream.java:159)
at java.io.FileInputStream.(FileInputStream.java:115)
at android.media.ExifInterface.initForFilename(ExifInterface.java:2363)
at android.media.ExifInterface.(ExifInterface.java:1415)
at io.ionic.libs.ioncameralib.processor.IONCAMRMediaProcessor.createImageMediaResult(IONCAMRMediaProcessor.kt:81)
at io.ionic.libs.ioncameralib.processor.IONCAMRMediaProcessor.createImageMediaResult$default(IONCAMRMediaProcessor.kt:65)
at io.ionic.libs.ioncameralib.manager.IONCAMRGalleryManager.createMediaResult(IONCAMRGalleryManager.kt:240)
at io.ionic.libs.ioncameralib.manager.IONCAMRGalleryManager.onChooseFromGalleryResult(IONCAMRGalleryManager.kt:126)
at com.capacitorjs.plugins.camera.IonCameraFlow$processResultFromGallery$1.invokeSuspend(IonCameraFlow.kt:901)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:811)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:715)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:702)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@2d03a37, Dispatchers.Default]
Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
at libcore.io.Linux.open(Native Method)
at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8464)
at libcore.io.IoBridge.open(IoBridge.java:482)
... 15 more
### Expected Behavior
When selecting an image from the gallery with Camera.chooseFromGallery(), the plugin should successfully return the selected image without crashing.
The plugin should handle Android Scoped Storage correctly by using the content URI provided by Android (ContentResolver/content:// URI) instead of trying to access the image through an absolute filesystem path.
### Reproduction
1. Install the app on an Android Huawei device with EMUI 12.
2. Use @capacitor/camera version 8.2.1.
3. Call: Camera.chooseFromGallery({ quality: 80, targetWidth: 600, targetHeight: 600, includeMetadata: false });
4. Select an existing image from the gallery.
5. The application crashes. The issue does not happen with: - Camera.getPhoto({ source: CameraSource.Photos }) -
iOS and Web : ok
### Screenshots / Media
_No response_
### Environment Details
```Shell
Latest Dependencies:
@capacitor/cli: 8.4.2
@capacitor/core: 8.4.2
@capacitor/android: 8.4.2
@capacitor/ios: 8.4.2
Installed Dependencies:
@capacitor/cli: 8.4.1
@capacitor/core: 8.4.1
@capacitor/android: 8.4.1
@capacitor/ios: 8.4.1
@capacitor/camera": "^8.2.1"
node 22
minSdkVersion = 24
compileSdkVersion = 36
targetSdkVersion = 36
androidxActivityVersion = '1.11.0'
androidxAppCompatVersion = '1.7.1'
androidxCoordinatorLayoutVersion = '1.3.0'
androidxCoreVersion = '1.17.0'
androidxFragmentVersion = '1.8.9'
coreSplashScreenVersion = '1.2.0'
androidxWebkitVersion = '1.14.0'
junitVersion = '4.13.2'
androidxJunitVersion = '1.3.0'
androidxEspressoCoreVersion = '3.7.0'
cordovaAndroidVersion = '14.0.1'
```
### Versions Affected
8.2.1
### Platforms Affected
- [ ] iOS
- [x] Android
- [ ] Web
### Notes / Comments
I suspect the issue is related to Huawei EMUI Scoped Storage handling.
The selected image seems to be returned as a filesystem path:
/storage/emulated/0/Pictures/...
instead of being processed through a content URI.
Android's MediaStore/Photo Picker should probably be accessed through ContentResolver to avoid permission issues.
Contributor guide
Research direction
Start at IONCAMRMediaProcessor.kt:81 and trace the gallery result through IONCAMRGalleryManager.kt:126 and :240, as identified in the stack trace. Verify how the selected image is opened and confirm with the Huawei EMUI 12 reproduction that chooseFromGallery returns the image without an EACCES crash.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, kotlin
- Domain
- mobile-dev
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100