6.3 Android Database

Android Database Tutorial

Ths chapter is about Android database.  With databases we can manage application data in a structured way. Every application can create its own application data and it has complete control over it. So let us not waste our time and start our tutorial as soon as possible.

6.3.1 Introduction to SQLite

Android has a full SQLite relational database library. SQLite is a relational database management system (RDBMS). So using SQLite, an effective encapsulated relational database can be created for our application. Complex and structured application data can be easily managed with this approach. Android databases have storage in /data/data/<package_name>/databases folder of emulator or device. By default, databases are private i.e. application which creates the database only that app has control over it. SQLite is an open source, light weight, single tier and standards-compliant structure. Since SQLite is added as a library in the android software stack architecture, each SQLite database is considered as an integrated part of application. SQlite is an extremely reliable system.

We shall create a helper class which is used to encapsulate all complexities. We shall create a helper class called DBHelper. It will create, open, use and close the database system. Helper class extends SQLiteOpenHelper super class. Let us create an example to sort this out.

6.3.2 Android Database Example    

Open your IDE and create a project. Name it as you like. I am naming it DBExample app. In this project we shall create two contacts. Retrieve the contacts and delete contacts as well. We shall create an adapter class and name it DbHelp. We shall create a helper class called DatabaseHelper and use the corresponding object to manage the database. Open your activity_main.xml file and code it as shown in the following listing:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >
    <Button
        android:id="@+id/buttonRetrieve"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/buttonDelete"
        android:layout_alignBottom="@+id/buttonDelete"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="14dp"
        android:text="Show All" />
    <Button
        android:id="@+id/buttonDelete"
        style="?android:attr/buttonStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="62dp"
        android:text="Delete" />
    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginTop="36dp"
        android:layout_toRightOf="@+id/buttonRetrieve"
        android:text="Hello Readers!!" />
</RelativeLayout>

                                Figure - activity_main.xml file Android Database Example

Graphical layout should be similar to the following snapshot:

Graphical layout of Android Database Example

                                                           Figure -  Graphical layout of Android Database Example

Open your main activity file and code it as shown in the following listing:

package com.android.tution.DB;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
    Button show,delete;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        show = (Button) findViewById(R.id.buttonRetrieve);
        delete=(Button)findViewById(R.id.buttonDelete);
        show.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent i = new Intent(MainActivity.this, Allcontacts.class);
                startActivity(i);
            }
        });
delete.setOnClickListener(new View.OnClickListener() {    
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub    
        Intent intent=new Intent(MainActivity.this,DeleteContact.class);
        startActivity(intent);
    }
});
        DbHelp db = new DbHelp(this);
        db.open();
        long id = db.insertContact("abc", "abc@xyz.com", "India");
        id = db.insertContact("pqr", "def@vs.com", "United States");
        db.close();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

                                                   Figure - main activity file of Android Database Example

Now create a class and name it DbHelp. Code it as shown in the following snapshot:

package com.android.tution.DB;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DbHelp {
    public static final String ROWID = "_id";
    public static final String NAME = "name";
    public static final String EMAIL = "email";
    public static final String ADDRESS = "address";
    private static final String TAG = "DbHelp";
    private static final String DATABASE_NAME = "Mydb";
    private static final String DATABASE_TABLE = "contacts";
    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_CREATE = "create table contacts (_id integer primary key autoincrement, "
            + "name text not null, email text not null, address text not null);";
    private final Context context;
    private DatabaseHelper DBHelper;
    private SQLiteDatabase db;    
    public DbHelp (Context con)
    {
        this.context=con;
        DBHelper=new DatabaseHelper(context);
    }
    private static class DatabaseHelper extends SQLiteOpenHelper
    {
        DatabaseHelper(Context context) {
            // TODO Auto-generated constructor stub
        super(context,DATABASE_NAME,null,DATABASE_VERSION);
        }
        @Override
        public void onCreate(SQLiteDatabase db) {
            // TODO Auto-generated method stub        
            try{
                db.execSQL(DATABASE_CREATE);
            }catch(SQLException e)
            {
                e.printStackTrace();
            }
        }
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // TODO Auto-generated method stub            
            Log.w(TAG,"Upgrading database from version" + oldVersion + "to " + newVersion + ", which will destroy all old data");
        db.execSQL("DROP TABLE IF EXISTS contacts");
        onCreate(db);        
        }
    }

                                                       Figure -  First half of DbHelp class

