react-native-image-picker not working in android 10
Asked Answered
H

4

5

i am working with a project that i need to use the camera or choose image from Library so used react native image picker it works fine in develop mode and in production it doesn't work in Android 10 only i tried a lot of solutions from github like permissions i add android:requestLegacyExternalStorage="true" in the manifest but it caused me and error android:requestLegacyExternalStorage not found when i want to build in develop and also in production

i update sdk target to 29 the same problem

my image picker code

const options = {
  cancelButtonTitle: strings.cancel,
  takePhotoButtonTitle: strings.takePicture,
  chooseFromLibraryButtonTitle: strings.chooseFromLibrary,
  title: strings.selectPhoto,
  quality: 0.1,
  noData: true,
  storageOptions: {
    skipBackup: true,
    path: 'images',
    cameraRoll: true,
    waitUntilSaved: true,
  },
};

const pickImage = () => {
  const promise = new Promise(async (resolve, reject) => {
    if (Platform.OS === 'android') {
      try {
        await PermissionsAndroid.requestMultiple([
          PermissionsAndroid.PERMISSIONS.CAMERA,
          PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
        ]);

        const permissionCamera = await PermissionsAndroid.check(
          'android.permission.CAMERA',
        );
        const permissionWriteStorage = await PermissionsAndroid.check(
          'android.permission.WRITE_EXTERNAL_STORAGE',
        );

        if (!permissionCamera || !permissionWriteStorage) {
          console.log('Failed to get the required permissions.');
        }

        const source = await openPicker();

        resolve(source);
      } catch (error) {
        reject(error);
        console.log('Failed to get the required permissions.');
      }
    } else {
      try {
        const source = await openPicker();
        resolve(source);
      } catch (error) {
        reject(error);
        console.log('Failed to get the required permissions.');
      }
    }
  });
  return promise;
};

const openPicker = () => {
  const promise = new Promise((resolve, reject) => {
    ImagePicker.showImagePicker(options, response => {
      if (response.didCancel) {
        console.log('User cancelled image picker');
      } else if (response.error) {
        console.log('ImagePicker Error: ', response.error);
        reject(response.error);
      } else if (response.customButton) {
        console.log('User tapped custom button: ', response.customButton);
      } else {
        const source = {
          uri: response.path ? `file://${response.path}` : response.uri,
          name: response.fileName ? response.fileName : 'picture_0.jpg',
          filename: response.fileName ? response.fileName : 'picture_0.jpg',
          type: response.type,
        };

        resolve(source);
      }
    });
  });

  return promise;
};

const openCamera = () => {
  const promise = new Promise((resolve, reject) => {
    ImagePicker.launchCamera(options, response => {
      if (response.didCancel) {
        console.log('User cancelled image picker');
      } else if (response.error) {
        console.log('ImagePicker Error: ', response.error);
        reject(response.error);
      } else if (response.customButton) {
        console.log('User tapped custom button: ', response.customButton);
      } else {
        const source = {
          uri: response.path ? `file://${response.path}` : response.uri,
          name: response.fileName ? response.fileName : 'picture_0.jpg',
          filename: response.fileName ? response.fileName : 'picture_0.jpg',
          type: response.type,
        };

        resolve(source);
      }
    });
  });

  return promise;
};

const openGallery = () => {
  const promise = new Promise((resolve, reject) => {
    ImagePicker.launchImageLibrary(options, response => {
      if (response.didCancel) {
        console.log('User cancelled image picker');
      } else if (response.error) {
        console.log('ImagePicker Error: ', response.error);
        reject(response.error);
      } else if (response.customButton) {
        console.log('User tapped custom button: ', response.customButton);
      } else {
        const source = {
          uri: response.path ? `file://${response.path}` : response.uri,
          name: response.fileName ? response.fileName : 'picture_0.jpg',
          filename: response.fileName ? response.fileName : 'picture_0.jpg',
          type: response.type,
        };

        resolve(source);
      }
    });
  });

  return promise;
};

export {pickImage, openCamera, openGallery};

my manifest permissions

