216 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			216 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| <h1> 
 | |
| SQLite Android Bindings 
 | |
| </h1>
 | |
| 
 | |
| <p> The SQLite library is a core part of the Android environment. Java
 | |
| applications and content providers access SQLite using the interface in
 | |
| the 
 | |
| <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html">android.database.sqlite</a> namespace.
 | |
| 
 | |
| <p> One disadvantage of using Android's built-in SQLite support is that the
 | |
| application is forced to use the version of SQLite that the current version of
 | |
| Android happened to ship with. If your application happens to require a newer
 | |
| version of SQLite, or a build with a custom extension or 
 | |
| <a href=http://www.sqlite.org/vfs.html>VFS</a> installed, you're out of luck.
 | |
| 
 | |
| <p>The code in this project allows an application to use the 
 | |
| <a href=http://developer.android.com/tools/sdk/ndk/index.html>Android NDK</a>
 | |
| to build a custom version of SQLite to be shipped with the application while
 | |
| still continuing to use the standard Java interface.
 | |
| 
 | |
| <h2>Normal Usage</h2>
 | |
| 
 | |
| <h3>Installation</h3>
 | |
| 
 | |
| <p>
 | |
|   Android API levels 15 (Android 4.0.3) and greater are supported. If
 | |
|   targetting API level 16 or greater, use the default "trunk" branch of this
 | |
|   project. Or, for API level 15, use the "api-level-15" branch. It is not possible
 | |
|   to target an API level lower than 15.
 | |
| 
 | |
| <p>
 | |
|   Copy the following files from this project into the equivalent locations in
 | |
|   the application project.
 | |
| 
 | |
| <pre>
 | |
|     jni/Android.mk
 | |
|     jni/Application.mk
 | |