Continue in the same class. Second part is as shown in the following listing:

public DbHelp open() throws SQLException
        {
            db=DBHelper.getWritableDatabase();
            return this;
        }    
    public void close()
    {
        DBHelper.close();
    }
public long insertContact(String name, String email, String address)
{
ContentValues initialValues=new ContentValues();
initialValues.put(NAME,name);
initialValues.put(EMAIL, email);
initialValues.put(ADDRESS,address);
return db.insert(DATABASE_TABLE, null, initialValues);
}
public boolean deleteContact(long rowId){
    return db.delete(DATABASE_TABLE, ROWID + "=" + rowId,null) > 0;
}
public Cursor getAllContacts(){
    return db.query(DATABASE_TABLE, new String[] {ROWID,NAME,EMAIL,ADDRESS},null,null,null,null,null);
}
public Cursor getContact(long rowId) throws SQLException
{
Cursor c=db.query(true, DATABASE_TABLE, new String[] {ROWID,NAME,EMAIL,ADDRESS}, ROWID + "=" + rowId, null, null, null,null,null);    
if(c!=null)
{
c.moveToFirst();    
}
return c;
}
public boolean updatContact(long rowId, String name, String email, String address)
{
ContentValues cv=new ContentValues();
cv.put(NAME,name);
cv.put(EMAIL, email);
cv.put(ADDRESS, address);
return db.update(DATABASE_TABLE, cv, ROWID + "=" + rowId, null)>0;
}
}

                                    Figure - Second half of code

Create an xml file and name it allcontacts.xml. Code it as shown in the following listing:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Showing Contacts" />
</LinearLayout>

                                                              Figure - Second xml file of  

Graphical snapshot should be similar to the following snapshot:

Graphical layout of second xml fileAndroid Database Example

                                                     Figure - Graphical layout of second xml file

Now create another class and name it Allcontacts. Code it as shown in the following listing:

package com.android.tution.DB;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.Toast;
public class Allcontacts extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.allcontacts);
        DbHelp db1 = new DbHelp(this);
        db1.open();
        Cursor c = db1.getAllContacts();
        if (c.moveToFirst()) {
            do {
                Display(c);
            } while (c.moveToNext());
        }
        db1.close();
    }
    public void Display(Cursor c) {
        Toast.makeText(
                this,
                "id: " + c.getString(0) + "\n" + "Name: " + c.getString(1)
                        + "\n" + "Email: " + c.getString(2) + "\n"
                        + "Address: " + c.getString(3), Toast.LENGTH_LONG)
                .show();
    }
}

                                        Figure - Allcontacts class

Now create another java class and name it DeleteContact and code it as shown in the following listing:

package com.android.tution.DB;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
public class DeleteContact extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.allcontacts);
        DbHelp db2 = new DbHelp(this);
        db2.open();
        if (db2.deleteContact(1))
            Toast.makeText(this, "Delete successful", Toast.LENGTH_SHORT)
                    .show();
        else
            Toast.makeText(this, "Delete failed", Toast.LENGTH_SHORT).show();
        db2.close();
    }
}

                                        Figure - DeleteContact class

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.tution.DB"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.android.tution.DB.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".Allcontacts" >
        </activity>
        <activity android:name=".DeleteContact" >
        </activity>
    </application>
</manifest>

                                                  Figure - manifest file of  Android Database Example

So we are done. Create a suitable emulator and run the application. Output should be similar to the following snapshot:

                                                                          Figure - Homepage of  Android Database Example

Now press the button saying show to retrieve all contacts. Output should be similar to the following snapshot:

 Figure - showing the first contact

                                                                     Figure - showing the first contact

After few seconds next contact would be displayed as shown in the following snapshot:

displaying second contact

                                                                    Figure - displaying second contact

Now press the back button shown on emulator. Press the button saying delete in home page of app. Output should be similar to the following snapshot:

deleting a contact

                                                                 Figure - deleting a contact

Let us confirm whether contact was actually deleted or someone is fooling us. For that go back to home page and press the button saying show. You would see that toast message displays the second contact only. That means first contact was actually deleted. Output should be similar to the following snapshot:

Retrieving output after deleting first contact

                                                                 Figure - Retrieving output after deleting first contact

Congratulations buddies!!! We are done with databases. See you in the next section with something new. Till then keep practicing. Happy App Developing!!