51
MobAppDev Structured Data Persistence on Android Devices with SQLite Vladimir Kulyukin www.vkedco.blogspot.com

MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Embed Size (px)

Citation preview

Page 1: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

MobAppDev

Structured Data Persistence on Android Devices with SQLite

Vladimir Kulyukin

www.vkedco.blogspot.com

Page 2: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Outline

● Persisting of Structured Data with SQL Databases

● Lite Intro to SQLite● SQLite Database Inspection● SQLite by Example● Creation & Population of SQLite Databases

Page 3: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Persistence of Structured Data with

SQL Databases

Page 4: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

SharedPreferences: Pros & Cons

● Pros Lightweight Easy to code and debug

● Cons Slow with large data volumes Not helpful with highly structured data when key/value

pairs are insufficient Entire file needs to be read and parsed to access data Takes up more space because XML is used for storage

Page 5: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

SQL Databases: Pros & Cons● Pros

Flexible with structured data Scalable: can handle large data volumes Robust: can handle incremental changes Responsive: can handle flexible queries

● Cons Heavyweight: more code & more memory Maintenance: harder to code & debug

Page 6: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Three-Tier Data Management Model

XML

Java Objects SQLite DB

GUI

Object Inflation

Objects to SQLite Records

Object Visualization

SQLite Records to Objects

Page 7: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Database Design

● Standard database design practices also apply on Android● A key design principle is to manage space well: reduction

redundancy via database normalization● The objective of database normalization is to decompose relations

with anomalies to produce smaller, well structured relations● Database design is more an art than a science: takes experience &

practice● Helpful resource: en.wikipedia.org/Database_normalization

Page 8: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Tables & Data Types

● Database is a persistent collection of structured data● Data are structured because they are organized in tables● A Table is similar to an Excel spreadsheet except that its

columns have standard SQL data types (e.g., TEXT, INTEGER, FLOAT, etc.)

● In terms of Object-Oriented Modeling, each table represents an Class (e.g., Book, Author) and each column represents an Attribute

● Each table row represents an Object of a specific Class

Page 9: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Primary Keys● In many tables, the ID column represents the

primary key● The primary key is the key that uniquely

identifies the row entry object● When design an SQL table, it is typical (not

necessary!) to specify the primary key as an integer and mark it as auto-incrementable: this way every inserted row is guaranteed to have a unique primary key

Page 10: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Lite Intro to SQLite

Page 11: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

What is SQLite?● SQLite is a relational database management system

(RDBMS)● SQLite is a compact C library that is part of the Android

software stack● Since it is a library, it can be integrated into each

application without external dependencies: this simplifies transactions and synchronizations, minimizes latency

● If you know or have worked with SQL, you will have no problem with SQLite

Page 12: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Where to Look for Application-Specific SQLite Databases

● Every application can create its own database over which it has complete control

● SQLite databases should be considered only when you need to manage complex, structured data

● Databases are stored in /data/data/<package_name>/databases/● For example, if the package is org.vkedco.mobappdev.simple_db_app_01,

then look for the databases in

/data/data/org.vkedco.mobappdev.simple_db_app_01/databases/

Page 13: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

SQL vs SQLite Data Typing

● SQL engines typically use static typing: datatype of a value is determined by the column in which the value is stored

● SQLite engines use dynamic typing: datatype of a value is associated with the value not the column in which it is stored

● Basic SQL vs. SQLite tradeoff: security and safety (SQL) vs. flexibility (SQLite)

● SQLite rule of thumb: do not expose your SQLite API to third parties

Page 14: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

SQLite Datatypes

● NULL – the value is NULL● INTEGER – signed integers; signed integer can be stored as

1, 2, 3, 4, 5, 6, or 8 bytes; the storage size depends on the value magnitude

● REAL – float-point numbers; stored as 8 bytes● TEXT – text string; stored according to the database

encoding (e.g., UTF-8)● BLOB – data blob, typically stored as array of bytes

Page 15: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Sample Book Database

Page 16: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

