4

I need to download file to user's Download directory in React Native app using rn-fetch-blob, but seems like it is not compatible with Android 10, because I am getting error:

enter image description here

First I ask for permissions:

try {
            const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE);
            if (granted === PermissionsAndroid.RESULTS.GRANTED) {
                await actualDownloadPDF();
            } else {
                ToastAndroid.show('Nepovolili jste ukládání souborů do zařízení.', ToastAndroid.LONG);
            }
        } catch (err) {
            console.warn(err);
        }

then I try to download file:

const res = await RNFetchBlob.config({
                addAndroidDownloads: {
                    useDownloadManager: true,
                    notification: true,
                    mime: 'application/pdf',
                    title: filename,
                    path: dirs.DownloadDir,
                },
            }).fetch('GET', url, {
                Authorization: 'Bearer ' + Api.Bearer,
            });

It seems like Android 10 requires from developer to open Intent where user select write permission to folder ( https://developer.android.com/training/data-storage/shared/documents-files#grant-access-directory), but I am not sure how to do it, because it seems like RNFetchBlob does not have this feature, yet.

Any ideas how to make this work? It was working fine on Android 9.

Baterka
  • 3,075
  • 5
  • 31
  • 60

4 Answers4

3
const fileName = 'document.pdf'; 
const destPath = RNFetchBlob.fs.dirs.DownloadDir + '/' + fileName;

const config = {
  fileCache : true, 
  path: destPath, 
  addAndroidDownloads: { 
    title: destPath, 
    description: `Download ${destPath}`,
    useDownloadManager: false, 
    notification: false,
  }
}; 

const res = await RNFetchBlob.config(config)...

I'm using this code and it works on Android 10.

Luis Abarca
  • 154
  • 3
  • 1
    How to open this downloaded file. I am facing an issue with Android. For iOS, it worked perfectly. – Sharad S Katre Mar 22 '21 at 17:10
  • 1
    @SharadSKatre if you want to open it in *your* app, you can use https://www.npmjs.com/package/react-native-pdf (look at the example section). Or, if you want to open it using some native (Android or iOS) viewer, use react-native-file-viewer. – Filip Savic Apr 02 '21 at 09:01
2

Add android:requestLegacyExternalStorage="true" to in your AndroidManifest.xml

<application
  ...
  android:requestLegacyExternalStorage="true"
>
1

I think that your if clause is wrong. My working example look like this:

import { PermissionsAndroid } from "react-native";

export const CheckFilePermissions = async (platform) => {
  if(platform === 'android') {
    try {
      const granted = await PermissionsAndroid.requestMultiple([
        PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
        PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
      ]);
      if (granted['android.permission.READ_EXTERNAL_STORAGE'] && granted['android.permission.WRITE_EXTERNAL_STORAGE']) {
        // user granted permissions
        return true;
      } else {
        // user didn't grant permission... handle with toastr, popup, something...
        return false;
      }
    } catch (err) {
      // unexpected error
      return false;
    }
  } else {
    // platform is iOS
    return true;
  }
};

You can use it like:

if(await CheckFilePermissions(Platform.OS)) {
....
your code 
....
David Ćeranić
  • 154
  • 1
  • 7
1

You should give complete path to the 'path' field. Change

path: dirs.DownloadDir

to

path: dirs.DownloadDir`/download.pdf`
Sanaullah Javeid
  • 103
  • 1
  • 10