Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to obtain read-only access to an sqlite database in an apk? [duplicate]

Tags:

android

sqlite

Possible Duplicate:
How to put existing database in the .apk file?

Is it possible to obtain read-only access to an sqlite database located with an apk? I don't want to duplicate the database if it is possible to access it for read-only purposes from within the apk.

like image 344
gonzobrains Avatar asked May 03 '11 18:05

gonzobrains


3 Answers

I've just started developing for Android, and was surprised to discover that bundling a static database is not easy to do. So I did the only reasonable thing: created a library which does just that.

android-staticdb is an Android library to allow read-only access to SQLite databases contained in an application's .apk file. This is ideal for apps which need to ship with a large quantity of static data (e.g. an offline Wikipedia reader).

It works by registering a new "virtual filesystem" layer with the SQLite library from native C code, which is able to intercept the filesystem calls made by SQLite. Because there is only one copy of the SQLite library per VM process, we actually end up intercepting any SQLite calls made by any application in the same process as us!

In normal operation, our VFS layer simply proxies all calls to the "default" VFS, which just uses open() and read() to access regular database files. But when a special filename matching the *.apk!filename pattern is encountered, our VFS grabs control. Using zlib and minizip, it opens the .apk file and looks inside for the database file; it will then read chunks of this file to satisfy any read() requests from SQLite.

By doing this in this manner, applications can continue to use the standard Android database APIs.

Example usage:

import android.database.sqlite.SQLiteDatabase;
import kiwidrew.staticdb.StaticDatabase;

public class BlahBlah extends Activity {
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    SQLiteDatabase db = StaticDatabase.openDatabase(this, "assets/foobar.db");
    // Do normal database stuff with 'db'...
  }
}

You get back a standard SQLiteDatabase object, with the only restriction being that it doesn't support writing. (Obviously!)

Note that this will fail unless the database is stored in your .apk without compression. Add the SQLite database using the aapt -0 command or modify your build.xml to pass the <nocompress extension="db" /> flag to the <aapt> tag...

Note:

I've literally just finished writing this, and have only done very basic testing so far. Bug reports would be appreciated.

like image 81
kiwidrew Avatar answered Oct 16 '22 15:10

kiwidrew


As mentioned in this answer Load files bigger than 1M from assets folder

If the asset is uncompressed, the system can memory-map the file data and use the Linux virtual memory paging system to pull in or discard 4K chunks as appropriate.

If that's true, one could store uncompressed database to APK (using some of extensions like mp3 to keep file uncopressed) and read it directly from APK. That's only my speculations, I'm not really sure about implementation though.

For Android 2.3 and newer you could use Native Access using NDK http://groups.google.com/group/android-ndk/browse_thread/thread/30b9f5abf48347a0/ef62db9a18646b1d .

like image 43
joshas Avatar answered Oct 16 '22 16:10

joshas


No, the apk must have an interface for you to pull data - which can be exposed with an Android service.

To my knowledge, Android is a Linux distribution where each .apk is installed as/by a separate user account, none of which are root. Therefore, the application spaces are effectively partitioned.

like image 1
tpow Avatar answered Oct 16 '22 15:10

tpow