SQLite Database

● Our sample book database on Sufi poetry will contain two tables

● The first table consists of five book records● The second table consists of two book authors● The exact tables are given on the next two

slides

Page 17: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Book Table

ID Title Author Translator ISBN Price

1 The Essential Rumi Jalal al-Din Rumi

C. Barks, J. Moyne

9780062509581 17.51

2 The Illuminated Rumi Jalal al-Din Rumi

C. Barks 9780767900027 25.04

3 A Year with Rumi: Daily Readings

Jalal al-Din Rumi

C. Barks 9780060845971 14.92

4 A Year with Hafiz: Daily Contemplations

Hafiz D. Ladinsky 9780143117544 12.24

5 The Gift Hafiz D. Ladinsky 9780140195811 12.24

- Book is a Class - ID, Title, Author, Translator, ISBN, Price are Attributes - Rows 1 – 5 are Book Objects

Page 18: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Author Table

ID Name BirthYear DeathYear Country

1 Jalal al-Din Rumi 1207 1273 Persia

2 Hafiz 1325 1389 Persia

- Author is a Class - ID, Name, BirthYear, DeathYear, Country, are Attributes - Row 1 is an Author Object - Row 2 is an Author Object

Page 19: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Command Line DB Access

Suppose that you have created a database such as the book database shown in the previous slides (we will learn how to do this shortly) and want to interact with it. Here is how:

1. Open a command line

2. CD into platform-tools directory

3. Connect to the device (e.g., adb -e shell)

4. CD into the database directory: cd /data/data/<package>databases>

5. Execute: sqlite3 <database_name> (e.g. sqlite3 book_info.db)

Now you can interct with book_info.db via sqlite shell

6. Execute .quit to quit

Page 20: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Connecting to ADB

You can use adb -e shell to connect to the emulator;

Then you can use standard Linux commands such as ls

Page 21: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

CD Into Data/Data/<APP PACKAGE>

1. CD Into data/data/ 2. LS 3. Look for APP PACKAGE 4. CD into it 5. LS to find database names

Page 22: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Discovering TABLE Schemas

● A Table Schema is the specification of column values and types for a given table

● To access table schemas for a DB:

1. Get in to the sqlite shell

2. Execute: .schema

You should see something like:

CREATE TABLE android_metadata (locale TEXT);

CREATE TABLE author (ID integer primary key autoincrement, Name text not null, ...);

CREATE TABLE book (ID integer primary key autoincrement, Title text not null, ...);

Page 23: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Using SQLite3 Interpreter

Page 24: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

SQLite by Example

Page 25: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Displaying Tables

Here is how you can display the entire table:

SELECT * FROM <TABLE>;

Examples: SELECT * FROM BOOK; SELECT * FROM AUTHOR;

Page 26: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Column Projections

To project the values of specific columns for each record:

SELECT COLUM_NAME_1, …, COLUMN_NAME_n FROM <TABLE>;

Examples:

SELECT Author, Title FROM BOOK;

SELECT Title, Author FROM BOOK;

Page 27: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Retrieval of Records with Specific Values

To retrieve records with specific values, use the WHERE clause:

SELECT COLUM_NAME_1, …, COLUMN_NAME_n FROM <TABLE> WHERE <COL_VAL_SPEC>;

Examples:

SELECT Title FROM BOOK WHERE ID = 3;

SELECT Title, Author FROM BOOK WHERE ID < 3;

Page 28: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Record Ordering

To order records by attributes, use the ORDER BY clause:

SELECT COLUM_NAME_1, …, COLUMN_NAME_n FROM <TABLE> ORDER BY COL_NAME Asc/Desc;

Examples:

SELECT Title, Author FROM BOOK ORDER BY Price Asc;

SELECT Title, Author FROM BOOK ORDER BY Price Desc;

Page 29: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Creation & Population of

SQLite Databases

Page 30: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Book DB Application

