Anda di halaman 1dari 40

11/05/2018 Android SQLite Database Tutorial

     

BEGINNER

Android SQLite Database Tutorial


BY RAVI TAMADA - 757 CO MMENTS

In Android, there are several ways to store persistent data. SQLite is one way of storing
app data. It is very lightweight database that comes with Android OS. In Android,
integrating SQLite is a tedious task as it needs writing lot of boilerplate code to store
simple data. Consider SQLite when your app needs to store simple data objects.
Alternatively you can consider Room Persistence Library for better APIs and easier
integration.

In this article we are going to learn basics of SQLite database with a realtime example of
Notes App.

DOWNLOAD CODE GITHUB DOWNLOAD .APK

VIDEO DEMO

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 1/40
11/05/2018 Android SQLite Database Tutorial

Android SQLite Notes App Demo

1. The Notes App


We are going to create a simple Notes App with SQLite as database storage. The app will
be very minimal and will have only one screen to manage the notes.

Below are the screenshots of the app.

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 2/40
11/05/2018 Android SQLite Database Tutorial

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 3/40
11/05/2018 Android SQLite Database Tutorial

Now let’s start by creating new project in Android Studio.

2. Creating New Project


1. Create a new project in Android Studio from File ⇒ New Project and select Basic
Activity from the templates.

2. Open build.gradle under app directory and add RecyclerView dependency. The
RecyclerView will be used to display the Notes in list manner.

build.gradle
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// ..

implementation 'com.android.support:recyclerview-v7:26.1.0'
}

3. Add the below resources to colors.xml, dimens.xml and strings.xml

colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#455399</color>
<color name="colorPrimaryDark">#455399</color>
<color name="colorAccent">#00c6ae</color>
<color name="msg_no_notes">#999</color>
<color name="hint_enter_note">#89c3c3c3</color>
<color name="timestamp">#858585</color>
<color name="note_list_text">#232323</color>
</resources>

dimens.xml
<resources>
<dimen name="fab_margin">16dp</dimen>
<dimen name="activity_margin">16dp</dimen>
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 4/40
11/05/2018 Android SQLite Database Tutorial

<dimen name="dot_margin_right">10dp</dimen>
<dimen name="msg_no_notes">26sp</dimen>
<dimen name="margin_top_no_notes">120dp</dimen>
<dimen name="lbl_new_note_title">20sp</dimen>
<dimen name="dimen_10">10dp</dimen>
<dimen name="input_new_note">20sp</dimen>
<dimen name="dot_height">30dp</dimen>
<dimen name="dot_text_size">40sp</dimen>
<dimen name="timestamp">14sp</dimen>
<dimen name="note_list_text">18sp</dimen>
</resources>

strings.xml
<resources>
<string name="app_name">Notes</string>
<string name="action_settings">Settings</string>
<string name="activity_title_home">Notes</string>
<string name="msg_no_notes">No notes found!</string>
<string name="lbl_new_note_title">New Note</string>
<string name="lbl_edit_note_title">Edit Note</string>
<string name="hint_enter_note">Enter your note!</string>
</resources>

4. Quickly create few packages named database, database/model, utils and view. Below
is the nal project structure and les we gonna need.

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 5/40
11/05/2018 Android SQLite Database Tutorial

2.1 Writing SQLite Helper Class


We need to create a class that extends from SQLiteOpenHelper. This class perform CRUD
operations (Create, Read, Update and Delete) on the database.

We also need a model class to create Note objects to manage the notes easily.

5. Under database/model package, create a class named Note.java. In this class we


de ne the SQLite table name, column names and create table SQL query along with
getter / setter methods.

The `notes` table needs three columns i.e `id`, `note` and `timestamp`.

Column `id` is de ned as Primary Key and Auto Increment which means each
note will be uniquely identi ed by its id.

Column `note` stores the actual note text.

Column `timestamp` stores the date and time of the note that is created.

Note.java
public class Note {
public static final String TABLE_NAME = "notes";

public static final String COLUMN_ID = "id";


public static final String COLUMN_NOTE = "note";
public static final String COLUMN_TIMESTAMP = "timestamp";

private int id;


private String note;
private String timestamp;

// Create table SQL query


public static final String CREATE_TABLE =
"CREATE TABLE " + TABLE_NAME + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,
+ COLUMN_NOTE + " TEXT,"
+ COLUMN_TIMESTAMP + " DATETIME DEFAULT CURRENT_TI
+ ")";

public Note() {
}
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 6/40
11/05/2018 Android SQLite Database Tutorial

public Note(int id, String note, String timestamp) {


this.id = id;
this.note = note;
this.timestamp = timestamp;
}

public int getId() {


return id;
}

public String getNote() {


return note;
}

public void setNote(String note) {


this.note = note;
}

public String getTimestamp() {


return timestamp;
}

public void setId(int id) {


this.id = id;
}

public void setTimestamp(String timestamp) {


this.timestamp = timestamp;
}
}

