Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write files to the Android external storage using React Native FS

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?

like image 206
Amphyx Avatar asked Jan 25 '23 19:01

Amphyx


1 Answers

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);
      });
  }
like image 185
Amphyx Avatar answered May 04 '23 18:05

Amphyx