My React Native Android application needs to save a JSON file in the special folder located in the external storage. I am trying to do it using RNFS (https://github.com/itinance/react-native-fs) this way:
const saveData = async () => {
    var path = `${RNFS.ExternalStorageDirectoryPath}/MyApp`;
    RNFS.mkdir(path);
    path += '/data.json';
    RNFS.writeFile(path, JSON.stringify(getData()), 'utf8')
      .then((success) => {
        console.log('Success');
      })
      .catch((err) => {
        console.log(err.message);
      });
  }
It works well but fails on Android Q device. This error is shown:
Error: Directory could not be created
If I try to write a plain file without creating directory it throws this error:
ENOENT: open failed: ENOENT (No such file or directory), open '/storage/emulated/0/data.json'
However, I've added this permissions to my AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
And granted the external storage permissions in the settings. But if I change the RNFS.ExternalStorageDirectoryPath to RNFS.DocumentDirectoryPath it works without any errors. But I need to get an access to the external storage. Is there any way to do it?
I've found out that legacy external storage access is required from Android API 29+. So, I've editied my AndroidManifest.xml (that located in android/app/src/main/) like this:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.appName">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <application
    ...
      android:requestLegacyExternalStorage="true"
    ...
    >
    </application>
</manifest>
And everything has started to work. Also, I've added a request for granting permissions to the saveData function:
const saveData = async () => {
    try {
      const granted = await PermissionsAndroid.requestMultiple([
        PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
        PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
      ]);
    } catch (err) {
      console.warn(err);
    }
    const readGranted = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE); 
    const writeGranted = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE);
    if(!readGranted || !writeGranted) {
      console.log('Read and write permissions have not been granted');
      return;
    }
    var path = `${RNFS.ExternalStorageDirectoryPath}/MyApp`;
    RNFS.mkdir(path);
    path += '/data.json';
    RNFS.writeFile(path, JSON.stringify(getData()), 'utf8')
      .then((success) => {
        console.log('Success');
      })
      .catch((err) => {
        console.log(err.message);
      });
  }
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With