Android Integration

The SQLite library is a core part of the Android environment. Java applications and content providers access SQLite using the interface in the android.database.sqlite namespace.

TheAndroid SQLite Bindings Project can be used to build a custom (encrypted) version of SQLite integrated into an application that requires no change of source code; it still uses the standard Java interface.

Installation

Android API levels 15 (Android 4.0.3) and greater are supported.

Copy the following files from the Android Bindings project into the equivalent locations in the application project.

jni/Android.mk
jni/Application.mk
jni/sqlite/* (copy contents of directory recursively)
src/org/sqlite/database/* (copy contents of directory recursively)

Following this, the directory structures should contain these files.

For API level 15 only, also copy the following:

src/org/sqlite/os/* (copy contents of directory recursively)

Directory "jni/sqlite/" contains copies of the sqlite3.h and sqlite3.c source files. Between them, they contain the source code for the SQLite library. For a custom encrypted SQLite database, replace these with the source. If SQLite is to be compiled with any special pre-processor macros defined, add them to the "jni/sqlite/Android.mk" file (not jni/Android.mk).

Once the files have been added to the project, run the command "ndk-build" in the root directory of the project. This compiles the native code in the jni/ directory (including the custom SQLite version) to shared libraries that will be deployed to the device along with the application. Assuming it is successful, unless you modify the sources or makefiles within the jni/ directory structure, you should not need to run "ndk-build" again.

Application Programming

Before using any SQLite related methods or objects, the shared library compiled using the ndk must be loaded into the application using the following code:

System.loadLibrary("sqliteX");

One way to ensure that the shared library is loaded early enough is to add it to a "static" block within the declaration of the application's main Activity class.

The classes that make up the built-in Android SQLite interface reside in the android.database.sqlite namespace. This interface provides all of the same classes, except within the org.sqlite.database.sqlite namespace. This means that to modify an application to use the custom version of SQLite, all that is usually required is to replace all occurrences android.database.sqlite within the source code with org.sqlite.database.sqlite. For example, the following:

app program 1

 

  

As well as replacing all uses of the classes in the android.database.sqlite.* namespace, the application must also be sure to use the following two:

app program 2

 

 

 

Aside from namespace changes, there are other differences from the stock Android interface that applications need to be aware of:

  • The SQLiteStatement.simpleQueryForBlobFileDescriptor() API is not available.
  • The collation sequence "UNICODE" is not available.
  • The collation sequence "LOCALIZED", which normally changes with the system's current locale, is always equivalent to SQLite's built in collation BINARY.

 

Example SQLite Binding (The SQLite Encryption Extension - SEE)

  1. 1. replace the sqlite3.c file at "jni/sqlite/sqlite3.c” (i.e. the concatenation of sqlite3.c and see.c). 
  2. 2. open the file jni/sqlite/Android.mk and locate the following two lines:
  • # If using SEE, uncomment the following:
  • # LOCAL_CFLAGS += -DSQLITE_HAS_CODEC
  • Uncomment the second of them, then run "ndk-build" as described above to generate the shared libraries.

After opening or creating an encrypted database, the application must immediately execute a PRAGMA to configure the encryption key. This must be done before any other database methods are called. For example:

android 1

 

 

 

 

Or, if you are using the SQLiteOpenHelper helper class, the PRAGMA must be the first thing executed within the onConfigure() callback. For example:

android 2