I've just had quite a struggle to package a medium sized database into my application in a way that will populate that database on the phone very quickly when the app first loads. But I'm victorious. I have read several posts from the past about people having the same problems, but they failed to post complete solutions. It would have saved me a lot of time. Here is the unified solution (as I see it). I welcome any input. I also have several questions at the end.
In the beginning, I wanted to simply pre-populate a database on android using a plain text file containing a single word on each line. I placed the file in the raw resource folder and set up my application to 1. set up a database with and empty table, and then 2. use a java.io.InputStreamReader to read line by line and run a SQL statement inserting each line of data into the database. The application crashed when I ran it and I got an error in my logcat: D/asset (909): Data exceeds UNCOMPRESS_DATA_MAX (1424000 vs 1048576) Turns out there is a file size limit of 1048576 bytes for resource files in raw and also in assets. So since it was just a text file, I split it into two files and ran the sequence twice, once on each file. It works great and the database populates perfectly. HOWEVER, it takes 5 minutes to insert 135,000 records. You can achieve slight speedup if you close the whole series of inserts in a single SQL transaction (first issue BEGIN TRANSACTION; then after the insert and update statements issue COMMIT TRANSACTION;). If you have a small database, this solution will work okay. But keep reading. There is a faster way. I couldn't deal with a 5 minute startup time on an app, so I decided to include the actual database file in my resource raw folder (others suggested this to me). (You can pull your existing database off of your emulator, if you happen to have gotten it on there as I did, using SQL statements and text files, by copying it off the phone from /data/data/com.yourdomain.applicationname/databases/applicationame.db using android debug bridge, or by creating one using sqlite3 on your desktop. Be sure to include the meta data table found in all android databases.) Then in my code, I built a method to create an empty database using the SQLiteOpenHelper--then immediately close it so I can overwrite the file. Then the method tries to open the included db file from raw resource as an input stream. But when I read from it, it thew an exception every time. The reason? The db file was too large. This took me forever to realize because the only exception was java.io.IOException, which isn't very informative. Finally, I decided to apply solution 1 again. That is, split the files. I used the linux split command to split the binary database file into a maximum of 1048576 bytes. The command is: split infile -b 1048576 outfileprefix and the files come out as outfileprefixaa, outfileprefixab, etc. I copied these files into my raw resource folder and set up my code to create and then close a database automatically using SQLiteOpenHelper and then to run the following method: private void copyDatabase() throws IOException{ OutputStream databaseOutputStream = new FileOutputStream("/data/data/com.domain.app/databases/app.db"); InputStream databaseInputStream; byte[] buffer = new byte[1024]; int length; databaseInputStream = databaseOpenHelperContext.getResources().openRawResource(R.raw.datafileaa); while ( (length = databaseInputStream.read(buffer)) > 0 ) { databaseOutputStream.write(buffer); } databaseInputStream.close(); databaseInputStream = databaseOpenHelperContext.getResources().openRawResource(R.raw.datafileab); while ( (length = databaseInputStream.read(buffer)) > 0 ) { databaseOutputStream.write(buffer); } databaseInputStream.close(); databaseInputStream = databaseOpenHelperContext.getResources().openRawResource(R.raw.datafileac); while ( (length = databaseInputStream.read(buffer)) > 0 ) { databaseOutputStream.write(buffer); } databaseInputStream.close(); databaseOutputStream.flush(); databaseOutputStream.close(); } This solution works perfectly. And it's very fast. My final database size on the emulator is 2714624 bytes (about 2.5 meg). It copies almost instantly. There is no delay when the application first runs. However, remember that the resource files remain installed, and you've copied the data to a database. This effectively doubles the data storage usage of the application. My questions are: 1. Why is there a file size limit on resources in the raw or assets folders (such a small limit, that is)? 2. Does this limit apply to all raw and asset files, or only to files that you get an input stream for? 2. Can I change the file size limit, or is it a fixed feature? 3. Is it appropriate to split a raw file into two or three files and read them in as three consecutive separate streams, all output to one file? Or is this a bad practice since they must have implemented a file size limit for storage conservation reasons? 4. Can I delete the resources from raw or assets at runtime (or is this totally invalid since the compiler sets up R.raw to have methods representing the files) to save space? 5. How big is too big an application? (mine is a large word dictionary and the whole app after first run takes 4 meg) I suppose a more space efficient model would be to offer the data online somewhere, especially for bigger databases, and load from there, and store the database on the SDCard, which requires you NOT use the SQLiteOpenHelper. Good luck to all you database pre-populators and I hope this helps. I welcome any input and correction to this document as I am no expert and may be doing something that isn't kosher in my code. Justin Jaynes --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to android-developers@googlegroups.com To unsubscribe from this group, send email to android-developers-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/android-developers?hl=en -~----------~----~----~----~------~----~------~--~---