Using files and the filesystem

Many apps require access to the filesystem for accessing databases, reading content, and many other reasons.

How to do it...

There are two main areas for storing files: internal storage and external storage. Making use of the internal storage or app sandbox is very easy:

  1. Writing files to the filesystem is very simple, and all that is required is the path to the sandbox for our app:
    string sandbox = FilesDir.AbsolutePath;
  2. Once we have this path, we can use the types from the .NET BCL to manipulate the files:
    string file = Path.Combine(sandbox, "myFile.txt");
    bool exists = File.Exists(file);
    File.WriteAllText(file, "this is my value");
    string value = File.ReadAllText(file);
  3. Sometimes, we only need to store files temporarily. In such cases, we can make use of the cache location:
    string cache = CacheDir.AbsolutePath;

Using the external storage only has a few extra requirements. Typically, the way external storage is used is the same as the way internal storage is used, except that we have a different root folder:

  1. If we wish to write to the external storage, we need to ask for permission to do so:
    [assembly: UsesPermission(
Manifest.Permission.WriteExternalStorage)]
    [assembly: UsesPermission(Manifest.Permission.ReadExternalStorage)]
  2. Once we have the permission to access the filesystem, we will verify that the external media is attached and writeable:
    bool writeable = Android.OS.Environment.ExternalStorageState == Android.OS.Environment.MediaMounted;
    
    bool readable = writeable || Android.OS.Environment.ExternalStorageState == Android.OS.Environment.MediaMountedReadOnly;
  3. We can obtain the path to the external location and then work as we would with the internal storage filesystem:
    string external = GetExternalFilesDir(null).AbsolutePath; 
    string externalCache = ExternalCacheDir.AbsolutePath;
  4. There are also a few extra external locations, such as the public directories. This is where Android places and reads files from things such as music, movies, and downloads:
    string downloadsDir = Android.OS.Environment.GetExternalStoragePublicDirectory(
        Android.OS.Environment.DirectoryDownloads)
        .AbsolutePath;
  5. We can also see how much space or free space is available by querying the file location:
    long freeSpace = FilesDir.FreeSpace;
    long totalSpace = GetExternalFilesDir(null).TotalSpace;

How it works...

Working with the Android filesystem is similar to using the file systems on any .NET-supported platform. We can make use of all the features in .NET, as well as many of the Java features. However, Android does not allow access to all file locations on the device, especially the system locations or other app sandboxes.

Usually an app will access its own internal sandbox location obtained from FilesDir and possibly the app cache location obtained from CacheDir. Files saved to the internal storage are private to our app and neither other apps nor the user can access them.

When the user uninstalls our app, the internal files are removed automatically. In addition, the user may remove them through the device settings screens. As a result, we must first check whether a file exists before trying to read it.

Tip

Files saved to the files and cache directories are deleted, and not preserved in any way, when the app is uninstalled.

Access to the external storage is no different but requires app permissions. Starting from Android 4.4, these permissions are not required if the only external access is through the GetExternalFilesDir() method and the ExternalCacheDir property. External files are visible to the user, especially if the files connect it to a computer as a USB mass storage device.

Files saved to the cache, whether internal via CacheDir or external via ExternalCacheDir, are meant to be temporary. Android may delete these files when the device starts to run out of free space or if the app is uninstalled. However, we should not rely on the system to clean up these files and maintain the cache ourselves.

It is very important to remember that external storage may become unavailable if the user mounts the external storage on a computer or removes the media. As a result, it is essential to check the availability of the external storage before use. In the Android.OS namespace, the Environment type contains the properties, methods, and other types used to determine the state of the external storage. The ExternalStorageState property may be MediaMounted, which is writeable, or MediaMountedReadOnly, which is read only.

Tip

External storage mediums are not always available and access should be verified before being used.

There are special public locations that are used by Android to hold the user's downloads—photos, music, and other files. These locations are obtained by passing the desired directory constant to the GetExternalStoragePublicDirectory() method on Environment.

We can see how much free space is available by using the FreeSpace or TotalSpace properties on the Java File objects, such as the result from the FilesDir property. The values returned aren't the exact space available, but a representation of how much free space can be available. If there is a few extra MB over the size to be saved, then it is probably OK to continue.

There's more...

The external storage may not actually be the SD card but rather a section of the device's internal memory marked as external.

The actual SD card can be accessed using the result of GetExternalFilesDirs() or ContextCompat.GetExternalFilesDir(), which is an array of the external storage mediums available, one of which will be the actual SD card. Similarly for the cache, the locations are found in the result of GetExternalCacheDir() or ContextCompat.GetExternalCacheDir().

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset