react-native-image-picker not working in android 10

user11583965 picture user11583965 · Sep 24, 2020 · Viewed 7k times · Source

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 ?

Answer

Sachintha picture Sachintha · Oct 22, 2020

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.