Akavache does not keep cache data between app restarts

advertisements

I've got a Xamarin Android project, using a shared PCL library, and I decided to use Akavache as a temporary data store (to store some simple login state info, to save relogging in every time).

So I added the Akavache and Akavache.Sqlite3 nuget packages to the Shared Library (and to the Xamarin.Android project). I set the BlobCache.ApplicationName, even called EnsureInitialized (tho that doesn't seem to do more than log a message).

I deployed the app to the device. Launched it manually (so there's no wiping of data and preferences etc.). Data is cached (and retrieved) as long as the app is running. It throws exceptions (as expected) if keys are missing. All works perfectly.

Then I shut the app down (at one stage I even rebooted the phone). When I relaunched it, the cache is either empty, or reinitialised. Either way, everything I cached is gone.

I had a look in the debugger at where the caching sqlite3 files are stored, and the app tells me they're apparently at data/data/packagename/cache/xyzblobs.db. I cannot see those files, because they're in an internal system cache/app files directory, so I have no idea whether they're being wiped or not.

I've turned on the WRITE_EXTERNAL_STORAGE (and READ_) permissions. No dice. I've tried using Secure, UserAccount and LocalMachine targets. Nada. None of them work.

As long as the app is running (or in memory) it behaves as expected. The moment the app goes away, so does the cache.

The only thing I haven't done is call the BlobStorage.Shutdown() method. And that's because I don't know where to call it. I have multiple activities and don't want to be reference counting because stupid.

Edit: Later I forced a call to .Shutdown().Wait() and that didn't seem to help either.

Has anyone else experienced this? I know of at least one other person who is having exactly the same problem, detailed in over here in the Xamarin forums.

I really don't want to have to pull all the Akavache stuff out, because I've used it before, elsewhere on not-Xamarin-Android, and it's awesome. Otherwise I'll have to start looking at some sort of xplat shared preferences manager, which I'd rather not do because Akavache is supposed to do Just That.

Edit: Here's some of the code:

Initialisation (I have a static shared "AppGlobal" class that I use to keep the singleton type stuff)

public static class SharedAppGlobal
{
  static SharedAppGlobal()
  {
    BlobCache.ApplicationName = SharedAppConstants.SharedAkavacheCacheName;
    BlobCache.EnsureInitialized();
  }
}

That all works fine, if I fire it up in the debugger and have a look at BlobCache it tells me I'm using the Sqlite3 storage and the path to it (tho the sqlite3 .db files are not accessible to me on a non-rooted device)

I can invoke the cache get/set with things like

currentCookie = await BlobCache.LocalMachine.GetObject<Cookie>("authCookie"); and write them back with

await BlobCache.LocalMachine.InsertObject("authCookie", cookie);

All Akavache calls are being made in the shared library. And it doesn't matter which store I use (Secure, UserAccount or LocalMachine), the behaviour is the same.

All works perfectly. Then I exit the app. Reopen the app (I can reboot the phone to make sure it's gone), and the cache is empty. Or reset. Or made anew. I don't know which because I can't see the .db files.

I am NOT running under a debugger and redeploying every time. So deployment directories aren't getting clobbered. This happens even when I install an apk. I think it probably has something to do with those db files not being where it says they are, but I'm at a complete loss.

Do I need to implement something at platform-specific level and pass it down to the shared library? I don't think so, because all the dependencies and paths seem to be resolved.

I've wasted hours on this.

Thanks :)


OK, I've found a workaround that fixes the problem for me.

I first tried to repro the problem so that someone else could take a look, and of course it worked perfectly in the new app. Colour me annoyed.

So then I tried manually instantiatiating an SQlitePersistentBlobCache, giving it a specific path to create the DB files at a path I can control and see using

GetExternalFilesDir(null).AbsolutePath + "test.db)

and that worked! The cache sticks around, even between reboots!

It still doesn't explain why I had the original problem, but right now this is an acceptable solution for me.

I've added a solution on github at https://github.com/wislon/xam-akavache-test .

The master branch uses the standard BlobCache static instance.

The instantiate-blobcache branch uses an instantiated SQlitePersistentBlobCache.

If anyone's curious, there it is. Unfortunately I can't spend more time on figuring out why the out-of-the-box static instance is doing what it's doing, because I have a product to build, but hopefully this helps someone else.