I don’t know how IsolatedStorageFile works. I think writing to the actual file system for mobile platforms is not desired anymore and that using some kind of cloud storage is preferred, but I don’t know how to use that.
For my own game, supporting Windows and Android, I used file storage as well and used the nuget package PCLStorage.
To use this, I made an interface…
namespace ArbitraryPixel.Common.SimpleFileSystem
{
/// <summary>
/// Represents an object that can perform simple interactions with a file system.
/// </summary>
public interface ISimpleFileSystem
{
/// <summary>
/// Check whether or not a file exists.
/// </summary>
/// <param name="fileName">The file to check.</param>
/// <returns>True if the file exists on the file system, false otherwise.</returns>
bool FileExists(string fileName);
/// <summary>
/// Check whether or not a folder exists.
/// </summary>
/// <param name="folderName">The folder to check.</param>
/// <returns>True if the folder exists on the file system, false otherwise.</returns>
bool FolderExists(string folderName);
/// <summary>
/// Create a folder in the file system. An exception will be thrown if the folder already exists.
/// </summary>
/// <param name="folderName">The name of the folder to create.</param>
void CreateFolder(string folderName);
/// <summary>
/// Read the contents of a file.
/// </summary>
/// <param name="fileName">The file to read.</param>
/// <returns>A string containing the contents of the file.</returns>
string ReadFileContents(string fileName);
/// <summary>
/// Write a string to a file, overwriting the file if it exists.
/// </summary>
/// <param name="fileName">The file to write to.</param>
/// <param name="contents">The string to write to the file.</param>
void WriteFileContents(string fileName, string contents);
/// <summary>
/// Delete a file.
/// </summary>
/// <param name="fileName">The file to delete.</param>
void DeleteFile(string fileName);
}
}
… and then an implementation.
using PCLStorage;
using System.Threading.Tasks;
namespace ArbitraryPixel.Common.SimpleFileSystem.PCLPortable
{
public class PCLStorageFileSystem : ISimpleFileSystem
{
public void DeleteFile(string fileName)
{
var t = Task.Run(
async () =>
{
var root = FileSystem.Current.LocalStorage;
var file = await root.GetFileAsync(fileName);
await file.DeleteAsync();
}
);
t.Wait();
}
public bool FileExists(string fileName)
{
var t = Task<bool>.Run(
async () =>
{
var root = FileSystem.Current.LocalStorage;
var result = await root.CheckExistsAsync(fileName);
return (result == ExistenceCheckResult.FileExists);
}
);
t.Wait();
return t.Result;
}
public bool FolderExists(string folderName)
{
var t = Task<bool>.Run(
async () =>
{
var root = FileSystem.Current.LocalStorage;
var result = await root.CheckExistsAsync(folderName);
return (result == ExistenceCheckResult.FolderExists);
}
);
t.Wait();
return t.Result;
}
public string ReadFileContents(string fileName)
{
var t = Task<string>.Run(
async () =>
{
var root = FileSystem.Current.LocalStorage;
var file = await root.GetFileAsync(fileName);
return await file.ReadAllTextAsync();
}
);
t.Wait();
return t.Result;
}
public void WriteFileContents(string fileName, string contents)
{
var t = Task.Run(
async () =>
{
var root = FileSystem.Current.LocalStorage;
var file = await root.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
await file.WriteAllTextAsync(contents);
}
);
t.Wait();
}
public void CreateFolder(string folderName)
{
var t = Task.Run(
async () =>
{
var root = FileSystem.Current.LocalStorage;
await root.CreateFolderAsync(folderName, CreationCollisionOption.FailIfExists);
}
);
t.Wait();
}
}
}
For the locations I wrote to, I used…
Windows:
_appStorageDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ArbitraryPixel", "CodeLogic");
Android:
_appStorageDir = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.ToString(), "ArbitraryPixel", "CodeLogic");
For Android in particular, you have to make sure you actually have storage permissions, so you can check this and then request it if you want to with this code…
#region Permission Check Methods
private const int REQUESTID_PERMISSION_STORAGE = 1;
private bool CheckStoragePermissions()
{
bool hasStoragePermissions = true
&& ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) == Permission.Granted
&& ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) == Permission.Granted
&& true;
return hasStoragePermissions;
}
private void RequestRequiredPermissions(bool hasStoragePermissions)
{
if (!hasStoragePermissions)
ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.WriteExternalStorage, Manifest.Permission.ReadExternalStorage }, REQUESTID_PERMISSION_STORAGE);
}
#endregion
Don’t worry about the extra true in the hasStoragePermissions
check, it was just a formatting style I was experimenting with at the time
Which I got from somewhere in the Android API documentation in 2018 when I wrote this. So there’s a real chance this might be somewhat out of date, but it’s what worked for me. I then just wrote and read json files for my configuration and data.
I hope that helps!