Monday, August 29, 2011

Prepopulate SQLite DataBase in PhoneGap Application

It is really hard to wait for too much time when a phonegap application runs for first time and create all its database stuff, which gives a really bad impression to the user who just downloaded the app for its iPhone or Android device. I have a little approach to save the long time taken for database creation at very first run of the app, that is; we should copy a Pre-Populated Database file to the native location of device.

You can create a basic database for app with the help of tools like SQLite Database Browser or if you already have a database in your app you can directly get the database files (you need Databases.db and file__0/0000000000000001.db files) from the following ways:


In case of Android: in File Explore(in Eclipse) go to  data > data > [YOUR APP NAME] > app_database


In case of iOS: go to Finder (in MAC) go to Library > Application Support > iPhone Simulator > [YOUR SIMULATOR VERSION] > Applications > [YOUR UNIQUE APP ID] > Library > WebKit > Databases

NOTE: for iOS and Android apps both of files are same we don't need to grab both files for same phonegap apps.


With these files all what you need to do is; just put them in to bundle of app that is assets folder in case of Android and Root folder in case of iOS.
in Eclipse: in XCode:


Now you have to copy the files at the native location of application at the time of first boot of application, and make sure that the files should copy before your very first SQLite query. To copy these files you can use the following code snippet based on your environment. JAVA (Android)
//Use this code in your bootstrapping steps like in onCreate()
        try
     {
         String pName = this.getClass().getPackage().getName();
         this.copy("Databases.db","/data/data/"+pName+"/app_database/");
   this.copy("0000000000000001.db","/data/data/"+pName+"/app_database/file__0/");
 }
     catch (IOException e)
 {
  e.printStackTrace();
 }


        //Copy Paste this function in the class where you used above part
 void copy(String file, String folder) throws IOException 
 {

  File CheckDirectory;
  CheckDirectory = new File(folder);
  if (!CheckDirectory.exists())
  { 
   CheckDirectory.mkdir();
  }

     InputStream in = getApplicationContext().getAssets().open(file);
     OutputStream out = new FileOutputStream(folder+file);

     // Transfer bytes from in to out
     byte[] buf = new byte[1024];
     int len; while ((len = in.read(buf)) > 0) out.write(buf, 0, len);
     in.close(); out.close();
     
 }


Objective C (iOS)
//For PhoneGapDelegate.m
- (void)webViewDidStartLoad:(UIWebView *)theWebView 
{
 NSString *databaseName = @"0000000000000001.db";
 NSString *masterName = @"Databases.db"; 
 
 NSArray *libraryPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
 NSString *libraryDir = [libraryPaths objectAtIndex:0];
 
 NSString *masterPath = [libraryDir stringByAppendingPathComponent:@"WebKit/Databases/"];
 NSString *databasePath = [libraryDir stringByAppendingPathComponent:@"WebKit/Databases/file__0/"];
 NSString *masterFile = [masterPath stringByAppendingPathComponent:masterName];
 NSString *databaseFile = [databasePath stringByAppendingPathComponent:databaseName];

 BOOL success;
 NSFileManager *fileManager = [NSFileManager defaultManager];
 
 success = [fileManager fileExistsAtPath:databasePath];
 if(success) return;
 
 NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
 NSString *masterPathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:masterName];
 
 [fileManager createDirectoryAtPath:databasePath withIntermediateDirectories:YES attributes:nil error:NULL];
 [fileManager copyItemAtPath:databasePathFromApp toPath:databaseFile error:nil];
 [fileManager copyItemAtPath:masterPathFromApp toPath:masterFile error:nil];
 [fileManager release];
}

