Issue
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?
Solution
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);
});
}
Answered By - anDev
Answer Checked By - Willingham (JavaFixing Volunteer)