Android SQLite Basics: creating and using a database, and working with sqlite3

Tagged:
UPDATE DISCLAIMERThis is one way to do direct DB access with SQLite on Android, but it's not the only way. I have modified the pattern I personally use somewhat, and it's quite a bit different from the time this article was written (this article is old). I plan to update this article at some point when I have time, but for now just keep in mind that this is meant to get you started, but not be a complete/comprehensive/exclusive approach.
Also, after a server crash the formatting, and some images were lost, these items will be fixed as soon as I get a chance, sorry.


Because I often have to revisit this stuff myself, I thought I would write a quick reference tutorial on creating and using a database with an Android application. This isn't terribly well covered in the Android docs, and though many ContentProvider tutorials exist (such as the Unlocking Android code for chapter 5, and the NotePad tutorial included with the SDK), and these help a lot with general database concepts, they are really more complicated than what a basic application needs - a database to store and retrieve stuff. I will walk through the code and tools for an oversimplified example here, with the ultimate goal of inserting and retrieving some data from an database in an Android app, and then examining the database using a shell and the sqlite3 command line tool. The entire code for this example is available here: http://totsp.com/svn/repo/AndroidExamples/trunk/. NOTE This code was updated for part 2, and part 3 of this series, so it no longer exactly matches this example -- it's still a working sample app, it just now does a bit more than the original. First, to get this rolling, we need to create an Android application that HAS a database. We could use any built in application that has a database just to explore it, such as com.android.alarmclock), but we are going to create one here for completeness. After it's setup, the interface for our application will look like the screen shot shown below:
Android Examples Yeah this project is ugly, and it only has one Activity, but for our purposes here we really aren't trying to create a fancy UI (or anything that is complicated on any level). To create this project we will use the Eclipse IDE. Along with Eclipse, we will also of course need to have the Android SDK with the correct Eclipse ADT Plug-In as a prerequisite too (to get that see the instructions at the aforelinked site). 1. To create a basic Android project, we will simply select File->New->Other->Android->Android Project. On the dialog we will then enter the application name AndroidExamples, and the package name com.totsp.androidexamples, along with some other settings, as shown in the figure below:
Create Android Project with Eclipse The target we choose must be one that we have installed when we setup or configued the Android SDK. For this example we are using 1.6 because it is still the most common Android platform that user's phones are running (we are using the 2.1 SDK, with a 1.6 Target). We will also set the "Min SDK Version" to "4" which is SDK 1.6. This is a confusing part of the Android setup at this point (names are transposed from "sdk" to "api" and such) but the details are documented somewhat. Once we have the default sample project in place, the next step will be to create a helper class that can create the database and encapsulate other SQL details. We will call this class DataHelper. Within this class (at the end) we will include an important inner class that provides a SQLiteOpenHelper. The full code is shown below:
package com.totsp.androidexamples;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

public class DataHelper {

   private static final String DATABASE_NAME = "example.db";
   private static final int DATABASE_VERSION = 1;
   private static final String TABLE_NAME = "table1";

   private Context context;
   private SQLiteDatabase db;

   private SQLiteStatement insertStmt;
   private static final String INSERT = "insert into " 
      + TABLE_NAME + "(name) values (?)";

   public DataHelper(Context context) {
      this.context = context;
      OpenHelper openHelper = new OpenHelper(this.context);
      this.db = openHelper.getWritableDatabase();
      this.insertStmt = this.db.compileStatement(INSERT);
   }

   public long insert(String name) {
      this.insertStmt.bindString(1, name);
      return this.insertStmt.executeInsert();
   }

   public void deleteAll() {
      this.db.delete(TABLE_NAME, null, null);
   }

   public List<String> selectAll() {
      List<String> list = new ArrayList<String>();
      Cursor cursor = this.db.query(TABLE_NAME, new String[] { "name" }, 
        null, null, null, null, "name desc");
      if (cursor.moveToFirst()) {
         do {
            list.add(cursor.getString(0)); 
         } while (cursor.moveToNext());
      }
      if (cursor != null && !cursor.isClosed()) {
         cursor.close();
      }
      return list;
   }

   private static class OpenHelper extends SQLiteOpenHelper {

      OpenHelper(Context context) {
         super(context, DATABASE_NAME, null, DATABASE_VERSION);
      }

