Search code examples
ionic-frameworkcapacitorcapacitor-plugin

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

  • 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