I am using Azure Mobile services for mobile offline sync in Xamarin Forms app. I am also trying to use Akavache to store user specific settings and cache that is only to be saved on that device and doesn't need to be synced to cloud.
If used separately, my azure client works well, I get data synced no problems. Same for Akavache, when used without azure mobile sync, I can easily save and retrieve my local data. However, there is an issue when used together. As soon as I make a call to any azure client sync functions (i.e. pullasync or pushasync) and then try to use Akavache later in the app, it fails silently and application crashes. I am getting SIGSEGV error in my output with no stacktrace.
I have a feeling it is somehow related to Azure Client and Akavache using same static SQLite connection object or something similar. Any pointers here?
Here is what I get in output
critical: at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object) [0x00031] in /Users/builder/data/lanes/3969/44931ae8/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:893
2016-12-07 19:49:25.354 BrixnMobileUIiOS[52036:14315387] critical: at System.Threading.ThreadHelper.ThreadStart (object) [0x00012] in /Users/builder/data/lanes/3969/44931ae8/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/thread.cs:87
2016-12-07 19:49:25.354 BrixnMobileUIiOS[52036:14315387] critical: at (wrapper runtime-invoke) .runtime_invoke_void__this___object (object,intptr,intptr,intptr) <IL 0x00053, 0x00310>
2016-12-07 19:49:25.354 BrixnMobileUIiOS[52036:14315387] critical:
FreezeProvider. experimental feature to possibly help with akavache/A…
…kavache#332 and Azure/azure-mobile-apps-net-client#266
Sister issue is akavache/Akavache#332 -- more discussion is happening there.
What all do you need to store in akavache? I could see them competing perhaps... Can you just store it in shared preferences? https://github.com/jamesmontemagno/SettingsPlugin
Regardless of whether SettingsPlugin or Akavache is a better fit, SQLitePCL.raw must be reliable in situations like these (where an app has a dependency on multiple libraries which have dependencies on SQLitePCL.raw), and if the OP has found a problem along those lines, I will address it.
@jamesmontemagno thanks for suggestion. I could give you multiple reasons why I would prefer Akavache, I could also use just Application.Current.Properties dictionary in Xamarin.Forms (which is what I am actually using now as I can't get Akavache to work). But as Eric mentioned, it is not about which library is better, it is the fact that two libraries that rely on SQLite lite should be able to coexist
Agreed - @ericsink - if there are changes we need to make, let us know or send us a PR. I'm happy to update to make this more reliable. I'll watch the Akavache issue as well.
@ericsink is there a way to tell if Batteries.Init() has already been called? I am using an internal var to hold it for Azure Mobile Apps so I don't call Batteries.Init() twice (here), but I'd rather just use the appropriate API?
No, there is no way to ask if Batteries.Init() has already been called. And there are good reasons why not, but I will spare you the details. So your code looks fine. It is still true that you should not call Batteries.Init() twice, which can be done by using a static constructor, or by the technique you're using to keep track of whether you already called it.
The real fix for the broader problem of difficulty with multiple libraries, as described in the Akavache sister issue, is for SQLitePCL.raw to provide the FreezeProvider() call, allowing an app to do the initialization and freeze it, so that subsequent calls will be ignored. That is in my 1.1.2 release, coming soon. I plan to write up some docs on when and how this should be used. For now, note that your library should not call FreezeProvider(). It should never be called by a library. Only by an app.
The only change I would suggest you make is to call the newer Batteries_V2.Init() instead of Batteries.Init(). They both do exactly the same thing, but the V2 version lives in an assembly of the same name in all bundles, so it supports bait-and-switch across bundle types.
SQLitePCL.raw 1.1.2 has been pushed to nuget.org.
The docs on FreezeProvider() are here:
Great - thanks @ericsink - we'll update and release as well.