      @Override
      public void onCreate(SQLiteDatabase db) {
         db.execSQL("CREATE TABLE " + TABLE_NAME + " 
          (id INTEGER PRIMARY KEY, name TEXT)");
      }

      @Override
      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
         Log.w("Example", "Upgrading database, this will drop tables and recreate.");
         db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
         onCreate(db);
      }
   }
}
This class is simple, as I have said it would be. For example it's using a database with one table and one column, but, it still covers some core Android concepts. We won't go into great detail concerning this class here, it should be mostly understandable from the code, but a few important things to note are:
  • it includes an implementation of SQLiteOpenHelper as an inner class
  • it demonstrates two different ways of interacting with the database in code, with a SQLiteStatement for inserts (which has the advantage of being pre-compiled, versus regular, but easier SQLiteDatabase.query() methods you probably also want to be familiar with), and directly by querying for selects
  • it shows a useful pattern (though again, oversimplified here) of exposing data persistence/retrieval methods on the helper
To use this class from the default Main.java class that we let the Android Eclipse Plug-In generate, we will modify it a bit to create an instance of our DataHelper and then use it to create and retrieve data as seen below.(NOTE: In the real world you might do this once per application, say by using the oft overlooked Android Application class, where you could create the DataHelper once, and then expose the reference to other classes, rather than in Activity.onCreate()):
package com.totsp.androidexamples;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import java.util.List;

public class Main extends Activity {
    
   private TextView output;
   
   private DataHelper dh;
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        this.output = (TextView) this.findViewById(R.id.out_text);
        
        this.dh = new DataHelper(this);
        this.dh.deleteAll();
        this.dh.insert("Porky Pig");
        this.dh.insert("Foghorn Leghorn");
        this.dh.insert("Yosemite Sam");        
        List<String> names = this.dh.selectAll();
        StringBuilder sb = new StringBuilder();
        sb.append("Names in database:\n");
        for (String name : names) {
           sb.append(name + "\n");
        }
        
        Log.d("EXAMPLE", "names size - " + names.size());
        
        this.output.setText(sb.toString());
        
    }
}
For this class to work, we also need to change the main.xml layout file it relies on. We need to include one additional TextView for the output, as seen below:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 
  xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content">
  <LinearLayout xmlns:android=
     "http://schemas.android.com/apk/res/android"
      android:orientation="vertical" 
      android:layout_width="fill_parent"
      android:layout_height="fill_parent">
    <TextView android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:text="@string/hello" />
    <TextView android:id="@+id/out_text"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:text="" />
  </LinearLayout>
</ScrollView>
With that, we have an application that we should be able to launch and run in the emulator, and it should look like the first screen shot we saw above - a basic black screen with white text and a few names as output. The names come from the database, which now exists, and now we can move on to using sqlite3. Android uses SQLite as it's built in embedded database. If you need to store local application data, rather than going to simpler mechanisms like the file system, or more complicated means such as the network, you use the database. To examine the database we can login using the shell provided by the Android Debug Bridge. To use this we need the "tools" folder of the SDK on our path (see the SDK documentation if you need more information about that). If we start the app in Eclipse (Run As -> Android Application), and leave it running, we should then be able to login with the command:
ccollins@crotalus:~$ adb -e shell
# 
The -e option tells ADB to use the emulator, rather than a possible connected device (and returns an error if more than one emulator is running). The "#" is the command prompt, we are logged in.

Once logged in we can browse around with the "ls" command. The directory we are interested in is /data/data/com.totsp.androidexamples/databases (each application has a directory at the path /data/data/PACKAGE_NAME). We can change to that directory with the "cd" command. Once there we can use the command line SQLite tool, sqlite3, to examine our database, as follows:
# sqlite3 example.db
SQLite version 3.5.9
Enter ".help" for instructions
sqlite> select * from sqlite_master;
table|android_metadata|android_metadata|3|CREATE TABLE android_metadata (locale TEXT)
table|table1|table1|4|CREATE TABLE table1 (id INTEGER PRIMARY KEY, name TEXT)
sqlite> 

We login with "sqlite3 [database_name]" and then we can run basic SQL commands that are supported by SQLite (see the documentation there for full details). One handy table is the sqlite_master that we can see shows all the other tables inside our database.

Some other interesting commands are:
sqlite> .schema
CREATE TABLE android_metadata (locale TEXT);
CREATE TABLE table1 (id INTEGER PRIMARY KEY, name TEXT);
sqlite> .tables
android_metadata  table1          
sqlite> select * from table1;
1|Porky Pig
2|Foghorn Leghorn
3|Yosemite Sam
sqlite> 