<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

some android info

 buildToolsVersion = "28.0.3"
        minSdkVersion = 16
        compileSdkVersion = 28
        targetSdkVersion = 29

so does anyone have a solution for that ?

Hairsplitting answered 24/9, 2020 at 21:46 Comment(2)
Hi, interesting, not sure if this might be of interest github.com/react-native-image-picker/react-native-image-picker/…Relieve
Follow this. https://mcmap.net/q/665386/-undefined-is-not-an-object-evaluating-imagepickermanager-showimagepickerMaganmagana
A
5

Adding the android:requestLegacyExternalStorage="true" in AndroidMenifest.xml file was worked for Android 10. Added it as property of the Application tag.

use target version as 29. Here are some information on build.gradle file.

  buildToolsVersion = "29.0.2"
  minSdkVersion = 16
  compileSdkVersion = 29
  targetSdkVersion = 29
  supportLibVersion = "29.0.0"

However this solution is not working for the Android 11. Which is latest version for now.

Assuasive answered 22/10, 2020 at 15:36 Comment(1)
C
1

1. First add the below line android\app\src\main\AndroidManifest.xml

 ...
        <usespermission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.CAMERA"/>
        
        <application
          ...
          android:requestLegacyExternalStorage="true"
          ...> 

2. Request Permission

 { 
   requestCameraPermission = async () => {
        try {
            const granted = await PermissionsAndroid.request(
                PermissionsAndroid.PERMISSIONS.CAMERA,
                {
                    title: 'Truventorm Camera Permission',
                    message:
                        'Truventorm needs access to your camera ' +
                        'to set profile picture.',
                    buttonNeutral: 'Ask Me Later',
                    buttonNegative: 'Cancel',
                    buttonPositive: 'OK',
                },
            );
            if (granted === PermissionsAndroid.RESULTS.GRANTED) {
                console.log('You can use the camera');
                this.chooseFromCamera();
            } else {
                console.log('Camera permission denied');
            }
        } catch (err) {
            console.warn(err);
        }
    }
}

3. Now Lunch Camera

chooseFromCamera = async() => {
    let options = {
      storageOptions: {
        skipBackup: true,
        path: 'images',
      },
    };

    launchCamera( options ,(response) => {
      console.log('Response = ', response);

      if (response.didCancel) {
        console.log('User cancelled image picker');
      } else if (response.error) {
        console.log('ImagePicker Error: ', response.error);
      } else if (response.customButton) {
        console.log('User tapped custom button: ', response.customButton);
        alert(response.customButton);
      } else {
        const source = { uri: response.uri };
        console.log('response', JSON.stringify(response));
        this.setState({
          filePath: response,
          fileData: response.data,
          fileUri: response.uri
        });
      }
    });

  }
Cormier answered 9/12, 2021 at 21:15 Comment(0)
H
0

For the reference: there's a thread for this issue on GitHub with more information: https://github.com/react-native-image-picker/react-native-image-picker/issues/1393#issuecomment-690312980

Another suggested solution is to lower your targetSDK to version 28 (android/build.gradle):

    buildToolsVersion = "28.0.3"
    minSdkVersion = 16
    compileSdkVersion = 28
    targetSdkVersion = 28

Another note: if you only use the camera and not the feature to choose from the gallery, and if you don't want the photo to appear in the gallery, then you can also set this option without changing the SDK version or setting any legacy option:

storageOptions={{ privateDirectory: true  }}
Hettiehetty answered 3/12, 2020 at 14:56 Comment(0)
J
0

If image picker still not work then you can use react-native-image-crop-picker.

After that, you have to make choose pic button and choose camera button and perform a function consist of code for image pic

ImagePicker.openPicker({
    multiple: true,
}).then(images => {})

and for camera

ImagePicker.openCamera({
    width: 300,
    height: 400,
    cropping: false,
}).then(images => {})

where images is your image file, get the path of that file and display it in uri:

Jarvis answered 24/6, 2021 at 8:4 Comment(1)

© 2022 - 2024 — McMap. All rights reserved.