6. Under database package, create a class named DatabaseHelper.java and extend the
class from SQLiteOpenHelper. This class holds the database related methods to perform
the CRUD operations.

onCreate() will be called only once when the app is installed. In this method, we
execute the create table sql statements to create necessary tables.

onUpgrade() called when an update is released. You need to modify the


DATABASE_VERSION in order to execute this method. You have to take care of
database migrations here without loosing the older data if necessary. For now, we
just drop the older tables and recreate them again.
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 7/40
11/05/2018 Android SQLite Database Tutorial

DatabaseHelper.java
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

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

import info.androidhive.sqlite.database.model.Note;

/**
* Created by ravi on 15/03/18.
*/

public class DatabaseHelper extends SQLiteOpenHelper {

// Database Version
private static final int DATABASE_VERSION = 1;

// Database Name
private static final String DATABASE_NAME = "notes_db";

public DatabaseHelper(Context context) {


super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

// Creating Tables
@Override
public void onCreate(SQLiteDatabase db) {

// create notes table


db.execSQL(Note.CREATE_TABLE);
}

// Upgrading database
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVe
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + Note.TABLE_NAME);

// Create tables again


onCreate(db);
}
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 8/40
11/05/2018 Android SQLite Database Tutorial

Now we’ll see the methods required to store or retrieve the notes. Add the following
methods to same class.

a. Inserting Note

Inserting data requires getting writable instance (getReadableDatabase()) on database.


Below, we are inserting new note in database.

ContentValues() is used to de ne the column name and its data to be stored. Here,
we are just setting the note value only ignoring `id` and `timestamp` as these two
will be inserted automatically.

Every time the database connection has to be closed once you are done with
database access. Calling db.close() closes the connection.

Once the note is inserted, the `id` of newly inserted note will be returned.

public long insertNote(String note) {


// get writable database as we want to write data
SQLiteDatabase db = this.getWritableDatabase();

ContentValues values = new ContentValues();


// `id` and `timestamp` will be inserted automatically.
// no need to add them
values.put(Note.COLUMN_NOTE, note);

// insert row
long id = db.insert(Note.TABLE_NAME, null, values);

// close db connection
db.close();

// return newly inserted row id


return id;
}

b. Reading Notes
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 9/40
11/05/2018 Android SQLite Database Tutorial

Reading data requires only read access (getReadableDatabase()) on the database.

getNote() takes already existed note `id` and fetches the note object.

getAllNotes() fetches all the notes in descending order by timestamp.

getNotesCount() returns the count of notes stored in database.