We can use .help from within the sqlite3 shell (it has it's own shell, apart from the emulator shell we are logged in to), to see a full list of commands. Commands that start with "." are built in, and perform a function - such as .schema and .tables that we see above. SQL commands themselves can also be run directly by typing them in -- something we also see above (typed commands are run as soon as a ; is encountered and you press enter).

With that, we have the basics. We have an application that creates a database and stores and retrieves data using it, and we have done a bit of exploring with the SQLite tools in ADB. In the future I hope to expand on this article and add some more involved tables, and further examples such as Android unit testing (another not so well documented, but extremely useful, part of the platform).

Comments

Thanks dude, your article was

Thanks dude, your article was really helpful to me! Indeed, Google could have done a better job documenting the database aspect of Android.

Thanks a lot..........

Actually, i am new in the android development, so This article help me lot to learn about android database...........

Thanks.

Stellar job. Thanks for taking the time to do this. -Banker

This is a great tutorial

You have just completed my understanding of android apps. I have learnt alot from different tutorials but none really covered DB connections properly. Thanks for this. I realy appreciate it. Maybe you can do a tutorial on storing data using preferences next.

I want to view the database

I want to view the database in SQL lite database browser, but the database does not appear in assets folder?

I want to view the database

Thank you for sharing your knowledge. One can see the SQLLIte database file in DDMS. Keep application running.Open DDMS,Select current application in "File Explorer" and navigate to "databases" folder.There one can find the .db file.

I want to view the database

Correction to above reply One can see the SQLLIte database file in DDMS. Keep application running.Open DDMS, Browse data/data/applicationname/databases folder in File Explorer .There one can find the .db file.

Hello, that is w very helpful

Hello, that is w very helpful article.. i translated that article and i liked it.. thak you very much..

View the database

Hi... It was highly useful... I need to see the .db file.. But in DDMS I could not find Databases ... Pls help..

Got it!!!!

Thanks dude... I could see the database... Great work!!!!!!

This example works with Target 2.2? Thanks for the post!

This example works with Target 2.2? Or any new version of android that will come? Thanks for the post!

Great article

Thank you, - again, like you mentioned, most tutorials involve contentproviders and what have you - this tutorial teaches us the very basic principles - which is absolutely puurrfect.. Thank you so much!

Congratulations & Query

Hi Charly, very good your explanation. Sorry, I need know where is obtain all commands for Android Emulator, relative reference about to this articles, so on. :) Thank!

simple and straightforward

Thanks for this useful tutorial. It makes it much easier to understand what you really need to get going with database stuff than the examples provided with the Android SDK. To answer one of the previous comments this also works with API Level 8 (Android 2.2) which is what I'm using.

Thanks a lot

Thanks a lot man... this article really helped me a lot in understanding android databases

Thank you! This was simple

Thank you! This was simple and very helpful.

Excellent !!

Excellent !!

Question

