'Capacitor Filesystem returns error while using main functions

I created a new app using capacitor 3, in this app I used the Filesystem to perform some functions. I created a service to handle everything related to the filesystem, but when I went to use the functions I had some problems.

When using Android 11 to create a directory using the mkdir() function I get the following error:

Unable to create directory, unknow reason.

Also on Android 11, when I try to create a file using only writeFile() it returns the following error:

FILE_NOTCREATED

For Android 10 and below the mkdir() function works correctly, but the writeFile() function causes the app to crash without any errors. Also, if I try to change the Diretory.ExternalStorage to Diretory.External I can create a directory in Android 11, but it still crashes when writing a file.

Using Android 11, I tried to write a txt file with a simple string and with also with a small base64 string. When using Diretory.External I can write the base64 string in a new file, but when using the Diretory.ExternalStorage I got the FILE_NOTCREATED error.

I did all the configurations and followed the steps in the documentation to set up AndroidManifest.xml.

Several tests have been done on emulators and phones with different versions of Android.

Tests with writeFile()

Android 11
base64 + Diretory.External = success
string + Diretory.External = crash
base64 + Diretory.ExternalStorage = error
string + ExternalStorage  = error

Android 10 and below
base64 + Diretory.External = success
string + Diretory.External = crash
base64 + Diretory.ExternalStorage = success
string + ExternalStorage  = crash

Android XML

    <application 
      android:allowBackup="true" 
      android:icon="@mipmap/ic_launcher" 
      android:label="@string/app_name" 
      android:roundIcon="@mipmap/ic_launcher_round"
      android:supportsRtl="true" 
      android:theme="@style/AppTheme" 
      android:requestLegacyExternalStorage="true"
    >

    <!-- Permissions -->

    <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" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.location.gps" android:required="true" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

MainFunction.ts

testeFilesystem(): void {
    let path: string = 'test/project';
    this.filesystem.checkAndCreateDir(path).then(_ => {
        this.filesystem.writeFile(path, 'test.txt', 'test').then(_ => {
            this.uicontroller.presentToast('file saved');
        });
    })
}

FilesystemService.ts

checkAndCreateDir(path: string): Promise<boolean> {
  return Filesystem.readdir({
    path: path,
    directory: Directory.ExternalStorage
  }).then(_ => {
    return true;
  }).catch(_ => {
    return Filesystem.mkdir({
      path: path,
      directory: Directory.ExternalStorage,
      recursive: true
    }).then(_ => {
      return true;
    });
  });
}

writeFile(path: string, filename: string, content: string): Promise<boolean> {
  return Filesystem.writeFile({
    path: path + filename,
    data: content,
    directory: Directory.ExternalStorage
  }).then(result => {
    if (result) {
      return true;
    } else {
      return false;
    }
  });
}

Ionic Info

Ionic CLI                     : 6.16.1 C:\Users\User\AppData\Roaming\npm\node_modules@ionic\cli
  Ionic Framework               : @ionic/angular 5.6.7
  @angular-devkit/build-angular : 0.1102.10
  @angular-devkit/schematics    : 11.2.13
  @angular/cli                  : 11.2.13
  @ionic/angular-toolkit        : 3.1.1

Capacitor:
  Capacitor CLI      : 3.0.0
  @capacitor/android : 3.0.0
  @capacitor/core    : 3.0.0
  @capacitor/ios     : not installed

Utility:
  cordova-res : 0.15.3
  native-run  : 1.3.0

System:
  NodeJS : v14.16.1 (C:\Program Files (x86)\nodejs\node.exe)
  npm    : 6.14.12
  OS     : Windows 10


Solution 1:[1]

I found this issue on capacitor's github, maybe it can help you, in short it says:

If you target SDK 30, then android:requestLegacyExternalStorage="true" will not work on Android 11+ devices. Google doesn't allow to programmatically access external shared files anymore. (Documents and ExternalStorage)

https://developer.android.com/training/data-storage/use-cases#opt-out-in-production-app

Solution 2:[2]

Got the same error ('FILE_NOTCREATED') on Android 12 using the following code after some writes:

// Save to filesystem
const resp = await Filesystem.writeFile({
  path: fileName,
  data, // base64 pdf
  directory: Directory.Documents,
});

The error occurs because of the same filename. After adding the current date with the following way, the error was solved:

const currentDate = new Date().toLocaleString().replace(/[,:\s\/]/g, '-');
const fileName = `myFile-${currentDate}.pdf`;

Be aware to replace all slashes because if not it will create sub-directories and if 'recursive: true' is not added the following error occurs on android:

Parent folder not found.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alejandro Barone
Solution 2 Temeteron