Write an Android application that creates and populates an SQLite database on Sufi poetry from an XML specification of the book title and book author tables. The book titles are displayed in a ListView. When the user clicks on an book title, its database record is displayed in a Toast. The application does OO modeling of SQLite tables as Java classes.

Book DB Application

source code is here

Page 31: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Sample Screenshots

Page 32: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Book Table as Book Class

public class Book {

protected String mTitle;

protected String mAuthor;

protected String mTranslator;

protected String mISBN;

protected float mPrice;

// rest of code

}

public class Book {

protected String mTitle;

protected String mAuthor;

protected String mTranslator;

protected String mISBN;

protected float mPrice;

// rest of code

}

source code is in Book.java

Page 33: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Author Table as Author Class

public class Author {

protected String mName;

protected int mBirthYear;

protected int mDeathYear;

protected String mCountry;

// rest of code

}

source code is in Author.java

Page 34: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

XML DB Table Specs

● XML DB table specs can come in a variety of formats and from a variety of resources

● Each XML table spec must describe inflatable row records; table specs inflated into table Java objects

● Table specs give you the flexibility to persist (save) Java into SQLite databases or Object databases

● Source of table specs can vary from local XML files, remote XML files, RSS feeds, etc

Page 35: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

XML Specs of Book Title Table

<string-array name="book_title_table">

<item>The Essential Rumi;Jalal adDin Rumi;C. Barks, J. Moyne;9780062509581;17.51</item>

<item>The Illuminated Rumi;Jalal adDin Rumi;C. Barks;9780767900027;25.04</item>

<item>A Year with Rumi: Daily Readings;Jalal adDin Rumi;C. Barks;9780060845971;14.92</item>

<item>A Year with Hafiz: Daily Contemplations;Hafiz;D. Ladinsky;9780143117544;12.24</item>

<item>The Gift;Hafiz;Daniel Ladinsky;9780140195811;12.24</item>

</string-array>

XML source is in strings.xml

Page 36: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

XML Specs of Book Author Table

<string-array name="book_author_table">

<item>Jalal adDin Rumi;1207;1273;Persia</item>

<item>Hafiz;1325;1389;Persia</item>

</string-array>

XML source is in strings.xml

Page 37: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Design & Implementation of

Database Adapters

Page 38: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

DB XML Specs Table Inflation

● Typically there is a class that creates objects from XML table specs

● In our case, we simply inflate XML string-arrays and create objects from XML strings

● Database adapter classes are intermediaries b/w data and SQLite databases; they typically extend SQLiteOpenHelper

● Each object is then given to the database adapter for SQLite persistence

Page 39: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Population of SQLite DB

● Once we have an adapter class, we can use it to populate the SQLite DB

● This is done in SufiPoetryBooksDBMainAct.java by the method populateBookList()

● This method parses XML, creates Book and Author objects and uses the methods insertUniqueBook() and insertUniqueAuthor() defined in SufiPoetryBooksDBHelper.java

Page 40: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Population of SQLite DB: XML Inflation

// 1. open db

mDBHelper.open();

// 2. Read XML arrays or use an XML parser to parse XML

String[] book_table = mRes.getStringArray(R.array.book_table);

String[] author_table =

mRes.getStringArray(R.array.author_table);

Page 41: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Population of SQLite DB: Population of Book Table

// 3. Inflate book table xml specs into Book objects and place them into SQLite DB

String[] book_entry_parts;

for(String book_entry: book_table) {

book_entry_parts = book_entry.trim().split(XML_ENTRY_SEPARATOR);

mDBHelper.insertUniqueBook(new Book(book_entry_parts[0], // title

book_entry_parts[1], // author

book_entry_parts[2], // translator

book_entry_parts[3], // isbn

Float.parseFloat(book_entry_parts[4]) // price

));

}

Page 42: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Population of SQLite DB: Population of Author Table// 4. Inflate author table xml specs into Author objects and insert them into DB

String[] author_entry_parts;

