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);
});
}