21 comments:

  1. hi,

    so, how do we execute opening a SQLite Db in our js files?

    ReplyDelete
  2. hello,

    could you please help me in showing how to access Sqlite in your js file? tnx

    ReplyDelete
  3. can you please show us your html file as well. I keep getting sqlite error that says cannot open the file.

    ReplyDelete
  4. I use your method but I keep getting sqlite error that cannot open file. Can you please show your javascript code as well? thanks

    ReplyDelete
  5. Hi Gaurav, I have a problem. I have pre-populated a .db file thru android native code. I have renamed the db file as 0000000000000001.db. I have placed this file and Databases.db under my Assets folder. Now when I am copying these 2 files to "data/data/"+pName+"/app_database/file__0/" folder, Phonegap is unable to find this file. And a new file is creatd each time Phonegap application loads. the name of this file is 0000000000000002.db in the same folder and it is a blank database.
    So am I missing something? or did I do something wrong.

    regards
    santu ghosh

    ReplyDelete
  6. Hi Gaurav, I have a problem. I have pre-populated a .db file thru android native code. I have renamed the db file as 0000000000000001.db. I have placed this file and Databases.db under my Assets folder. Now when I am copying these 2 files to "data/data/"+pName+"/app_database/file__0/" folder, Phonegap is unable to find this file. And a new file is creatd each time Phonegap application loads. the name of this file is 0000000000000002.db in the same folder and it is a blank database.
    So am I missing something? or did I do something wrong.

    regards
    santu ghosh

    ReplyDelete
  7. Santu. I think you need to copy DB files to the different filders.

    this.copy("Databases.db","/data/data/"+pName+"/app_database/");

    but

    this.copy("0000000000000001.db","/data/data/"+pName+"/app_database/file__0/");

    ReplyDelete
    Replies
    1. Please tell the steps to convert a native DB file to PhoneGap like style(0000000000000001.db and Databases.db)?

      Delete
  8. Please tell the steps to convert the native Android DB file to phonegap like style(0000000000000001.db and Databases.db)?

    ReplyDelete
  9. thanks gaurav for writing this post. its really very useful. keep it up.

    ReplyDelete
  10. Dear Gaurav,

    I am having prepopulated database in SQLITE
    When I am Pushing it to Device, I can see it in File Explorer.
    But, I am not getting how to use this pushed database in javascript code.
    Whenever I am using
    window.openDatabase("DBName", "1.0", "New DB Demo", 200000);

    It creates new databse with the name app_database:DBName

    Any idea about why this is happening?

    Thanks,
    Amol

    ReplyDelete
  11. Dear Gaurav,

    I am having prepopulated database in SQLITE
    When I am Pushing it to Device, I can see it in File Explorer.
    But, I am not getting how to use this pushed database in javascript code.
    Whenever I am using
    window.openDatabase("DBName", "1.0", "New DB Demo", 200000);

    It creates new databse with the name app_database:DBName

    Any idea about why this is happening?

    Thanks,
    Amol

    ReplyDelete
  12. Hi Gaurav, This article is very useful but now i have a problem. I have being developed phonegap application for iOS that is used pre populated .db file. This solution is working fine for below iOS 5.1. But I upgraded to IOS 5.1 , this solution does not to work.
    Can you give me a solution for that. I am stuck now.
    Thank you

    ReplyDelete
  13. Hi Gaurav!

    Thank you very much for share useful code. I have a question, how I can add rows and save in the Prepopulate database?

    ReplyDelete
  14. Thank you Gaurav!
    How I can insert aditional data into a Prepopulate database, and use them later close and open the app?

    ReplyDelete
  15. Hi Gourav, your trick is working fine for high end devices & android 2.3.
    But i have problem low end devices & android 2.2.
    Can you help me?

    ReplyDelete
  16. Hi... Can you tell me where can I put the code listed above. I am developing for Android without any prior knowledge in JAVA. Can you explain in specific details ? Thanks

    ReplyDelete
  17. Hi Gaurav, how do i achieve same task for blackberry webworks platform. plz reply

    ReplyDelete
  18. A more up to date version that I worked with and made a guest post on Ray Camden's website:
    http://www.raymondcamden.com/index.cfm/2012/7/27/Guest-Blog-Post-Shipping-a-populated-SQLite-DB-with-PhoneGap

    ReplyDelete
  19. Muy interesante este tema, como seria si si estoy trabajando con html5 js y css3 como podria hacer esto mismo algĂșn manual o algo que me recomiendes

    ReplyDelete