for(String author_entry: author_table) {

author_entry_parts = author_entry.trim().split(XML_ENTRY_SEPARATOR);

mDBHelper.insertUniqueAuthor(

new Author(author_entry_parts[0], // author's name

Integer.parseInt(author_entry_parts[1]), // author's birth year

Integer.parseInt(author_entry_parts[2]), // author's death year

author_entry_parts[3]) // author's country

);

}

// 5. Close db

mDBHelper.close();

Page 43: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Storing Images in SQLite Databases

Page 44: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Modification of Book DB Application

Let us extend our book db application so that it has an SQLite table that stores book cover images and maps them into book ISBNs.

source is here

Page 45: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

BOOK_COVER_IMAGE Table

Data Rows

9780062509581|BLOB_01

9780767900027|BLOB_02

9780060845971|BLOB_03

9780143117544|BLOB_04

9780140195811|BLOB_05

Database Schema

ISBN | Image (BLOB)

Page 46: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Image Blobs from Amazon

BLOB_01 BLOB_02 BLOB_03 BLOB_04 BLOB_05

Page 47: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

OO Modeling of Book Cover Image Table

public class BookCoverImage {

protected String mISBN;

protected byte[ ] mCoverRef;

public BookCoverImage(String isbn, byte[] coverRef) {

mISBN = isbn; mCoverRef = coverRef;

}

public String getISBN() { return mISBN; }

public byte[] getCoverRef() { return mCoverRef; }

}

Page 48: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Images Into Byte Arrays Bitmap bmp = null; Resources mRes = cntxt.getResources();

// 1. Construct a bitmap from a source image

bmp = BitmapFactory.decodeResource(mRes, R.drawable.essential_rumi_cover);

// 2. Create a ByteArrayOutputStream

ByteArrayOutputStream bos = new ByteArrayOutputStream();

// 3. Compress the bitmap into the ByteArrayOutputStream

byte[] bitmapbytes = null; bmp.compress(CompressFormat.PNG, 0, bos);

// 4. Get the bytes the bitmap's bytes from the ByteArrayOutputStream

bitmapbytes = bos.toByteArray();

// 5. Recycle the bitmap so that it can be used again

bmp.recycle();

// 6. Close the ByteArrayOutputStream

try { bos.close(); } catch (IOException e) { e.printStackTrace(); }

Page 49: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Images Into Byte Arrays Bitmap bmp = null; Resources mRes = cntxt.getResources();

// 1. Construct a bitmap from a source image

bmp = BitmapFactory.decodeResource(mRes, R.drawable.essential_rumi_cover);

// 2. Create a ByteArrayOutputStream

ByteArrayOutputStream bos = new ByteArrayOutputStream();

// 3. Compress the bitmap into the ByteArrayOutputStream

byte[] bitmapbytes = null; bmp.compress(CompressFormat.PNG, 0, bos);

// 4. Get the bytes the bitmap's bytes from the ByteArrayOutputStream

bitmapbytes = bos.toByteArray();

// 5. Recycle the bitmap so that it can be used again

bmp.recycle();

// 6. Close the ByteArrayOutputStream

try { bos.close(); } catch (IOException e) { e.printStackTrace(); }

Page 50: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

Inserting Images into SQLite Databases // Assume that bci is a BookCoverImage object.

byte[] bitmapbytes = bci.getCoverRef();

// we assume that bitmapbytes is not null

ContentValues newBookCoverRef = new ContentValues();

// COVER_IMAGE_ISBN_COL_NAME is a string constant

newBookCoverRef.put(COVER_IMAGE_ISBN_COL_NAME, bci.getISBN());

newBookCoverRef.put(COVER_IMAGE_IMG_COL_NAME, bitmapbytes);

// mDb is a database reference of SQLiteDatabase class.

return mDb.insertWithOnConflict(BOOK_COVER_IMAGE_TABLE,

null, newBookCoverRef,

SQLiteDatabase.CONFLICT_REPLACE);

Page 51: MobAppDev (Fall 2014): Structured Data Persistence on Android Devices with SQLite

References● en.wikipedia.org/Database_normalization● http://developer.android.com/tools/help/adb.html● http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html