|     jni/sqlite/*                       (copy contents of directory recursively)
 | |
|     src/org/sqlite/database/*          (copy contents of directory recursively)
 | |
| </pre>
 | |
| 
 | |
| <p>
 | |
|   Following this, the directory structures should contain 
 | |
|   [/tree?ci=trunk&re=%5ejni%7csrc/org/sqlite/data&expand | these files].
 | |
| 
 | |
| <p>
 | |
|   For API level 15 only, also copy the following:
 | |
| 
 | |
| <pre>
 | |
|     src/org/sqlite/os/*                (copy contents of directory recursively)
 | |
| </pre>
 | |
| 
 | |
| <p>
 | |
|   Directory "jni/sqlite/" contains copies of the sqlite3.h and sqlite3.c 
 | |
|   source files. Between them, they contain the
 | |
|   <a href=http://www.sqlite.org/amalgamation.html>source code for the SQLite
 | |
|   library</a>. If necessary, replace these with the source for the specific 
 | |
|   version of SQLite required. 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).
 | |
| 
 | |
| <p>
 | |
|   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.
 | |
| 
 | |
| <h3>Application Programming</h3>
 | |
| 
 | |
| <p>
 | |
|   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:
 | |
| 
 | |
| <verbatim>
 | |
|   System.loadLibrary("sqliteX");
 | |
| </verbatim>
 | |
| 
 | |
| <p>
 | |
|   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.
 | |
| 
 | |
| <p>
 | |
|   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:
 | |
| 
 | |
| <verbatim>
 | |
|   import android.database.sqlite.SQLiteDatabase;
 | |
| </verbatim>
 | |
| 
 | |
| <p>should be replaced with:
 | |
| 
 | |
| <verbatim>
 | |
|   import org.sqlite.database.sqlite.SQLiteDatabase;
 | |
| </verbatim>
 | |
| 
 | |
| <p>
 | |
|   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:
 | |
| 
 | |
| <verbatim>
 | |
|   org.sqlite.database.SQLException
 | |
|   org.sqlite.database.DatabaseErrorHandler
 | |
| </verbatim>
 | |
| 
 | |
| <p>instead of:
 | |
| 
 | |
| <verbatim>
 | |
|   android.database.SQLException
 | |
|   android.database.DatabaseErrorHandler
 | |
| </verbatim>
 | |
|   
 | |
| <p>Aside from namespace changes, there are other differences from the
 | |
| stock Android interface that applications need to be aware of:
 | |
| 
 | |
| <ol>
 | |
|   <li> The SQLiteStatement.<a href="http://developer.android.com/reference/android/database/sqlite/SQLiteStatement.html#simpleQueryForBlobFileDescriptor()">simpleQueryForBlobFileDescriptor()</a> 
 | |
|        API is not available.
 | |
| 
 | |
|   <li> The collation sequence "UNICODE" is not available.
 | |
| 
 | |
|   <li> The collation sequence "LOCALIZED", which normally changes with the 
 | |
|        system's current locale, is always equivalent to SQLite's built
 | |
|        in collation BINARY.
 | |
| </ol>
 | |
| 
 | |
| 
 | |
| <h2>Using The SQLite Encryption Extension</h2>
 | |
| 
 | |
| <p>
 | |
|   To use the <a href=http://www.sqlite.org/see/doc/trunk/www/readme.wiki>
 | |
|   SQLite Encryption Extension</a> (SEE) on Android, replace the sqlite3.c
 | |
|   file at "jni/sqlite/sqlite3.c" with a SEE-enabled version (i.e. the
 | |
|   concatenation of sqlite3.c and see.c - refer to the link above for
 | |
|   details). Next, open the file jni/sqlite/Android.mk and locate the
 | |
|   following two lines:
 | |
| 
 | |
| <verbatim>
 | |
|   # If using SEE, uncomment the following:
 | |
|   # LOCAL_CFLAGS += -DSQLITE_HAS_CODEC
 | |
| </verbatim>
 | |
| 
 | |
| <p>
 | |
|   Uncomment the second of them, then run "ndk-build" as described above to
 | |
|   generate the shared libraries. 
 | |
| 
 | |
| <p>
 | |
|   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:
 | |
| 
 | |
| <verbatim>
 | |
|   import org.sqlite.database.sqlite.SQLiteDatabase;
 | |
| 
 | |
|     ...
 | |
| 
 | |
|   SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase("my.db", null);
 | |
|   db.execSQL("PRAGMA key = 'secretkey'");
 | |
| </verbatim>
 | |
| 
 | |
| <p>
 | |
|   Or, if you are using the
 | |
|   <a href=http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html>SQLiteOpenHelper</a>
 | |
|   helper class, the PRAGMA must be the first thing executed within the
 | |
|   onConfigure() callback. For example:
 | |
| 
 | |
| <verbatim>
 | |
|   import org.sqlite.database.sqlite.SQLiteDatabase;
 | |
|   import org.sqlite.database.sqlite.SQLiteHelper;
 | |
| 
 | |
|     ...
 | |
| 
 | |
|   class MyHelper extends SQLiteOpenHelper {
 | |
|     ...
 | |
|     void onConfigure(SQLiteDatabase db){
 | |
|       db.execSQL("PRAGMA key = 'secretkey'");
 | |
|     }
 | |
|     ...
 | |
|   }
 | |
| </verbatim>
 | |
| 
 | |
| <p>
 | |
|   Refer to the <a href=http://www.sqlite.org/see/doc/trunk/www/readme.wiki>
 | |
|   SEE documentation</a> for further details regarding encryption keys.
 | |
| 
 | |
| <p>Aside from supporting encrypted databases, SEE-enabled builds behave
 | |
| differently in two more respects:
 | |
| 
 | |
| <ol>
 | |
|   <li> <p>The SQLiteDatabase.<a href="http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#enableWriteAheadLogging()">enableWriteAheadLogging()</a> method does not enable
 | |
|        connection pooling. It is not possible for connection pooling to be
 | |
|        used with a SEE-enabled build (even if the database is unencrypted).
 | |
| 
 | |
|   <li> <p>In Android, if database corruption is encountered, or if an attempt is
 | |
|        made to open a file that is not an SQLite database, the default
 | |
|        behaviour is to delete the file and create an empty database file in 
 | |
|        its place. In a SEE-enabled build, the default behaviour is to throw
 | |
|        an exception.<br><br>
 | |
|        The reason for this is that supplying an incorrect encryption key
 | |
|        is indistinguishable from opening a file that is not a database file.
 | |
|        And it seems too dangerous to simply delete the file in this case.
 | |
|        <br><br>
 | |
|        The default behaviour can be overriden using the
 | |
|        <a href="http://developer.android.com/reference/android/database/DatabaseErrorHandler.html">DatabaseErrorHandler</a> interface.
 | |
| 
 | |
| </ol>
 |