public Note getNote(long id) {


// get readable database as we are not inserting anything
SQLiteDatabase db = this.getReadableDatabase();

Cursor cursor = db.query(Note.TABLE_NAME,


new String[]{Note.COLUMN_ID, Note.COLUMN_NOTE, Note.COLUMN
Note.COLUMN_ID + "=?",
new String[]{String.valueOf(id)}, null, null, null, null);

if (cursor != null)
cursor.moveToFirst();

// prepare note object


Note note = new Note(
cursor.getInt(cursor.getColumnIndex(Note.COLUMN_ID)),
cursor.getString(cursor.getColumnIndex(Note.COLUMN_NOTE)),
cursor.getString(cursor.getColumnIndex(Note.COLUMN_TIMESTA

// close the db connection


cursor.close();

return note;
}

public List<Note> getAllNotes() {


List<Note> notes = new ArrayList<>();

// Select All Query


String selectQuery = "SELECT * FROM " + Note.TABLE_NAME + " ORDER
Note.COLUMN_TIMESTAMP + " DESC";

SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);

// looping through all rows and adding to list


if (cursor.moveToFirst()) {
do {
Note note = new Note();

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 10/40
11/05/2018 Android SQLite Database Tutorial

note.setId(cursor.getInt(cursor.getColumnIndex(Note.COLUMN
note.setNote(cursor.getString(cursor.getColumnIndex(Note.C
note.setTimestamp(cursor.getString(cursor.getColumnIndex(N

notes.add(note);
} while (cursor.moveToNext());
}

// close db connection
db.close();

// return notes list


return notes;
}

public int getNotesCount() {


String countQuery = "SELECT * FROM " + Note.TABLE_NAME;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);

int count = cursor.getCount();


cursor.close();

// return count
return count;
}

c. Updating Note

Updating data again requires writable access. Below the note is updated by its `id`.

public int updateNote(Note note) {


SQLiteDatabase db = this.getWritableDatabase();

ContentValues values = new ContentValues();


values.put(Note.COLUMN_NOTE, note.getNote());

// updating row
return db.update(Note.TABLE_NAME, values, Note.COLUMN_ID + " = ?",
new String[]{String.valueOf(note.getId())});
}

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 11/40
11/05/2018 Android SQLite Database Tutorial

d. Deleting Note

Deleting data also requires writable access. Below method deletes a note by nding its
`id`.

public void deleteNote(Note note) {


SQLiteDatabase db = this.getWritableDatabase();
db.delete(Note.TABLE_NAME, Note.COLUMN_ID + " = ?",
new String[]{String.valueOf(note.getId())});
db.close();
}

After adding all the methods, the DatabaseHelper.java class should be like this.

DatabaseHelper.java
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

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

import info.androidhive.sqlite.database.model.Note;

public class DatabaseHelper extends SQLiteOpenHelper {

// Database Version
private static final int DATABASE_VERSION = 1;

// Database Name
private static final String DATABASE_NAME = "notes_db";

public DatabaseHelper(Context context) {


super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

// Creating Tables
@Override
public void onCreate(SQLiteDatabase db) {
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 12/40
11/05/2018 Android SQLite Database Tutorial

// create notes table


db.execSQL(Note.CREATE_TABLE);
}

// Upgrading database
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVe
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + Note.TABLE_NAME);

// Create tables again


onCreate(db);
}

public long insertNote(String note) {


// get writable database as we want to write data
SQLiteDatabase db = this.getWritableDatabase();

ContentValues values = new ContentValues();


// `id` and `timestamp` will be inserted automatically.
// no need to add them
values.put(Note.COLUMN_NOTE, note);

// insert row
long id = db.insert(Note.TABLE_NAME, null, values);

// close db connection
db.close();

// return newly inserted row id


return id;
}

public Note getNote(long id) {


// get readable database as we are not inserting anything
SQLiteDatabase db = this.getReadableDatabase();

Cursor cursor = db.query(Note.TABLE_NAME,


new String[]{Note.COLUMN_ID, Note.COLUMN_NOTE, Note.CO
Note.COLUMN_ID + "=?",
new String[]{String.valueOf(id)}, null, null, null, nu

if (cursor != null)
cursor.moveToFirst();

// prepare note object

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 13/40
11/05/2018 Android SQLite Database Tutorial

Note note = new Note(


cursor.getInt(cursor.getColumnIndex(Note.COLUMN_ID)),
cursor.getString(cursor.getColumnIndex(Note.COLUMN_NOT
cursor.getString(cursor.getColumnIndex(Note.COLUMN_TIM

// close the db connection


cursor.close();

return note;
}

public List<Note> getAllNotes() {


List<Note> notes = new ArrayList<>();

// Select All Query


String selectQuery = "SELECT * FROM " + Note.TABLE_NAME + " O
Note.COLUMN_TIMESTAMP + " DESC";

SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);

// looping through all rows and adding to list


if (cursor.moveToFirst()) {
do {
Note note = new Note();
note.setId(cursor.getInt(cursor.getColumnIndex(Note.CO
note.setNote(cursor.getString(cursor.getColumnIndex(No
note.setTimestamp(cursor.getString(cursor.getColumnInd

notes.add(note);
} while (cursor.moveToNext());
}

// close db connection
db.close();

// return notes list


return notes;
}

public int getNotesCount() {


String countQuery = "SELECT * FROM " + Note.TABLE_NAME;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);

int count = cursor.getCount();


cursor.close();

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 14/40
11/05/2018 Android SQLite Database Tutorial

// return count
return count;
}

public int updateNote(Note note) {


SQLiteDatabase db = this.getWritableDatabase();

ContentValues values = new ContentValues();


values.put(Note.COLUMN_NOTE, note.getNote());

// updating row
return db.update(Note.TABLE_NAME, values, Note.COLUMN_ID + " =
new String[]{String.valueOf(note.getId())});
}

public void deleteNote(Note note) {


SQLiteDatabase db = this.getWritableDatabase();
db.delete(Note.TABLE_NAME, Note.COLUMN_ID + " = ?",
new String[]{String.valueOf(note.getId())});
db.close();
}
}

7. Under utils package, create two classes named RecyclerTouchListener.java and


MyDividerItemDecoration.java

RecyclerTouchListener class adds touch event to RecyclerView row.

MyDividerItemDecoration class adds divider line between rows.

RecyclerTouchListener.java
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

/**
* Created by ravi on 21/02/18.
*/

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 15/40
11/05/2018 Android SQLite Database Tutorial

public class RecyclerTouchListener implements RecyclerView.OnItemTouch

private ClickListener clicklistener;


private GestureDetector gestureDetector;

public RecyclerTouchListener(Context context, final RecyclerView r

this.clicklistener = clicklistener;
gestureDetector = new GestureDetector(context, new GestureDete
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}

@Override
public void onLongPress(MotionEvent e) {
View child = recycleView.findChildViewUnder(e.getX(),
if (child != null && clicklistener != null) {
clicklistener.onLongClick(child, recycleView.getCh
}
}
});
}

@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clicklistener != null && gestureDetector.
clicklistener.onClick(child, rv.getChildAdapterPosition(ch
}

return false;
}

@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {

@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowI

public interface ClickListener {


void onClick(View view, int position);

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 16/40
11/05/2018 Android SQLite Database Tutorial

void onLongClick(View view, int position);


}
}

MyDividerItemDecoration.java
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.View;

public class MyDividerItemDecoration extends RecyclerView.ItemDecorati

private static final int[] ATTRS = new int[]{


android.R.attr.listDivider
};

public static final int HORIZONTAL_LIST = LinearLayoutManager.HORI


public static final int VERTICAL_LIST = LinearLayoutManager.VERTIC

private Drawable mDivider;


private int mOrientation;
private Context context;
private int margin;

public MyDividerItemDecoration(Context context, int orientation, i


this.context = context;
this.margin = margin;
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}

public void setOrientation(int orientation) {


if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_
throw new IllegalArgumentException("invalid orientation");

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 17/40
11/05/2018 Android SQLite Database Tutorial

}
mOrientation = orientation;
}

@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}

public void drawVertical(Canvas c, RecyclerView parent) {


final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight()

final int childCount = parent.getChildCount();


for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.Lay
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left + dpToPx(margin), top, right - dpT
mDivider.draw(c);
}
}

public void drawHorizontal(Canvas c, RecyclerView parent) {


final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBotto

final int childCount = parent.getChildCount();


for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.Lay
.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top + dpToPx(margin), right, bott
mDivider.draw(c);
}
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView p

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 18/40
11/05/2018 Android SQLite Database Tutorial

if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}

private int dpToPx(int dp) {


Resources r = context.getResources();
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX
}
}

3. Adding Notes UI
Now we have the database helper class ready. Let’s quickly build the main interface and
integrate it with the database.

First we need an adapter to display the notes in list manner. For this, we need a layout le
and Adapter class.

8. Create new xml layout named note_list_row.xml. This layout holds the design of single
note item in the list.

note_list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/andr
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:foreground="?attr/selectableItemBackground"
android:paddingBottom="@dimen/dimen_10"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:paddingTop="@dimen/dimen_10">

<TextView
android:id="@+id/dot"
android:layout_width="wrap_content"
android:layout_height="@dimen/dot_height"
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 19/40
11/05/2018 Android SQLite Database Tutorial

android:layout_marginRight="@dimen/dot_margin_right"
android:layout_marginTop="@dimen/dimen_10"
android:includeFontPadding="false"
android:textColor="@color/colorAccent"
android:lineSpacingExtra="0dp"
android:textSize="@dimen/dot_text_size" />

<TextView
android:id="@+id/timestamp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/dot"
android:textColor="@color/timestamp"
android:textSize="@dimen/timestamp" />

<TextView
android:id="@+id/note"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/timestamp"
android:layout_toRightOf="@id/dot"
android:textColor="@color/note_list_text"
android:textSize="@dimen/note_list_text" />

</RelativeLayout>

9. Under view package, create a class named NotesAdapter.java. This adapter class
renders the RecyclerView with de ned layout and data set.

NotesAdapter.java
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 20/40
11/05/2018 Android SQLite Database Tutorial

import info.androidhive.sqlite.R;
import info.androidhive.sqlite.database.model.Note;

public class NotesAdapter extends RecyclerView.Adapter<NotesAdapter.My

private Context context;


private List<Note> notesList;

public class MyViewHolder extends RecyclerView.ViewHolder {


public TextView note;
public TextView dot;
public TextView timestamp;

public MyViewHolder(View view) {


super(view);
note = view.findViewById(R.id.note);
dot = view.findViewById(R.id.dot);
timestamp = view.findViewById(R.id.timestamp);
}
}

public NotesAdapter(Context context, List<Note> notesList) {


this.context = context;
this.notesList = notesList;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewT
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.note_list_row, parent, false);

return new MyViewHolder(itemView);


}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Note note = notesList.get(position);

holder.note.setText(note.getNote());

// Displaying dot from HTML character code


holder.dot.setText(Html.fromHtml("&#8226;"));

// Formatting and displaying timestamp


holder.timestamp.setText(formatDate(note.getTimestamp()));
}

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 21/40
11/05/2018 Android SQLite Database Tutorial

@Override
public int getItemCount() {
return notesList.size();
}

/**
* Formatting timestamp to `MMM d` format
* Input: 2018-02-21 00:15:42
* Output: Feb 21
*/
private String formatDate(String dateStr) {
try {
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH
Date date = fmt.parse(dateStr);
SimpleDateFormat fmtOut = new SimpleDateFormat("MMM d");
return fmtOut.format(date);
} catch (ParseException e) {

return "";
}
}

3.1 Adding Create / Edit Note Dialog


If you observe the app design, a note is created or updated using a Dialog. So, we need to
create a custom layout with EditText input and in ate it in AlertDialog.

10. Create another layout named note_dialog.xml

note_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/androi
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:paddingTop="@dimen/activity_margin">
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 22/40
11/05/2018 Android SQLite Database Tutorial

<TextView android:id="@+id/dialog_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/dimen_10"
android:fontFamily="sans-serif-medium"
android:lineSpacingExtra="8sp"
android:text="@string/lbl_new_note_title"
android:textColor="@color/colorAccent"
android:textSize="@dimen/lbl_new_note_title"
android:textStyle="normal" />

<EditText
android:id="@+id/note"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:gravity="top"
android:hint="@string/hint_enter_note"
android:inputType="textCapSentences|textMultiLine"
android:lines="4"
android:textColorHint="@color/hint_enter_note"
android:textSize="@dimen/input_new_note" />

</LinearLayout>

11. Open the layout les of main activity (activity_main.xml and content_main.xml) and
add RecyclerView widget. I am also changing the icon of FAB here.

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http:/
android:id="@+id/coordinator_layout"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="info.androidhive.sqlite.view.MainActivity">

<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 23/40
11/05/2018 Android SQLite Database Tutorial

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.AppBarLayout>

<include layout="@layout/content_main" />

<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@drawable/ic_add_white_24dp" />

</android.support.design.widget.CoordinatorLayout>

content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/andr
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="info.androidhive.sqlite.view.MainActivity"
tools:showIn="@layout/activity_main">

<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<TextView
android:id="@+id/empty_notes_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 24/40
11/05/2018 Android SQLite Database Tutorial

android:layout_marginTop="@dimen/margin_top_no_notes"
android:fontFamily="sans-serif-light"
android:text="@string/msg_no_notes"
android:textColor="@color/msg_no_notes"
android:textSize="@dimen/msg_no_notes" />

</RelativeLayout>

12. Finally open MainActivity.java and do the below changes.

showNoteDialog() open the alert dialog to create new note. This dialog will be
shown by tapping FAB.

createNote() inserts new note in database and adds the newly inserted note in
RecyclerView list.

showActionsDialog() shows a dialog with Edit and Delete options. This dialog can
be invoked by long pressing the note in the list.

Selecting Edit, opens the update note dialog with already existed note text. You can
modify the note text and update it in database by calling updateNote() method.

deleteNote() deletes a note from database. The deleted note is again removed
from list by calling notifyItemRemoved() on adapter.

toggleEmptyNotes() toggles the visibility of notes and empty note view depending
on the count (db.getNotesCount() > 0) of notes.

MainActivity.java
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 25/40
11/05/2018 Android SQLite Database Tutorial

import android.widget.TextView;
import android.widget.Toast;

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

import info.androidhive.sqlite.R;
import info.androidhive.sqlite.database.DatabaseHelper;
import info.androidhive.sqlite.database.model.Note;
import info.androidhive.sqlite.utils.MyDividerItemDecoration;
import info.androidhive.sqlite.utils.RecyclerTouchListener;

public class MainActivity extends AppCompatActivity {


private NotesAdapter mAdapter;
private List<Note> notesList = new ArrayList<>();
private CoordinatorLayout coordinatorLayout;
private RecyclerView recyclerView;
private TextView noNotesView;

private DatabaseHelper db;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

coordinatorLayout = findViewById(R.id.coordinator_layout);
recyclerView = findViewById(R.id.recycler_view);
noNotesView = findViewById(R.id.empty_notes_view);

db = new DatabaseHelper(this);

notesList.addAll(db.getAllNotes());

FloatingActionButton fab = (FloatingActionButton) findViewById


fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showNoteDialog(false, null, -1);
}
});

mAdapter = new NotesAdapter(this, notesList);


RecyclerView.LayoutManager mLayoutManager = new LinearLayoutMa
recyclerView.setLayoutManager(mLayoutManager);

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 26/40
11/05/2018 Android SQLite Database Tutorial

recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new MyDividerItemDecoration(thi
recyclerView.setAdapter(mAdapter);

toggleEmptyNotes();

/**
* On long press on RecyclerView item, open alert dialog
* with options to choose
* Edit and Delete
* */
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(
recyclerView, new RecyclerTouchListener.ClickListener(
@Override
public void onClick(View view, final int position) {
}

@Override
public void onLongClick(View view, int position) {
showActionsDialog(position);
}
}));
}

/**
* Inserting new note in db
* and refreshing the list
*/
private void createNote(String note) {
// inserting note in db and getting
// newly inserted note id
long id = db.insertNote(note);

// get the newly inserted note from db


Note n = db.getNote(id);

if (n != null) {
// adding new note to array list at 0 position
notesList.add(0, n);

// refreshing the list


mAdapter.notifyDataSetChanged();

toggleEmptyNotes();
}
}

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 27/40
11/05/2018 Android SQLite Database Tutorial

/**
* Updating note in db and updating
* item in the list by its position
*/
private void updateNote(String note, int position) {
Note n = notesList.get(position);
// updating note text
n.setNote(note);

// updating note in db
db.updateNote(n);

// refreshing the list


notesList.set(position, n);
mAdapter.notifyItemChanged(position);

toggleEmptyNotes();
}

/**
* Deleting note from SQLite and removing the
* item from the list by its position
*/
private void deleteNote(int position) {
// deleting the note from db
db.deleteNote(notesList.get(position));

// removing the note from the list


notesList.remove(position);
mAdapter.notifyItemRemoved(position);

toggleEmptyNotes();
}

/**
* Opens dialog with Edit - Delete options
* Edit - 0
* Delete - 0
*/
private void showActionsDialog(final int position) {
CharSequence colors[] = new CharSequence[]{"Edit", "Delete"};

AlertDialog.Builder builder = new AlertDialog.Builder(this);


builder.setTitle("Choose option");
builder.setItems(colors, new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which) {

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 28/40
11/05/2018 Android SQLite Database Tutorial

if (which == 0) {
showNoteDialog(true, notesList.get(position), posi
} else {
deleteNote(position);
}
}
});
builder.show();
}

/**
* Shows alert dialog with EditText options to enter / edit
* a note.
* when shouldUpdate=true, it automatically displays old note and
* button text to UPDATE
*/
private void showNoteDialog(final boolean shouldUpdate, final Note
LayoutInflater layoutInflaterAndroid = LayoutInflater.from(get
View view = layoutInflaterAndroid.inflate(R.layout.note_dialog

AlertDialog.Builder alertDialogBuilderUserInput = new AlertDia


alertDialogBuilderUserInput.setView(view);

final EditText inputNote = view.findViewById(R.id.note);


TextView dialogTitle = view.findViewById(R.id.dialog_title);
dialogTitle.setText(!shouldUpdate ? getString(R.string.lbl_new

if (shouldUpdate && note != null) {


inputNote.setText(note.getNote());
}
alertDialogBuilderUserInput
.setCancelable(false)
.setPositiveButton(shouldUpdate ? "update" : "save", n
public void onClick(DialogInterface dialogBox, int

}
})
.setNegativeButton("cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog
dialogBox.cancel();
}
});

final AlertDialog alertDialog = alertDialogBuilderUserInput.cr


alertDialog.show();

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 29/40
11/05/2018 Android SQLite Database Tutorial

alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickL
@Override
public void onClick(View v) {
// Show toast message when no text is entered
if (TextUtils.isEmpty(inputNote.getText().toString()))
Toast.makeText(MainActivity.this, "Enter note!", T
return;
} else {
alertDialog.dismiss();
}

// check if user updating note


if (shouldUpdate && note != null) {
// update note by it's id
updateNote(inputNote.getText().toString(), positio
} else {
// create new note
createNote(inputNote.getText().toString());
}
}
});
}

/**
* Toggling list and empty notes view
*/
private void toggleEmptyNotes() {
// you can check notesList.size() > 0

if (db.getNotesCount() > 0) {
noNotesView.setVisibility(View.GONE);
} else {
noNotesView.setVisibility(View.VISIBLE);
}
}
}

If you have followed the article carefully, you can see the app running very smoothly as
shown in the video demo.

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 30/40
11/05/2018 Android SQLite Database Tutorial

5. Further Reading
Once you are comfortable with SQLite, check out Android SQLite Database with Multiple
Tables that explains how to handle SQLite when your app needs more than one table.

Happy Coding

Change Log

Updated On 16th Mar 2018 (Updated code and introduced Notes App)

Ravi Tamada
Ravi is hardcore Android programmer and Android programming
has been his passion since he compiled his rst hello-world
program. Solving real problems of Android developers through
tutorials has always been interesting part for him.

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 31/40
11/05/2018 Android SQLite Database Tutorial

D A T A BASE SQ L I TE

RELATED POSTS

Android Easy Runtime Permissions with Dexter

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 32/40
11/05/2018 Android SQLite Database Tutorial

Android Working with ButterKnife ViewBinding Library

Android Working with WebView – Building a Simple In-App Browser

757 Comments Android Hive 


1 Login

Sort by Newest
 Recommend 214 ⤤ Share

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 33/40
11/05/2018 Android SQLite Database Tutorial

Join the discussion…

LOG IN WITH
OR SIGN UP WITH DISQUS ?

Name

eko hendratno • 21 days ago


please request this using fragment on TabLayout with notifDataChange
this app https://imgur.com/a/KmYU7Er
△ ▽ • Reply • Share ›

Barkha Choithani • 23 days ago


Can you please share styles.xml
△ ▽ • Reply • Share ›

Ravi Tamada Mod > Barkha Choithani • 22 days ago

Pls get it from downloaded code. I forgot to add it.


△ ▽ • Reply • Share ›

Jeff • a month ago


How you get row, you always getAll
△ ▽ • Reply • Share ›

ahmed mohamed • a month ago


can't query replace raw query !!
△ ▽ • Reply • Share ›

Dilshod Rakhmanov • 2 months ago


Where can I find the old version of this tutorial? The page was opened, but when
browser was updated, there is new version.
△ ▽ • Reply • Share ›

Ravi Tamada Mod > Dilshod Rakhmanov • 2 months ago

You can download the older code here http://download.androidhive...


△ ▽ • Reply • Share ›

Ravi Tamada Mod > Dilshod Rakhmanov • 2 months ago

Older article is no longer available as it has lot of bugs.


△ ▽ • Reply • Share ›

Maximo • 2 months ago


where are RecyclerTouchListener and MyDividerItemDecoration?
△ ▽ • Reply • Share ›

Ravi Tamada Mod > Maximo • 2 months ago

Oops! Just added them. Check once.


△ ▽ • Reply • Share ›
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 34/40
11/05/2018 Android SQLite Database Tutorial

AbelardoLG • 2 months ago


@Ravi Tamada , could you show the date of publishing of your posts? Also, you
might show the minimum Android OS necessary to run your code. It would be very
useful to know this information for us.

Thanks in advance. :) Best regards.


△ ▽ • Reply • Share ›

Ravi Tamada Mod > AbelardoLG • 2 months ago

Hi Abelardo

All the articles will work with little modifications in case of any problem. I need
to spend at least a month to update them all. Are you facing any problem in
following this article?
△ ▽ • Reply • Share ›

AbelardoLG > Ravi Tamada • 2 months ago


Hi Ravi,

No, I hadn't got any issue with this article. Thanks. :)

My last comment was a suggestion in order to avoid most of questions


set out here. :)
△ ▽ • Reply • Share ›

Ravi Tamada Mod > AbelardoLG • 2 months ago

Okay.
△ ▽ • Reply • Share ›

BM • 2 months ago
thank you for this useful article, as i was trying to create a datebase to store my data.
my app consists of have live score for football matches. Is it possible to have a save
button on every live match that is occurring, when the button is pressed it
automatically saves that specific match in an another activity called bookmark? do
you have any article on that?
△ ▽ • Reply • Share ›

Ravi Tamada Mod > BM • 2 months ago

You won't find the code depending on your requirements. Always you have to
understand the concepts and build the modules on your own.
△ ▽ • Reply • Share ›

Gurpreet Kaur • 2 months ago


Sir look into getContactsCount().. And I think u should remove this
statement.......cursor.close()... Some time it make lots of trouble while copy n pasting
ur code in production... U know what i mean.....
△ ▽ • Reply • Share ›

Ravi Tamada Mod > Gurpreet Kaur • 2 months ago


https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 35/40
11/05/2018 Android SQLite Database Tutorial

The article is updated. Please check once.


△ ▽ • Reply • Share ›

Omar Beshary • 3 months ago


Easy and into the point , thank you .
△ ▽ • Reply • Share ›

hiren gavit • 3 months ago


how to access same sqlite database from different activities ?
△ ▽ • Reply • Share ›

Amjad • 3 months ago


thank you for your tutorial
but after executed i go to Tools->Android->Android Device Monitor ,
I don't find my table in data
△ ▽ • Reply • Share ›

Amjad > Amjad • 3 months ago

△ ▽ • Reply • Share ›

muhammadjawwad rohani > Amjad • a month ago


install api level 21 emulator it will show you ... same issue i face
△ ▽ • Reply • Share ›

Vurjana Govinda • 3 months ago


What is the use of
if (cursor != null)
cursor.moveToFirst();
in the getContact() method.
△ ▽ • Reply • Share ›

Shagun Choudhary • 3 months ago


where is this contactsManager.db database stored in project usually we store it in
assets folder ?
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 36/40
11/05/2018 Android SQLite Database Tutorial
assets folder ?
△ ▽ • Reply • Share ›

Ravi Tamada Mod > Shagun Choudhary • 3 months ago


Here, but you can't access with without root access
/data/data/your.app.package/databases/contactsManager.db
△ ▽ • Reply • Share ›

Gunjan Sharma > Ravi Tamada • 2 months ago


Sir i am facing the same problem. I can not see the package name
under device option.please tell me how can i access the root of the
device.
△ ▽ • Reply • Share ›

Sumaira Ansari • 3 months ago

see more

△ ▽ • Reply • Share ›

muhammadjawwad rohani > Sumaira Ansari • a month ago


just download api level 21 it will show you,face same problem..
△ ▽ • Reply • Share ›

Vratislav Jindra • 3 months ago


Hi, you're not closing the Cursor object in getContact and getAllContacts methods.
Also you're not closing the SQLiteDatabase object in getContact, getAllContacts,
updateContact and getContactsCount methods. Isn't that an issue?

I'm asking because I have a bit more complex app and database, and now I'm
starting to get a few crashes because I had some leaked Cursor objects. So I'm now
closing all Cursors after I'm done with them. But now I also tried enabling strict mode
for my app, and it reveals that I'm not closing the SQLiteDatabase objects and they
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 37/40
11/05/2018 Android SQLite Database Tutorial

can also leak. So should I perhaps keep only one SQLiteDatabase object in the
DatabaseHandler class?

Also, I'm using instances of DatabaseHandler in multiple Fragments (and Activities).


In each Fragment or Activity, there is only one DatabaseHandler object - but isn't that
also an issue? Should I for example keep only one DatabaseHandler object in
memory and pass this object between all my Fragments and Activities? Or keep the
only one DatabaseHandler object accessible via a static method in Application class?

Last but not least - the SQLiteOpenHelper class (and therefore also the
DatabaseHandler class) have a close() method. Should I for example close the
DatabaseHandler object in onPause or onStop in Fragments/Activites to prevent
memory leaks?

Those single Activity examples are really nice to get started, but once things get more
complicated, there is not enough sources and examples on how we should handle
these things.
△ ▽ • Reply • Share ›

Ravi Tamada Mod > Vratislav Jindra • 2 months ago

Sorry mate, I missed out your valuable comment. I got your points. I just
updated the article with an example app. Please check once.
△ ▽ • Reply • Share ›

Vratislav Jindra > Ravi Tamada • 2 months ago


Thanks for the update. I already stopped using SQLiteDatabase in
favor of Firebase DB (I needed real-time sync), but I'll definitely check
that update out to learn something new.
△ ▽ • Reply • Share ›

Fatima Mirza > Vratislav Jindra • 25 days ago


Is there anyway to connect the this sql database to firebase
database?
△ ▽ • Reply • Share ›

Vratislav Jindra > Fatima Mirza • 25 days ago


No. Firebase is a NoSQL database. It doesn't have tables and
relationships - it's just a JSON file. The nature of NoSQL
databases goes against best practices used in SQL - for
example duplicate data can be a good thing here. I had to
scratch 90 % of my app and start over when I was moving from
SQLite to Firebase. But with that I also went for MVP design
pattern, and now that I'm almost finished with it, I'd say it was
worth it. Firebase offers much better sync options than I've ebev
dreamed of, and although querying data can sometimes be a
pain, I don't miss SQLite at all.
△ ▽ • Reply • Share ›

Fatima Mirza > Vratislav Jindra • 25 days ago


:D. Haha, thank you. I am trying to find a way to sync the offline
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 38/40
11/05/2018
, Androidy SQLite Database
y Tutorial
g y y
capabilities for Firebase. However, it simply isn't working (no
errors, just not working. Must be making a mistake somewhere,
can't figure it out). Have you worked on the offline capabilities of
Firebase?
△ ▽ • Reply • Share ›

Vratislav Jindra > Fatima Mirza • 25 days ago


Nah, I haven't looked into that yet. I only enabled cache, and
that seems to work fine.
△ ▽ • Reply • Share ›

Fatima Mirza > Vratislav Jindra • 25 days ago


I have figured it out btw. I have used android hive's code itself.
1△ ▽ • Reply • Share ›

Ravi Tamada Mod > Vratislav Jindra • 2 months ago

Great:)
△ ▽ • Reply • Share ›

Sethu mekala • 3 months ago


please do a video tutorial about this.
△ ▽ • Reply • Share ›

David Richard • 3 months ago


Thank you very much for such a tutorial,I have followed it and it work perfectly for my
app,however, I can not save any pictures in my database.If you can help me saving
my app images in my database it will great..
Thanks in advance.
△ ▽ • Reply • Share ›

Ravi Tamada Mod > David Richard • 3 months ago

We shouldn't save images into Database, instead they should be stored in


Gallery and the image name / path can be saved to database. When
retrieving, you can form the path again and show the image from Gallery.
△ ▽ • Reply • Share ›

Justinas Vijeikis > Ravi Tamada • 3 months ago


I trying to read other column and when i print value into screen i get
text null, maybe i mist something. Please help im trying to do this all
day
△ ▽ • Reply • Share ›

Ravi Tamada Mod > Justinas Vijeikis • 3 months ago

Pls post the related code.


△ ▽ • Reply • Share ›

Slimen Tunis • 3 months ago


Nice article well done
https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 39/40
11/05/2018 Android SQLite Database Tutorial

But I get this error each time I run the app:


no such table
I did exactly as you described here
what can be the cause of this exception ?!!
△ ▽ • Reply • Share ›

Ravi Tamada Mod > Slimen Tunis • 3 months ago


You are modifying the SQLite create table statements, you need to uninstall
and install the app again to see the new tables created.
△ ▽ • Reply • Share ›

tugcekolcu • 3 months ago


Hi,

cursor.moveToFirst() always returns false. What can the problem be ?

Regards,
△ ▽ • Reply • Share ›

Ravi Tamada Mod > tugcekolcu • 3 months ago

Have you checked your Query? Print the query in Log. and see whether it is
proper or not.
△ ▽ • Reply • Share ›

Akshay • 4 months ago


Great article. Easy to follow. Keep up.

https://www.androidhive.info/2011/11/android-sqlite-database-tutorial/ 40/40

Anda mungkin juga menyukai