Hi, I am using this tutorial to create a database with multiple rows. I'm a bit stuck though and hope someone will be able to answer my question. I don't know how to alter the following code to insert multiple strings: public long insert(String name) { this.insertStmt.bindString(1, name); return this.insertStmt.executeInsert(); } I'm also wondering how to use the public List code, I want to show rows based on a query like SELECT * from TABLE_NAME where country = 'NETHERLANDS', how would I do that? I've already altered the rest of the code to my needs as seen below, not sure it works yet, though. import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteStatement; import android.util.Log; import java.util.ArrayList; import java.util.List; public class DataHelper { private static final String DATABASE_NAME = "rooster.db"; private static final int DATABASE_VERSION = 1; private static final String TABLE_NAME = "rooster"; private Context context; private SQLiteDatabase db; private SQLiteStatement insertStmt; private static final String INSERT = "insert into " + TABLE_NAME + "(dag, vak, lokaal, begintijd, eindtijd, leraar) values (?, ?, ?, ?, ?, ?)"; public DataHelper(Context context) { this.context = context; OpenHelper openHelper = new OpenHelper(this.context); this.db = openHelper.getWritableDatabase(); this.insertStmt = this.db.compileStatement(INSERT); } public long insert(String dag, String vak, String lokaal, String begintijd, String eindtijd, String leraar) { this.insertStmt.bindString(1, dag); return this.insertStmt.executeInsert(); } public void deleteAll() { this.db.delete(TABLE_NAME, null, null); } public List selectAll() { List list = new ArrayList(); Cursor cursor = this.db.query(TABLE_NAME, new String[] { "name" }, null, null, null, null, "id desc"); if (cursor.moveToFirst()) { do { list.add(cursor.getString(0)); } while (cursor.moveToNext()); } if (cursor != null && !cursor.isClosed()) { cursor.close(); } return list; } private static class OpenHelper extends SQLiteOpenHelper { OpenHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + TABLE_NAME + " (id INTEGER PRIMARY KEY, dag TEXT, vak TEXT, lokaal TEXT, begintijd TEXT, eindtijd TEXT, leraar TEXT)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w("Example", "Upgrading database, this will drop tables and recreate."); db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } } } Thanks in advance for your help!

Keep in mind what I've done

Keep in mind what I've done here is just a basic example. See the docs for all the stuff you can do: http://developer.android.com/reference/android/database/sqlite/SQLiteDat.... To bind multiple strings to one statement, just use bindString(1, firstName), bindString(2, lastName), where your statement has multiple placeholders (?s). Here's an example (see the insert method): http://code.google.com/p/and-bookworm/source/browse/trunk/src/com/totsp/... Also note that you don't *have* to use a SQLiteStatement. The statement is pre-compiled and will be a little faster if you use it over and over again, but there is also a plain "insert" method: http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#insert(java.lang.String, java.lang.String, android.content.ContentValues)

Thank you so much! I'll be

Thank you so much! I'll be looking into it.

Hi, i also want to knw how to

Hi, i also want to knw how to add 2 or more columns using your code. Thanks

Great!!! tutorial

superb!!! work simple but very useful... Thanks a lot... Ronic

Excellent tutorial indeed!

It makes it much easier to understand what you really need to get going with database stuff than the examples provided with the Android SDK.

I now got as far as being

I now got as far as being able to insert multiple columns in the database. The only thing I'm still struggling with is viewing all the data. I only am able to show 1 column from the database with the following code: this.output = (TextView) this.findViewById(R.id.out_text); this.dh = new DataHelper(this); List lesuren = this.dh.selectAll(); StringBuilder sb = new StringBuilder(); sb.append("Names in database:\n"); for (String address: addresses) { sb.append("address: " + address+ "\n"); } this.output.setText(sb.toString()); And in DataHelper.java: public List selectAll() { List list = new ArrayList(); Cursor cursor = this.db.query(TABLE_NAME, new String[] { "address" }, null, null, null, null, "addressasc"); if (cursor.moveToFirst()) { do { list.add(cursor.getString(0)); } while (cursor.moveToNext()); } if (cursor != null && !cursor.isClosed()) { cursor.close(); } return list; } I would be very grateful if someone can help me out with this.

Check the docs, a lot of

Check the docs, a lot of helpful stuff is in there. But to go ahead an bite, without carefully reviewing your code, this might be the right direction (disclaimer, did I say check the docs?): ... // the second element to the query method is an array of the columns you want to retrieve Cursor cursor = this.db.query(TABLE_NAME, new String[] { "address", "fname", "lname" }, null, null, null, null, "addressasc"); if (cursor.moveToFirst()) { do { list.add(cursor.getString(0)); // address list.add(cursor.getString(1)); // fname list.add(cursor.getString(2)); // lname ... http://developer.android.com/reference/android/database/sqlite/SQLiteDat...

Thanks, I already had found

Thanks, I already had found the solution, just like you're example, so it's working now. Now I'm gonna figure out how to put it in a nice grid and being able to do a query like: SELECT * from TABLE_NAME where day = 'monday'. Thanks for your help.

Great example, a very good start point

It's a fact that the Android docs are horrible to anyone who is starting at anything. It's not beginner-oriented, and that is to be expected somewhat. When I learned how to use SQLite3 with Android, the only example that really did for me was yours. I actually use the same methodology I learned with you to this very day. Of course, many of my projects are huge behemoths, but the skeleton is still the same of your example. Thank you very much. You don't know how much you helped me.

I know this article isn't

I know this article isn't perfect, but glad to hear it helped, and thanks for saying thanks.

Database in Gridview?

Does anyone know how to put the database entries into a gridview? Or is there a tutorial out there which explains how to do that. I've followed the Gridview documentation on developer.android.com, and succeeded into loading text into the gridview, but not the text my database contains. My gridview code at this time:
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.TextView;

public class ImageAdapter extends BaseAdapter {
    private Context context;

  public ImageAdapter(Context context) {
        this.context = context;
    }

   public int getCount() {
        return 4;
    }


    public Object getItem(int position) {
        return null;
    }

   public long getItemId(int position) {
        return 0;
    }

    // create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        TextView tv;
        if (convertView == null) {
            tv = new TextView(context);
            tv.setLayoutParams(new GridView.LayoutParams(60, 25));
        }
        else {
            tv = (TextView) convertView;
        }

        tv.setText(texts[position]);
        return tv;
        
    }
    
    private String[] texts = {"PWU", "10:00", "10:45", "Boukiour"};

}
Thanks in advance for your help!

Thanks for the tutorial!

Thanks for the tutorial! Helped me a lot.

Thanks

This is exactly what i was looking for, i ran your code successfully, and based on my previous programming experience in other platforms(Other than android) i am able to modify it to fit my android application's needs. Thanks.

Where is database (if i am using sqlite browser)?

I am using an sqlite browser in MAC. I want to this database to open in my browser..? will you please help? where the file actually stored?

To use something like SQLite

To use something like SQLite Manager (http://code.google.com/p/sqlite-manager/), which can be handy, you'll have to copy the DB file over. You can't connect directly to it. And this article explains exactly where the file is stored.

Thumbs up

Much more useful than any of the documentation provided by Google, thanks very much :)

Awesome tutorial

I just wanted to thank you for the greatest tutorial ever. It really helped. It's simple and truly understandable. Thanks a lot

Thankyou Man!

This tutorial had greatly helped me. Keep the good/Great stuff going on man. Hope you achieve greater heights. :-)

