-
-
Notifications
You must be signed in to change notification settings - Fork 121
SQLitePCL.Batteries.Init
An initialization function provided by SQLitePCL.raw's bundle packages.
A bundle package is a meta-package that does two things:
- Use nuget dependencies to bring in other packages as needed for the platform. These include a SQLitePCLRaw.provider package, and if needed, one or more SQLitePCLRaw.lib packages.
- Provide the
SQLitePCL.Batteries.Init()
function to get things properly configured for that platform.
Bundle packages have ids that start with SQLitePCLRaw.bundle_
. For example:
- SQLitePCLRaw.bundle_e_sqlite3
- SQLitePCLRaw.bundle_sqlcipher
- SQLitePCLRaw.bundle_green
Each bundle package has a different policy about which instance of the native SQLite library is being used. The name reflects that policy.
- bundle_e_sqlite3 always brings in e_sqlite3, a native SQLite library which is built specifically for SQLitePCL.raw users.
- bundle_sqlcipher brings in the appropriate platform build of sqlcipher, a variant of SQLite with support for encryption. The sqlcipher builds are maintained by Couchbase.
- bundle_green is just like bundle_e_sqlite3, except that on iOS, it uses the SQLite library provided by iOS.
Each one contains an implementation of ISQLite3Provider.
It is the even-lower-level interface that SQLitePCL.raw uses to talk to the native SQLite library.
The ISQLite3Provider abstraction hides the details of how the native code is called. The pinvoke/DllImport code exists inside the implementation of ISQLite3Provider, not in the main assembly. And since Silverlight platforms do not support DllImport, Windows Phone 8.0 has an implementation of ISQLite3Provider which is completely different, using C++/CLI instead.
The main SQLitePCL.raw assembly does not contain any implementations of ISQLite3Provider. An implementation must be injected by calling SQLitePCL.raw.SetProvider().
It calls SQLitePCLRaw.SetProvider() to inject an instance of ISQLite3Provider, which tells SQLitePCL.raw how to talk to a specific instance of the native SQLite3 library.
From platform-specific code. For example:
- On iOS, you might call it from the FinishedLaunching() method of your AppDelegate class.
- On Android, you might call it from somewhere in your MainApplication or MainActivity class.
- In an MvvmCross app, you might call it from InitializeFirstChance().
- etc
No. The initialization is platform-specific, by its very nature.
My library depends on SQLitePCL.raw. How do I spare users of my library from the need to call SQLitePCL.Batteries.Init()?
If your library already has platform packages and a platform initialization function of some kind:
- From your platform packages, take a dep on SQLitePCLRaw.bundle_whatever
- In your platform initialization function, call SQLitePCLRaw.Batteries.Init()
Well, you could add such things. But it might be kinda sad to add all that stuff just to do SQLite initialization. Especially because your library users STILL have to:
- Add a package to their app project
- Call an init function
You are simply renaming the package and the init function.
Then your library users will need to do so.
If no implementation of ISQLite3Provider is injected, all operations will throw an exception which attempts to explain what needs to be done. At the time of this writing, that message says:
You need to call SQLitePCL.raw.SetProvider(). If you are using a bundle package, this is done by calling SQLitePCL.Batteries.Init().
I may change this error message to improve it. I am also considering allowing it to be customized, so that libraries can provide more specific instructions.
It allows them to choose which bundle they want to use. More to the point, they could choose SQLitePCLRaw.bundle_sqlcipher if they want.
Maybe your library wants to use SQLite as merely an implementation detail that is not visible to users.
Yep.
Not anymore. Android N disallows this.
In other words, if your library supports Android and wants to use SQLite, even as a hidden implementation detail, your library's users will somehow have to bundle a SQLite library into their app.
Taking away flexibility in this area would definitely make things simpler, and would probably eliminate the need for an initialization call, but requests for that flexibility have been very common. Lots of people ask me how they can substitute sqlcipher, or a custom SQLite build, and so on.
Maybe you could just bundle several ISQLite3Provider implementations into the main assembly and call them all in a certain order and use the first one that works?
I tried that. Some AOT-based implementations choke if the app contains DllImport calls that are unresolved. Windows Universal 8.0 apps were failing store validation because of SQLitePCL.raw. As AOT gets more common in the .NET world, I expect more such problems.