diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 01f2ba8ded5..e4799c6dac9 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -13,7 +13,6 @@ android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" - android:requestLegacyExternalStorage="true" android:theme="@style/AppTheme"> this.showImagePicker(RNImagePicker.launchCamera), + pickAttachment: () => this.showImagePicker(launchCamera), }, { icon: Gallery, text: this.props.translate('attachmentPicker.chooseFromGallery'), - pickAttachment: () => this.showImagePicker(RNImagePicker.launchImageLibrary), + pickAttachment: () => this.showImagePicker(launchImageLibrary), }, { icon: Paperclip, @@ -95,7 +96,7 @@ class AttachmentPicker extends Component { * @param {ImagePickerResponse|DocumentPickerResponse} attachment */ pickAttachment(attachment) { - if (attachment && !attachment.didCancel && !attachment.error) { + if (attachment) { if (attachment.width === -1 || attachment.height === -1) { this.showImageCorruptionAlert(); return; @@ -135,20 +136,25 @@ class AttachmentPicker extends Component { showImagePicker(imagePickerFunc) { return new Promise((resolve, reject) => { imagePickerFunc(imagePickerOptions, (response) => { - if (response.error) { - switch (response.error) { - case 'Camera permissions not granted': - case 'Permissions weren\'t granted': + if (response.didCancel) { + // When the user cancelled resolve with no attachment + return resolve(); + } + if (response.errorCode) { + switch (response.errorCode) { + case 'permission': this.showPermissionsAlert(); break; default: - this.showGeneralAlert(response.error); + this.showGeneralAlert(); break; } - reject(new Error(`Error during attachment selection: ${response.error}`)); + + return reject(new Error(`Error during attachment selection: ${response.errorMessage}`)); } - resolve(response); + // Resolve with the first (and only) selected file + return resolve(response.assets[0]); }); }); } diff --git a/src/components/AttachmentPicker/launchCamera.android.js b/src/components/AttachmentPicker/launchCamera.android.js new file mode 100644 index 00000000000..b431c55e756 --- /dev/null +++ b/src/components/AttachmentPicker/launchCamera.android.js @@ -0,0 +1,32 @@ +import {PermissionsAndroid} from 'react-native'; +import {launchCamera} from 'react-native-image-picker'; + +/** + * Launching the camera for Android involves checking for permissions + * And only then starting the camera + * If the user deny permission the callback will be called with an error response + * in the same format as the error returned by react-native-image-picker + * @param {CameraOptions} options + * @param {function} callback - callback called with the result + */ +export default function launchCameraAndroid(options, callback) { + // Checks current camera permissions and prompts the user in case they aren't granted + PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA) + .then((permission) => { + if (permission !== PermissionsAndroid.RESULTS.GRANTED) { + const error = new Error('User did not grant permissions'); + error.errorCode = 'permission'; + throw error; + } + + launchCamera(options, callback); + }) + .catch((error) => { + /* Intercept the permission error as well as any other errors and call the callback + * follow the same pattern expected for image picker results */ + callback({ + errorMessage: error.message, + errorCode: error.errorCode || 'others', + }); + }); +} diff --git a/src/components/AttachmentPicker/launchCamera.js b/src/components/AttachmentPicker/launchCamera.js new file mode 100644 index 00000000000..dc1f921086d --- /dev/null +++ b/src/components/AttachmentPicker/launchCamera.js @@ -0,0 +1,3 @@ +import {launchCamera} from 'react-native-image-picker'; + +export default launchCamera;