Unable to view database

Hi, I have created exact copy of this application. but as you said "a basic black screen with white text and a few names" will come as output, but i am not getting it in my emulator. next when i give ls data/data in cmd. i can find package "com.totsp.androidexamples" but when i give " ls /data/data/com.totsp.androidexamples/databases " i get the message "No such file or directory" even i went to windows explorer of ddms and clicked on data/data. i found only package name when i placed cursor above com file. but couldnt find any .db file. can you please tell me why this is happening and how can i solve my prob Thanks

Unable to view database

This will happen to you if you mess up project creation in Eclipse. The .png file is to small to actually read project configuration, but click generate activity and name it Main. I tried manually correcting the manifest, but gave up and created a new project and copied over all my source. Works great now.

It really helped me a lot,

It really helped me a lot, thank u so much.. keep doing ur job...

Thanks

Ne nalla iruppa da.. romba supera sollirukka.. thanks machi..

awesome

it was very useful....... thanks for such program

Thanks!

Ah, now I get it! Thanks for the clear and simple tutorial. I'm glad I came across this page.

error help

this.input = (EditText) this.findViewById(R.id.in_text); this.saveButton = (Button) this.findViewById(R.id.save_button); this.deleteButton = (Button) this.findViewById(R.id.del_button); this.output = (TextView) this.findViewById(R.id.out_text); in_text cannot be resolved or is not a field i do not know what to do with this error. please help.

error help

R.java is a generated resource file which lives in gen/. R.id.in_text would come from your xml definitions. Make sure your res/layout/main.xml has a section like: android:id="@+id/in_text". Robert

As you mentioned the

As you mentioned the res/layout/main.xml has a section like: android:id="@+id/in_text". and for every other corresponding id. still it is showing an error. what could be the reason. and thanks for your help.

A few questions...

I noticed that there is this "sqlite" thingy inside the tools folder in the android sdk, does that mean that I don't have to install sqlite separately? Also, why does the app need to create the DB through code? Can't we access a pre populated DB and access it from there?

Great tutorial!

Many thanks for the tutorial. It is very well done. As for me, I used this video tutorial http://www.tubestime.com/watch/android-database-sqlite-tutorial but there were a lot of points I couldn't fullfill. You are right sometimes the tutorials are more complicated that they are needed to be. Thanks for giving us the alternative!

This tutorial saves lives

Thank you so much for making this tutorial. Not only did it save hours and hours of time, but it gave me a strong foundation to build off of. Thank you again!!!

SQLite database

I have tried several tutorials for android for SQLite but the database does not load at all. There is no folder databases with the file name. I do have mySQL on machine. Is that maybe why this won't work. Can someone help with how to get SQLite to work with android. thanks, alex

I try to instantiate the

I try to instantiate the DataHelper on the Application but the constructor of DataHelper require a context I try getApplicationContext() but does'nt works :( any suggestion? Thanks in advance

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.