cordova-plugin-file: Platform android@9.0.0 running on Android 10 : getFile produces INVALID_MODIFICATION_ERR - Error code 9.

Bug Report

Problem

What is expected to happen?

fileSystem.root.getFile Should trigger the success callback.

What does actually happen?

On Android 10, it triggers the error callback with FileError {code: 9} (INVALID_MODIFICATION_ERR). On Android 9 it works as expected - the success callback is triggered.

Information

Issue replicated with a physical Pixel 2 & the Pixel 2 emulator from android studio.

I wasn’t getting the issue with android@8.0.0 / API 28, it’s just been introduced when switching to android@9.0.0 / API 29.

Command or Code

Minimal example:

requestFileSystem(LocalFileSystem.PERSISTENT, 0,
	function(fileSystem) {	// FS loaded
		
		fileSystem.root.getFile("test.txt", {create: true, exclusive: false},
			function(fileEntry) {	// File loaded/created
				
				fileEntry.createWriter(
					function(writer) {	// Writer created
						
						writer.write('hello');
						console.log('It worked!');
						
					},
					function(error) {	// Writer failure
						console.log('createWriter', error);
					}
				);
				
			},
			function(error) {	// File failure
				console.log('getFile', error);	// !!! This gets triggered on Android 10 !!! //
			}
		);
		
	},
	function(error) {	// FS Failure
		console.log('requestFileSystem', error);
	}
);

Output:

getFile FileError {code: 9}

Environment, Platform, Device

Android 10.0 / Pixel 2 API 29 emulator Also replicated on a real Pixel 2 / Android 10.

Works correctly on Android 9 / Samsung S8.

Version information

Cordova 9.0.0 (cordova-lib@9.0.1)

Platform android@9.0.0

cordova-plugin-file 6.0.1 & 6.0.2

Android 10.0 / Pixel 2 API 29 emulator Android Studio 4.0.1 Windows 10.

Checklist

  • I searched for existing GitHub issues
  • I updated all Cordova tooling to most recent version
  • I included all the necessary information above

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 4
  • Comments: 36 (9 by maintainers)

Most upvoted comments

I can confirm that the same line from PR #410 put manually in config.xml solves the problem. I could not install PR 410 since that exact line was conflicting with an edit-config tag we have i our config.xml.

Just to add some details, we had this line in our config.xml:

<edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application">
   <application android:usesCleartextTraffic="true" />
</edit-config>

Installing @eliadAfeka 's fork gave us this error:

Failed to install 'cordova-plugin-file': Error: cordova-plugin-file cannot be added. <edit-config> changes in this plugin conflicts with <edit-config> changes in config.xml. Conflicts must be resolved before plugin can be added.

So we edited our config.xml to look like this:

<edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application">
   <application android:usesCleartextTraffic="true" android:requestLegacyExternalStorage="true"/>
</edit-config>

and the problem seems to be solved.

Thanks everyone for your help.

@apolunderblade I think you need to update your Cordova CLI to version 10.0.0 and your Cordova Android to 9.0.0 before you can add the requestLegacyExternalStorage flag.

I see let me try! Thanks

Edited: It works! Thanks!!

I can confirm that the same line from PR #410 put manually in config.xml solves the problem. I could not install PR 410 since that exact line was conflicting with an edit-config tag we have i our config.xml.

Just to add some details, we had this line in our config.xml:

<edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application">
   <application android:usesCleartextTraffic="true" />
</edit-config>

Installing @eliadAfeka 's fork gave us this error:

Failed to install 'cordova-plugin-file': Error: cordova-plugin-file cannot be added. <edit-config> changes in this plugin conflicts with <edit-config> changes in config.xml. Conflicts must be resolved before plugin can be added.

So we edited our config.xml to look like this:

<edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application">
   <application android:usesCleartextTraffic="true" android:requestLegacyExternalStorage="true"/>
</edit-config>

and the problem seems to be solved.

Thanks everyone for your help.

It magically worked. Thank you everyone!

setting “android-targetSdkVersion” to 28 is only a temporary solution. from August 2020 android will allow new apps only with “android-targetSdkVersion=29” and existing apps from November. is someone working on a solution for it?

Gave it a go saving to another location to see if it would get around that permission, seems like saving to the app data directory cordova.file.dataDirectory works.

