Unable to clear App cache in Xamarin.Forms Android

62 Views Asked by At

I am trying to clear/delete app cache folder of my Xamarin.Forms Android app. I have tried different approaches, but the folder still is not getting cleared.

What I have done:

I am calling this class through an interface. But no matter what I do, the cache folder keeps having data in it.

namespace MyApp.Droid.Services
{
    public class CacheClearService: ICacheClearService
    {
        public async Task ClearCacheAsync()
        {
            try
            {
                var cacheDir = Android.App.Application.Context.CacheDir;
                deleteDir(cacheDir);
                await Task.CompletedTask;
            }
            catch (Exception ex)
            {

            }
        }

        public  static bool deleteDir(File dir)
        {
            if (dir != null && dir.IsDirectory)
            {
                string[] children = dir.List();
                for (int i = 0; i < children.Length; i++)
                {
                    bool success= deleteDir(new File(dir, children[i]));
                    if (!success)
                    {
                        return false;
                    }
                }
                return dir.Delete();
            }
            else if (dir != null && dir.IsFile)
            {
                return dir.Delete();
            }
            else
            {
                return false;
            }
        }

    }
}

I have added permissions like WRITE_EXTERNAL_STORAGE and MANAGE_EXTERNAL_STORAGE. What am I missing here? Any help is appreciated

1

There are 1 best solutions below

6
Julian On BEST ANSWER

There are a few issues and things to consider here.

1. Permissions

First of all, you don't need the WRITE_EXTERNAL_STORAGE and MANAGE_EXTERNAL_STORAGE permissions to read and write your app's private cache and app data folders.

2. Use file system helpers

To obtain the path of your app's cache directory, you could simply use the file system helpers of the Xamarin.Essentials package/namespace:

using Xamarin.Essentials;

namespace MyApp.Droid.Services
{
    public class CacheClearService : ICacheClearService
    {
        public async Task ClearCacheAsync()
        {
            try
            {
                var cacheDir = FileSystem.CacheDirectory;

                // skipped for brevity
            }
            catch (Exception ex)
            {
            }
        }

        // skipped for brevity
    }
}

3. Simplify deletion code

Your deletion code can be simplified. You can use the Directory.Delete(string path, bool recursive) method instead by passing the path and true as the second argument to delete files and subfolders similar to how it's done in Recursive delete of files and directories in C#:

private static void DeleteDir(string dir)
{
    foreach (string subDir in Directory.GetDirectories(dir))
    {
        DeleteDir(subDir);
    }
    Directory.Delete(dir, true);
}

4. async/await

Last but not least, your interface seems to require you to implement the method that clears the cache as an awaitable Task. However, in your implementation, you don't perform any asynchronous calls except for awaing the Task.CompletedTask, which returns immediately, because it's always in its completed state.

Instead, you could wrap your blocking code (deleting files and folders may take a while) in a Task.Run() statement, which can then be awaited:

public async Task ClearCacheAsync()
{
    try
    {
        await Task.Run(() =>
        {
            var cacheDir = FileSystem.CacheDirectory;
            DeleteDir(cacheDir);
        });
    }
    catch (Exception ex)
    {
        //maybe log the exception here?
    }
}

5. Bringing it all together

namespace MyApp.Droid.Services
{
    public class CacheClearService : ICacheClearService
    {
        public async Task ClearCacheAsync()
        {
            try
            {
                await Task.Run(() =>
                {
                    var cacheDir = FileSystem.CacheDirectory;
                    DeleteDir(cacheDir);
                });
            }
            catch (Exception ex)
            {
                //maybe log the exception here?
            }
        }

        private static void DeleteDir(string dir)
        {
            foreach (string subDir in Directory.GetDirectories(dir))
            {
                DeleteDir(subDir);
            }
            Directory.Delete(dir, true);
        }
    }
}

Note: This should work on both Android and iOS.