expo-image-picker fails with exception when launching camera async
See original GitHub issueREAD THIS FIRST, PLEASE!
Hello! Thanks for reporting an issue. Please make sure you’re posting this in the right place:
- If this is an issue with Expo CLI, our command line tool, please post it in the https://github.com/expo/expo-cli repo instead.
- If this is a feature request, please vote or post it at https://expo.canny.io instead.
- If you are unable to create a reproducible Snack example that demonstrates the bug/issue, please first post in our forums at https://forums.expo.io/ before opening an issue here! (Unless the bug/issue pertains to a standalone, non-ejected build)
Thanks for helping us make Expo better!
Environment
Expo CLI 2.11.7 environment info: System: OS: macOS 10.14.3 Shell: 3.2.57 - /bin/bash Binaries: Node: 10.15.3 - ~/.nvm/versions/node/v10.15.3/bin/node Yarn: 1.13.0 - /usr/local/bin/yarn npm: 6.4.1 - ~/.nvm/versions/node/v10.15.3/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman IDEs: Android Studio: 3.3 AI-182.5107.16.33.5314842 Xcode: 10.1/10B61 - /usr/bin/xcodebuild npmPackages: react: 16.6.3 => 16.6.3 react-native: 0.58.6 => 0.58.6 react-navigation: ^3.3.2 => 3.3.2
This is a bare Expo app created with expo init --template bare-minimum and which has the expo-image-picker module added as per https://github.com/expo/expo/tree/master/packages/expo-image-picker
I am running on a Samsung Galaxy S5 (SM-G930F) running Android 8.0.0 Oreo, API Level 26.
Steps to Reproduce
Here’s the code that launches the ImagePicker:
import * as ImagePicker from "expo-image-picker";
import PropTypes from "prop-types";
import { Component } from "react";
class TakePhoto extends Component {
// Permissions.CAMERA and Permissions.CAMERA_ROLL have already been secured at this point
componentDidMount() {
const { onSuccess, onError, onCancel, quality } = this.props;
ImagePicker.launchCameraAsync({
allowsEditing: true,
aspect: [1, 1],
quality: quality,
base64: true,
})
.then(res => {
if (!res.cancelled) {
const file = `data:image/jpeg;base64,${res.base64}`;
onSuccess(file);
} else {
onCancel();
}
})
.catch(error => onError(error));
}
render() {
return null;
}
}
TakePhoto.propTypes = {
onSuccess: PropTypes.func.isRequired,
onError: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired,
quality: function(props, propName, componentName) {
const quality = props[propName];
if (typeof quality !== "number" || quality <= 0 || quality > 1) {
return new Error(
`Invalid prop ${propName} supplied to ${componentName} must be a number in (0, 1]. Validation failed.`,
);
}
},
};
TakePhoto.defaultProps = {
quality: 0.5,
};
export default TakePhoto;
(Write your steps here:)
- Tap the button that mounts the TakePhoto Component.
- TakePhoto launches the camera async.
- The app instantly crashes with the exception given below.
Expected Behavior
expo-image-picker should NOT crash when we use it to take a picture with the device camera.
Actual Behavior
App crashes with the following exception:
03-11 23:27:52.537 2257 2257 E AndroidRuntime: java.lang.RuntimeException: Unable to resume activity {com.bidvidclientmobile/com.bidvidclientmobile.MainActivity}: android.os.FileUriExposedException: file:///data/user/0/com.bidvidclientmobile/cache/ImagePicker/458e779d-3481-4e7d-8e85-caca047b2d41.jpg exposed beyond app through ClipData.Item.getUri()
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3790)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3830)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1746)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:105)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.os.Looper.loop(Looper.java:164)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6944)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: Caused by: android.os.FileUriExposedException: file:///data/user/0/com.bidvidclientmobile/cache/ImagePicker/458e779d-3481-4e7d-8e85-caca047b2d41.jpg exposed beyond app through ClipData.Item.getUri()
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.os.StrictMode.onFileUriExposed(StrictMode.java:1958)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.net.Uri.checkFileUriExposed(Uri.java:2356)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.content.ClipData.prepareToLeaveProcess(ClipData.java:944)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.content.Intent.prepareToLeaveProcess(Intent.java:10480)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.content.Intent.prepareToLeaveProcess(Intent.java:10465)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.app.Instrumentation.execStartActivity(Instrumentation.java:1616)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:4564)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:4522)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at expo.modules.imagepicker.ImagePickerModule.startActivityOnResult(ImagePickerModule.java:755)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at expo.modules.imagepicker.ImagePickerModule.launchCameraWithPermissionsGranted(ImagePickerModule.java:201)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at expo.modules.imagepicker.ImagePickerModule.access$000(ImagePickerModule.java:60)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at expo.modules.imagepicker.ImagePickerModule$1.onPermissionsResult(ImagePickerModule.java:156)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at expo.modules.permissions.PermissionsService$1.onPermissionResult(PermissionsService.java:56)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at expo.adapters.react.services.UIManagerModuleWrapper$5.onRequestPermissionsResult(UIManagerModuleWrapper.java:217)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at com.facebook.react.ReactActivityDelegate$1.invoke(ReactActivityDelegate.java:201)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at com.facebook.react.ReactActivityDelegate.onResume(ReactActivityDelegate.java:111)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at com.facebook.react.ReactActivity.onResume(ReactActivity.java:64)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1361)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.app.Activity.performResume(Activity.java:7352)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3765)
03-11 23:27:52.537 2257 2257 E AndroidRuntime: ... 8 more
Reproducible Demo
I can’t create a snack because this is an expo bare app.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:2
- Comments:31 (22 by maintainers)
I’ve provided PR with fix for that, but if you need changes immediately you can go apply it manually 😉
@bbarthec are you sure that your pull request #3743 fixes the issue? I’ve copied the changes into my bare app and I still get the
FileUriExposedException
.In order to fix it I’ve had to replace
ExpFileUtils.uriFromFile
withExpFileUtils.contentUriFromFile
inlaunchCameraWithPermissionsGranted
:The change goes into this line: https://github.com/expo/expo/blob/master/packages/expo-image-picker/android/src/main/java/expo/modules/imagepicker/ImagePickerModule.java#L301
After doing this I got this Exception:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
.To fix it, in
ExpFileUtils.contentUriFromFile
I’ve had to change the name of the provider authority to match the one you put in theAndroidManifest.xml
in #3743:The names need to match - see https://stackoverflow.com/a/30896464/4034572.
The change goes into this line: https://github.com/expo/expo/blob/master/packages/expo-image-picker/android/src/main/java/expo/modules/imagepicker/ImagePickerModule.java#L807
With this 2 changes it does work. I can now call
ImagePicker.launchCameraAsync
without the app crashing.If you want I can open a pull request (would be my first open source contribution 😃 Just let me know.