fileSystem.root seems to be outside of the app data perhaps? - I didn’t realise this since the docs say “fs.root is a DirectoryEntry object that represents the persistent storage in the sandboxed file system.”

Also noticed the following when trying out some options:

  • If the file was created by the API 28 app, the API 29 app seems to be able to write to it, it just can’t create new files.
  • Using requestFileSystem(window.TEMPORARY seems to work.

In case it’s useful for anyone else that only needs to store files in the app dir, the change to use cordova.file.dataDirectory is:

window.resolveLocalFileSystemURL(cordova.file.dataDirectory,	// <-----------
	function (dirEntry) {	// <-----------
		
		dirEntry.getFile("test2.txt", {create: true, exclusive: false},	// <-----------
			function(fileEntry) {	// File loaded/created
				
				fileEntry.createWriter(
					function(writer) {	// Writer created
						
						writer.write('hello');
						console.log('test2 it worked!');
						
					},
					function(error) {	// Writer failure
						console.log('createWriter', error);
					}
				);
				
			},
			function(error) {	// File failure
				console.log('getFile', error);
			}
		);
	
	},
	function(error) { console.log('resolveLocalFileSystemURL', error); }
);

Yeah I think you’re right, that worked with cordova-android@9 and android-targetSdkVersion set to 28.

Hi @Rei66RM, can your provide your code in config.xml file (loc: /config.xml) & the AndroidManifest.xml file located in - /plaforms/android/app/src/main/AndroidManifest.xml to examine the diff of my existing cordova app. Thanks!

HI Pepenero, Are you Italian? However it seems that I have solved it. Reading the various comments in the post, I have updated cordova and CLI, and now access to the filesystem is ok, also I have installed the plugin to check permissions and am still working to develop an effective file access strategy (mine app makes extensive use of it). I struggle to find valid documentation about managing files in cordova, indeed if anyone knows any efficient plugin, or documentation, if they can post it I would be very grateful. Greetings from Italy! This is my section from config.xml <preference name="android-minSdkVersion" value="22" /> <preference name="android-targetSdkVersion" value="29" /> <preference name="AndroidPersistentFileLocation" value="Compatibility" /> <preference name="SplashScreen" value="none" /> <preference name="loadUrlTimeoutValue" value="100000" /> <plugin name="cordova-plugin-android-fingerprint-auth" spec="^1.5.0" /> <plugin name="cordova-plugin-app-version" spec="~0.1.8" /> <plugin name="cordova-plugin-camera" spec="^2.4.1" /> <plugin name="cordova-plugin-device" spec="~1.1.1" /> <plugin name="cordova-plugin-device-orientation" spec="~1.0.2" /> <plugin name="cordova-plugin-dialogs" spec="~1.2.0" /> <plugin name="cordova-plugin-file" spec="^6.0.1" /> <plugin name="cordova-plugin-file-opener2" spec="~2.0.2" /> <plugin name="cordova-plugin-email-composer" spec="~0.8.15" /> <plugin name="cordova-plugin-geolocation" spec="^2.4.3" /> <plugin name="cordova-plugin-globalization" spec="~1.0.3" /> <plugin name="cordova-plugin-inappbrowser" spec="~1.3.0" /> <plugin name="cordova-plugin-media-capture" spec="^3.0.2" /> <plugin name="cordova-plugin-network-information" spec="~1.2.0" /> <plugin name="cordova-plugin-speechrecognition" spec="^1.1.2" /> <plugin name="cordova-plugin-statusbar" spec="~2.1.2" /> <plugin name="cordova-plugin-whitelist" spec="~1.2.1" /> <plugin name="cordova.plugins.diagnostic" spec="~3.5.0" /> <plugin name="org.apache.cordova.plugin.cache" spec="https://github.com/tiltshiftfocus/cordova-plugin-cache.git" /> <plugin name="phonegap-plugin-barcodescanner" spec="git+https://github.com/phonegap/phonegap-plugin-barcodescanner.git" />

@apolunderblade I think you need to update your Cordova CLI to version 10.0.0 and your Cordova Android to 9.0.0 before you can add the requestLegacyExternalStorage flag.

@breautek - I will try to see if I can fork a solution.

Definitely sounds like an API 29 restriction/change. Does it work on cordova-android@9 when targeting API 28?

Try setting the android-targetSdkVersion preference to 28. If it works, i think this will prove that there was no code change that caused the problem, just simply the target API upgrade.