I have a small MAUI app i'm testing with. Im trying to read a file that was part of the deployment. I have the code below, which works great in a Windows deploy of the MAUI app, but crashes in Android. What is the proper cross-platform way to do this?
// TODO get from service or xml
var path = AppDomain.CurrentDomain.BaseDirectory;
//var path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
var fullpath = Path.Combine(path, "Services\\questions.json");
var json = File.ReadAllText(fullpath);
MAUI has a new way to access files included with the app: MauiAsset.
Described in blog Announcing .NET MAUI Preview 4, Raw Assets:
.NET MAUI now makes it very easy to add other assets to your project and reference them directly while retaining platform-native performance. For example, if you want to display a static HTML file in a WebView you can add the file to your project and annotate it as a MauiAsset in the properties.
<MauiAsset Include="Resources\Raw\index.html" />
Tip: you can also use wildcards to enable all files in a directory:
... Include="Resources\Raw\*" ...
Then you can use it in your application by filename.
<WebView Source="index.html" />
UPDATE
However, the feature MauiAsset apparently still needs improvement:
open issue - MauiAsset is very hard to use.
There we learn that for now:
Set BuildAction in each file's properties to MauiAsset.
That is, its not recommended to use the "wildcard" approach at this time. Set that build action on each file in solution explorer / your project / the file.
Accessing on Windows requires a work-around:
#if WINDOWS
var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync("Assets/" + filePath);
#else
var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync(filePath);
#endif
NOTE: This will be simplified at some point; follow that issue to see progress.
UPDATE
The current MAUI template is missing some platform-specific flags. For now, add your own flag to identify when the code is running on Windows:
Complete example in ToolmakerSteve - repo MauiSOAnswers. See MauiAssetPage.
MauiAssetPage.xaml:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiTests.MauiAssetPage">
<ContentPage.Content>
<!-- By the time Maui is released, this is all you will need. -->
<!-- The Init code-behind won't be needed. -->
<WebView x:Name="MyWebView" Source="TestWeb.html" />
</ContentPage.Content>
</ContentPage>
MauiAssetPage.xaml.cs:
using Microsoft.Maui.Controls;
using System.Threading.Tasks;
namespace MauiTests
{
public partial class MauiAssetPage : ContentPage
{
public MauiAssetPage()
{
InitializeComponent();
Device.BeginInvokeOnMainThread(async () =>
{
await InitAsync();
});
}
private async Task InitAsync()
{
string filePath = "TestWeb.html";
#if WINDOWS
var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync("Assets/" + filePath);
#else
var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync(filePath);
#endif
if (stream != null)
{
string s = (new System.IO.StreamReader(stream)).ReadToEnd();
this.MyWebView.Source = new HtmlWebViewSource { Html = s };
}
}
}
}
TestWeb.html:
(whatever html you want)
In Solution Explorer, add TestWeb.html to your project. In its Properties, select Build Action = MauiAsset.
I tried looking for a solution to this for months. I ended up hosting the file online then creating a method to download the file during runtime
public async Task DownloadFile(string fileName)
{
if (File.Exists(FileSystem.Current.AppDataDirectory + $"/{fileName}"))
{
return;
}
else
{
try
{
NetworkAccess networkAccess = Connectivity.Current.NetworkAccess;
if (networkAccess == NetworkAccess.Internet)
{
await Task.Run(() =>
{
var uri = new Uri($"https://myhostedfile.com/{fileName}");
WebClient webClient = new WebClient();
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCallback2);//checking if download is complete
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(MaintainProgress);//event handler to check download progress
webClient.DownloadFileAsync(uri, FileSystem.Current.AppDataDirectory + $"/{fileName}");
});
}
else
await Shell.Current.DisplayAlert("No Internet", "Failed to get some files from the internet, confirm if your internet is" +
"working", "OK");
}
catch (Exception)
{
await Shell.Current.DisplayAlert("Error", "Failed to get some files from the internet, confirm if your internet is" +
"working", "OK");
}
}
}
Then you can access your file URL using:
string filePath = FileSystem.Current.AppDataDirectory + $"/myfile.pdf;
Related
Using Xamarin.Forms, has the way to write to file changed since Android 8.0?
I updated an existing project of mine, which includes a very simple function to write a text file to local storage, but after running the app and testing the write to file part, it just freezes and crashes out. There are no errors in the console or even evidence of it doing anything.
My function is as such:
public void Submit_Clicked(object sender, EventArgs e)
{
{
string text = NameEntry.Text;
string path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string filename = Path.Combine(path, "DeviceProfile.txt");
File.WriteAllText(filename, text);
}
catch(Exception ex)
{
DisplayAlert("Error:", ex.Message.ToString(), "Ok");
}
}
I cant see why this shouldn't work. Does someone know any reason why this wouldn't?
Like Jason said, the code below and the code you provided both work to write a text file to local storage.
string text = NameEntry.Text;
var path = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "DeviceProfile.txt");
using (var writer = File.CreateText(backingFile))
{
await writer.WriteLineAsync(text);
}
You could read the text from the file to check.
public async Task<string> ReadCountAsync()
{
var backingFile = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "DeviceProfile.txt");
if (backingFile == null || !File.Exists(backingFile))
{
return null;
}
var text = string.Empty;
using (var reader = new StreamReader(backingFile, true))
{
var str = await reader.ReadToEndAsync();
text = str;
}
return text;
}
The path Environment.SpecialFolder.Personal you used to save the file is internal storage.
In Internal Storage, you couldn't see the files without root permission. If you want to view it, you could use adb tool. Please check the way in link.
How to write the username in a local txt file when login success and check on file for next login?
Looking at this issue xamarin/Essentials#1322, how do I download a file on both Android ( versions 6-10, Api 23-29 ) and iOS ( version 13.1+ ) that is publicly available (share-able to other apps, such as Microsoft Word). I don't need to give write access to the other apps, just read-only is ok if it must be restricted.
I get the following exception:
[Bug] Android.OS.FileUriExposedException: file:///data/user/0/{AppBundleName}/cache/file.doc exposed beyond app through Intent.getData()
With the following code.
public static string GetCacheDataPath( string fileName ) => Path.Combine(Xamarin.Essentials.FileSystem.CacheDirectory, fileName);
public static FileInfo SaveFile( string filename, Uri link )
{
using var client = new WebClient();
string path = GetCacheDataPath(filename);
DebugTools.PrintMessage(path);
client.DownloadFile(link, path);
return new FileInfo(path);
}
public async Task Test(Uri link)
{
LocalFile path = await SaveFile("file.doc", link).ConfigureAwait(true);
var url = new Uri($"ms-word://{path.FullName}", UriKind.Absolute);
await Xamarin.Essentials.Launcher.OpenAsync(url).ConfigureAwait(true);
}
With this answer, I created a FileService interface and it works with local private files but I am unable to share the files. Starting with Android Q (10 / Api 29), the following is deprecated.
string path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath; // deprecated
I get the following exception:
System.UnauthorizedAccessException: Access to the path '/storage/emulated/0/Download/file.doc' is denied. ---> System.IO.IOException: Permission denied
I haven't found any way yet to get a public path for Android 10 with Xamarin.Forms. I've looked at the Android Docs for Content providers but it's in Java, and I can't get it working in C# yet.
Any help would be greatly appreciated.
I did find a Solution
Found a fix
For Android
public Task<System.IO.FileInfo> DownloadFile( Uri link, string fileName )
{
if ( link is null )
throw new ArgumentNullException(nameof(link));
using System.Net.WebClient client = new System.Net.WebClient();
// MainActivity is the class that loads the application.
// MainActivity.Instance is a property that you set "Instance = this;" inside of OnCreate.
Java.IO.File root = MainActivity.Instance.GetExternalFilesDir(MediaStore.Downloads.ContentType);
string path = Path.Combine(root.AbsolutePath, fileName);
client.DownloadFile(link, path);
return Task.FromResult(new System.IO.FileInfo(path));
}
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
internal static MainActivity Instance { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
...
Instance = this;
...
}
...
}
For iOS
public Task<System.IO.FileInfo> DownloadFile( Uri link, string fileName )
{
if ( link is null )
throw new ArgumentNullException(nameof(link));
using System.Net.WebClient client = new System.Net.WebClient();
string path = Path.Combine(Xamarin.Essentials.FileSystem.CacheDirectory, fileName)
client.DownloadFile(link, path);
return Task.FromResult(new System.IO.FileInfo(path));
}
public async Task Share()
{
// back in shared project, choose a file name and pass the link.
System.IO.FileInfo info = await DependencyService.Get<IDownload>().DownloadFile(new Uri("<enter site>", "file.doc").ConfigureAwait(true);
ShareFile shareFile = new ShareFile(info.FullName, "doc"); // enter the file type / extension.
var request = new ShareFileRequest("Choose the App to open the file", shareFile);
await Xamarin.Essentials.Share.RequestAsync(request).ConfigureAwait(true);
}
Note that for iOS, due to Apple's infinite wisdom... I cannot share the file directly with another app as I can on Android. Sandboxing is good for security but in this case, how they implemented it, it limits options. Both Applications must be pre-registered / pre-allocated in an "App Group" to share files directly. See this Article and the Apple Docs for more information.
I am new to Unity and Android development, but please do not mark this as a duplicate - I've looked all over the stacks for an answer to this, but similar topics and questions haven't yielded any working solutions, or are wanting on details, or outdated, or seem not to fit my specific need.
Ok, I have a quiz app built from following part 1 & 2 of this tutorial. That link contains all the source files anyone might need for reference, and everything works fine on ios and in the unity editor, fyi.
The trouble is with the loadGameData function from the DataController script in Android. Again, everything works fine in iOS and the unity editor, but when I make an Android sdk, the quiz is blank and the console says the data couldn't be loaded.
Here is how the function is currently written (full file in tutorial link):
private void LoadGameData ()
{
string filePath = Path.Combine (Application.streamingAssetsPath, gameDataFileName);
if (File.Exists (result))
{
string dataAsJson = File.ReadAllText (result);
GameData loadedData = JsonUtility.FromJson<GameData> (dataAsJson);
allRoundData = loadedData.allRoundData;
} // #if(File.Exists...
else
{
Debug.LogError ("Cannot load game data!");
} // #else
} // #LoadGameData
If you check the same tutorial on youtube, you'll see lots of people have noted the same problem with the Android build and have been left unanswered. Same goes with unity forums - that's one reason why I don't think this question is a duplicate and could be helpful to others in a similar situation.
I've found that Android has always been sorta tricky with this and that there used to different ways of accessing a file based on platform, but these days "Application.streamingAssetsPath" should find the streaming assets directory on any platform, even Android.
What I've also learned is that in android, even if the path is correct, the file is compressed and will only return a url. So the url needs to be converted using unity's WWW class. I get that, but as of yet, I haven't been able to re-write my loadGameData function to work properly and load the allRoundData array.
Here's an example of some things I've tried:
IEnumerator androidData()
{
string filePath = Path.Combine (Application.streamingAssetsPath, gameDataFileName);
if (filePath.Contains("://"))
{
WWW www = new WWW(filePath);
yield return www;
result = www.text;
} // #if(filePath.Contains
} // #androidData
private void LoadGameData ()
{
androidData();
if (File.Exists (result))
{
string dataAsJson = File.ReadAllText (result);
GameData loadedData = JsonUtility.FromJson<GameData> (dataAsJson);
allRoundData = loadedData.allRoundData;
} // #if(File.Exists...
else
{
Debug.LogError ("Cannot load game data!");
} // #else
} // #LoadGameData
I know I'm close, and this is probably simple -- but I just can't seem to get to the finish line on this. Can some one help me figure out how to write the loadGameData function so it will load this allRoundData array on android?
An example code would be awesome and much appreciated, not just by me, but I'm sure many others would appreciate it also - Thank you!
UPDATE:
Based on the first answer, I've tested some code that works on the unity editor, but crashes in Android. In the Unity editor, I get the "file already exists" message. Here is the code I've tested:
Already had: private string gameDataFileName = "data.json";
I added the copyFile call above loadGameDate in Start() and wrote the copy file and loadGameData functions like so ..
int copyFileToPersistentDataPath(string gameDataFileName)
{
string persistentPath = Application.persistentDataPath + "/" + gameDataFileName;
try
{
//Copy only if gameDataFileName does not exist
if (!System.IO.File.Exists(persistentPath))
{
string path = System.IO.Path.Combine(Application.streamingAssetsPath, gameDataFileName);
WWW www = new WWW(path);
while (!www.isDone) { }
System.IO.File.WriteAllBytes(persistentPath, www.bytes);
Debug.Log(gameDataFileName + " Successfully Copied File to " + persistentPath);
return 1;
}
else
{
Debug.Log(gameDataFileName + " File already exist here. There is no need to copy it again");
return 0;
}
}
catch (Exception e)
{
Debug.Log(gameDataFileName + " Failed To Copy File. Reason: " + e.Message);
return -1;
}
}
private void LoadGameData ()
{
string tempPath = Path.Combine(Application.persistentDataPath, gameDataFileName);
string dataAsJson = File.ReadAllText(tempPath);
GameData loadedData = JsonUtility.FromJson<GameData>(dataAsJson);
allRoundData = loadedData.allRoundData;
} // #LoadGameData
This works with or without the call to copy the file in the editor, but crashes either way in Android.
I ended up putting the files in a Resources folder and going the resources.load a json file into a text asset and throw that into a string to parse route. I now have two different load functions, one that works in ios etc. and one that works in android. Here is the android function (the resourcesGameDataFile does not have the .json extension):
public void LoadDataForAndroid()
{
TextAsset dataFile = Resources.Load(resourcesGameDataFile) as TextAsset;
string dataAsJson = dataFile.ToString();
GameData loadedData = JsonUtility.FromJson<GameData>(dataAsJson);
allRoundData = loadedData.allRoundData;
Debug.Log ("Android data loaded with" + resourcesGameDataFile);
} // #LoadDataForAndroid
And this works in the unity editor and in Bluestacks (android simulator).
As for loading and saving games, this is a duplicate. I marked and remove this as a duplicate because the answer in the duplicated questions did not explain how to read from the StreamingAssets folder. It only talked about saving and loading data.
Make sure that Write Permission is set to External (SDCard).
The first thing to do is to copy the file from StreamingAssets to the persistentDataPath location.
I've found reading data from Application.streamingAssetsPath problematic but I use two methods to solve this.
int copyFileToPersistentDataPath(string fileNameWithExtensionName)
{
string persistentPath = Application.persistentDataPath + "/" + fileNameWithExtensionName;
try
{
//Copy only if fileNameWithExtensionName does not exist
if (!System.IO.File.Exists(persistentPath))
{
string path = System.IO.Path.Combine(Application.streamingAssetsPath, fileNameWithExtensionName);
WWW www = new WWW(path);
while (!www.isDone) { }
System.IO.File.WriteAllBytes(persistentPath, www.bytes);
Debug.Log(fileNameWithExtensionName + " Successfully Copied File to " + persistentPath);
return 1;
}
else
{
Debug.Log(fileNameWithExtensionName + " File already exist here. There is no need to copy it again");
return 0;
}
}
catch (Exception e)
{
Debug.Log(fileNameWithExtensionName + " Failed To Copy File. Reason: " + e.Message);
return -1;
}
}
If that does not work for you, use the method with WebClient below:
void copyFileToPersistentDataPath(string fileNameWithExtensionName)
{
string path = System.IO.Path.Combine(Application.streamingAssetsPath, fileNameWithExtensionName);
string persistentPath = Application.persistentDataPath + "/" + fileNameWithExtensionName;
Debug.Log("Dir: " + persistentPath);
WebClient webClient = new WebClient();
webClient.Proxy = null;
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(OnDownloadComplete);
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnUpdateDownloadProgress);
Uri uri = new Uri(path);
webClient.DownloadFileAsync(uri, persistentPath);
}
void OnDownloadComplete(object sender, AsyncCompletedEventArgs e)
{
Debug.Log("Finished Downloading: " + e.Error.Message);
}
void OnUpdateDownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
Debug.Log("Uploading Progreess: " + e.ProgressPercentage);
}
File Copy Usage:
copyFileToPersistentDataPath("yourFileName.txt");
After copying the file, you can then read and convert it to Json like this:
string fileNameWithExtensionName = "questionfile.txt";
string tempPath = Path.Combine(Application.persistentDataPath, fileNameWithExtensionName);
string dataAsJson = File.ReadAllText(fileNameWithExtensionName);
GameData loadedData = JsonUtility.FromJson<GameData>(dataAsJson);
I am building a Xamarin.Forms project with a PCL, iOS and Android project. One of my requirements is that I have to read a JSON file stored in the platform project (iOS/Android) from the PCL.
How can I do this please? I can't find a solution for this problem. :(
Thank you very much,
Nikolai
If the file that you want to read is embedded in the platform project assembly you can use the following code:
var assembly = typeof(MyPage).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream("WorkingWithFiles.PCLTextResource.txt");
string text = "";
using (var reader = new System.IO.StreamReader (stream)) {
text = reader.ReadToEnd ();
}
Make sure that you replace WorkingWithFiles with namespace of your project and PCLTextResource.txt with name of the file.
Check Xamarin documentation at Loading Files Embedded as Resources for more details
If on the other hand you want to create and read/write files at runtime you can use PCLStorage library:
public async Task PCLStorageSample()
{
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder folder = await rootFolder.CreateFolderAsync("MySubFolder",
CreationCollisionOption.OpenIfExists);
IFile file = await folder.CreateFileAsync("answer.txt",
CreationCollisionOption.ReplaceExisting);
await file.WriteAllTextAsync("42");
}
I got it working by using an IoC container.
In my iOS project I have created a ConfigAccess class:
public class ConfigAccess : IConfigAccess
{
public string ReadConfigAsString()
{
return System.IO.File.ReadAllText("config.json");
}
}
I also had to add the following line to my AppDelegate.cs
SimpleIoc.Default.Register<IConfigAccess, ConfigAccess>();
And in my PCL I am simply asking for a ConfigAccess object during runtime:
var configAccess = SimpleIoc.Default.GetInstance<IConfigAccess>();
var test = configAccess.ReadConfigAsString();
i am using cordova-ionic framework to build app. i am new to the iOS or iPhone
in my requirement, i have to read a file in the app. i am reading file in the android app but same code showing error (code: 5).
i am following code types:
in android:
$cordovaFile.writeFile(( 'user.json', data, {'append':false} )).then(function(result) {
alert('file created.');
alert(JSON.stringify(result));
}, function(err) {
// An error occured. Show a message to the user
alert('file writed');
alert(JSON.stringify(err));
});
i can create file, writing, reading data and removing the file but in ios phone i am not able to create file using the same code.
in iPhone:
var data = {"user":{"name":"errer","email":"sdsdff#gmail.com","username":"sdfsdfsd"}};
$cordovaFile.writeFile(( 'user.json', data, {'append':false} )).then(function(result) {
// Success!
alert('file created.');
alert(JSON.stringify(result));
}, function(err) {
// An error occured. Show a message to the user
alert('file writed');
alert(JSON.stringify(err));
});
i just change my directory is cordova.file.cacheDirecotry/cordova.file.applicationDirectory
$cordovaFile.createFile(( cordova.file.cacheDirecotry+'user.json', true )).then(function(result) {
// Success!
alert('file created.');
alert(JSON.stringify(result));
}, function(err) {
// An error occured. Show a message to the user
alert('file writed');
alert(JSON.stringify(err));
});
all way getting the error like code: 12 or code: 5
please help me to solve this or give me a idea to get application file path
I have some progression.
First, I alert my cordova.file.dataDirectory or cordova.file.documentsDirectory.
They are
file:///var/mobile/...../Library/NoCloud
and
file:///var/mobile/..../Documents
Then I create a File without the prefix and succeed. Referring to this https://github.com/driftyco/ng-cordova/issues/362
and the success message shows that the native url of the file is saved in
file:///var/mobile/...../Library/files
Which is quite strange. By the way, I add the
<preference name="iosPersistentFileLocation" value="Library" />
according to https://github.com/apache/cordova-plugin-file/blob/master/doc/index.md#ios-persistent-storage-location
All the tests are running on IOS, i haven't test for Android.
Updates
All the following code worked for me and give success response
$cordovaFile.checkFile('/test.data')
$cordovaFile.createFile('test.data',false)
$cordovaFile.checkDir('/')
Hope this can solve your problems.
/*
Here is what I am using for my Android and IOS apps
Keep attention to a couple of things:
- Android and IOS have other directorynames for files
- Android devices have different root (myFSRootDirectory1 = Samsung Tab 3, msFSRootDirectory2 = Samsung SII)
- $cordovaFile functions prefixes all pathnames with root
$cordovaFileTransfer functions needs absolute pathnames
Here I create the prefixes for File functions and FileTransfer functions for Android and IOS
*/
// The $ionicPlatform and ionic.Platorm are from Ionic framework
//
$ionicPlatform.ready(function() {
if (ionic.Platform.isAndroid()) {
// If running on Android
console.log('cordova.file.externalDataDirectory: ' + cordova.file.externalDataDirectory);
//
// I use cordova.file.externalDataDirectory because this url is for Android devices
// If you remove the app from the device these url are cleared too on the device. So keep it clean.
// Remove the root from cordova.file.externalDataDirectory
//
myFsRootDirectory1 = 'file:///storage/emulated/0/'; // path for tablet
myFsRootDirectory2 = 'file:///storage/sdcard0/'; // path for phone
fileTransferDir = cordova.file.externalDataDirectory;
if (fileTransferDir.indexOf(myFsRootDirectory1) === 0) {
fileDir = fileTransferDir.replace(myFsRootDirectory1, '');
}
if (fileTransferDir.indexOf(myFsRootDirectory2) === 0) {
fileDir = fileTransferDir.replace(myFsRootDirectory2, '');
}
console.log('Android FILETRANSFERDIR: ' + fileTransferDir);
console.log('Android FILEDIR: ' + fileDir);
}
if (ionic.Platform.isIOS()) {
// if running on IOS
console.log('cordova.file.documentsDirectory: ' + cordova.file.documentsDirectory);
// I use cordova.file.documentsDirectory because this url is for IOS (NOT backed on iCloud) devices
fileTransferDir = cordova.file.documentsDirectory;
fileDir = '';
console.log('IOS FILETRANSFERDIR: ' + fileTransferDir);
console.log('IOS FILEDIR: ' + fileDir);
}
if (ionic.Platform.isAndroid() || ionic.Platform.isIOS()) {
//
// Just functions from the list below one by one ( or chain them)
//
}
});
// Download file from 'http://www.yourdomain.com/test.jpg' to test/one/test.jpg on device Filesystem
var hostPath = 'http://www.yourdomain.com/test.jpg';
var clientPath = fileTransferDir + 'test/one/test.jpg';
var fileTransferOptions = {};
$cordovaFile.downloadFile(hostPath, clientPath, true, fileTransferOptions).then (function() {
});
// Create dir test
$cordovaFile.createDir(fileDir + 'test/').then( function(dirEntry) {
});
// Create dir aganin in dir test
$cordovaFile.createDir(fileDir + 'test/one/').then( function(dirEntry) {
});
// Create empty file test.txt in test/again/
$cordovaFile.createFile(fileDir + 'test/one/test.txt', true).then( function(fileEntry) {
});
// List of files in test/again
$cordovaFile.listDir(fileDir + 'test/one/').then( function(entries) {
console.log('list dir: ', entries);
});
// Write some text into file
$cordovaFile.writeFile(fileDir + 'test/one/test.txt', 'Some text te test filewrite', '').then( function(result) {
});
// Read text written in file
$cordovaFile.readAsText(fileDir + 'test/one/test.txt').then( function(result) {
console.log('readAsText: ', result);
});
Perhaps it's because of a typo? You have cordova.file.cacheDirecotry. Shouldn't that be : cordova.file.cacheDirectory ?
Refer to the original documentation :-
https://github.com/apache/cordova-plugin-file/blob/master/doc/index.md#ios-file-system-layout
iOS has some directories as read-only. Try changing your path.
Let me know if it does not work for you.