Data Storage: Part 3 (SQLite)

Slides:



Advertisements
Similar presentations
SQLite is a software library. It is: self-contained + Serverless + zero-configuration transactional = SQL database engine. Most widely deployed. The source.
Advertisements

 data/data-storage.html#pref data/data-storage.html#pref 
ListView Examples. Basic Steps for Creating a Listview 1.Create a layout (e.g., a LinearLayout), with elements for –the ListView (
Android – CoNTENT PRoViders
All About Android Introduction to Android 1. Creating a New App “These aren’t the droids we’re looking for.” Obi-wan Kenobi 1. Bring up Eclipse. 2. Click.
SQLite in Mobile Apps by Dan Youberg. Overview Many well known applications and Internet browsers use SQLite due to its very small size (~250 Kb). Also.
Application Fundamentals. See: developer.android.com/guide/developing/building/index.html.
Cosc 4730 Android TabActivity and ListView. TabActivity A TabActivity allows for multiple “tabs”. – Each Tab is it’s own activity and the “root” activity.
Cosc 5/4730 Android and Blackberry SQLite. For the sql language syntax, please see SQlite documentation –
SQLLite and Java CS-328 Dick Steflik. SQLLite Embedded RDBMS ACID Compliant Size – about 257 Kbytes Not a client/server architecture –Accessed via function.
Phonegap Bridge – File System CIS 136 Building Mobile Apps 1.
CS378 - Mobile Computing Persistence - SQLite. Databases RDBMS – relational data base management system Relational databases introduced by E. F. Codd.
Presenting Lists of Data. Lists of Data Issues involved – unknown number of elements – allowing the user to scroll Data sources – most common ArrayList.
Data Persistence in Android
Chien-Chung Shen Manifest and Activity Chien-Chung Shen
SQLite Database. SQLite Public domain database – Advantages Small (about 150 KB) – Used on devices with limited resources Each database contained within.
Database Rung-Hung Gau Department of Computer Science and Engineering
Chapter 5: Investigate! Lists, Arrays, and Web Browsers.
Android Boot Camp for Developers Using Java, Comprehensive: A Guide to Creating Your First Android Apps Chapter 5: Investigate! Android Lists, Arrays,
Content providers Accessing shared data in a uniform way 1Content providers.
Cosc 5/4730 Android Content Providers and Intents.
Data Storage: Part 4 (Content Providers). Content Providers Content providers allow the sharing of data between applications. Inter-process communication.
Package org.androidtown.database.query; import android.app.Activity; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase;
Frank Xu Gannon University.  Linear Layout  Relative Layout  Table Layout.
Mobile Computing Lecture#11 Adapters and Dialogs.
Address Book App 1. Define styles   Specify a background for a TextView – res/drawable/textview_border.xml.
9 Persistence - SQLite CSNB544 Mobile Application Development Thanks to Utexas Austin.
User Interfaces: Part 1 (View Groups and Layouts).
© 2016 Cengage Learning®. May not be scanned, copied or duplicated, or posted to a publicly accessible website, in whole or in part. Android Boot Camp.
Persistence Dr. David Janzen Except as otherwise noted, the content of this presentation is licensed under the Creative Commons Attribution 2.5 License.
SQLite (part deux) 1 CS440. Traditional Model View Controller (MVC) CS440 2.
Mobile Software Development ISCG 7424 Department of Computing UNITEC John Casey and Richard Rabeder SQLite and Permissions.
Applications with Multiple Activities. Most applications will have more than one activity. The main activity is started when the application is started.
SQLite DB Storing Data in Android RAVI GAURAV PANDEY 1.
Android - SQLite Database 12/10/2015. Introduction SQLite is a opensource SQL database that stores data to a text file on a device. Android comes in with.
SQlite. SQLite is a opensource SQL database that stores data to a text file on a device. Android comes in with built in SQLite database implementation.
Address Book App 1 Fall 2014 CS7020: Game Design and Development.
David Sutton USING CONTENT PROVIDERS. TOPICS COVERED THIS WEEK  Persistence  Introduction to databases  Content providers  Cursors  Cursor adapters.
CHAPTER 9 File Storage Shared Preferences SQLite.
Mobile Programming Lecture 4 Resources, Selection, Activities, Intents.
By: Eliav Menachi.  On Android, all application data (including files) are private to that application  Android provides a standard way for an application.
CMPE419 Mobile Application Development Asst.Prof.Dr.Ahmet Ünveren SPRING Computer Engineering Department Asst.Prof.Dr.Ahmet Ünveren
CS371m - Mobile Computing Persistence - SQLite. 2 In case you have not taken 347: Data Management or worked with databases as part of a job, internship,
Chapter 5: Investigate! Lists, Arrays, and Web Browsers.
Content Providers.
CS499 – Mobile Application Development
Making content providers
Data Storage: Part 3 (SQLite)
Cosc 5/4730 Sqlite primer.
Android Content Providers & SQLite
Mobile Applications (Android Programming)
Data Storage: Part 4 (Content Providers)
SQLite in Android Landon Cox March 2, 2017.
Mobile Application Development BSCS-7 Lecture # 18, 19
ListView: Part 2.
Android Application SQLite 1.
CS499 – Mobile Application Development
Android Database using SQLite
Mobile Application Development Chapter 5 [Persistent Data in Android]
ANDROID UI – FRAGMENTS UNIT II.
Mobile Computing With Android ACST Android Database Storage Part 2
Android Programming Lecture 6
Android Programming Lecture 7
CMPE419 Mobile Application Development
Mobile Computing With Android ACST 4550 Android Database Storage
Android Developer Fundamentals V2
ListView A view that shows items in a vertically scrolling list. The items come from the ListAdapter associated with this view. ListAdapter is used to.
Department of School of Computing and Engineering
SQLLite and Android.
Mobile Programming Dr. Mohsin Ali Memon.
Presentation transcript:

Data Storage: Part 3 (SQLite)

SQLite SQLite is a software library that provides full relational database capability for Android applications. Each application that uses SQLite has its own instance of the database, which is by default accessible only from the application itself. The database is stored in the following folder: /data/data/<package name>/databases A Content Provider can be used to share the database information with other applications. ©SoftMoore Consulting

Features of SQLite ACID transactions (atomic, consistent, isolated, and durable) Zero-configuration – no setup or administration. Implements most of SQL92. Complete database is stored in a single file. Supports terabyte-sized databases and gigabyte-sized strings and blobs. Small code footprint (less than 325KB fully configured). Self-contained: no external dependencies. C source code is in the public domain. ©SoftMoore Consulting

SQLite Datatypes Most SQL database systems use static typing; i.e., the type of a value is determined by the column in which the value is stored. SQLite uses a more general dynamic type system – the type of a value is associated with the value itself, not with its column. Think of column types as hints. It is possible to store a string in an integer column and vice versa. ©SoftMoore Consulting

SQLite Datatypes (continued) Each value stored in an SQLite database has one of the following storage classes: NULL. The value is a NULL value. INTEGER. The value is a signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value. REAL. The value is a floating point value, stored as an 8-byte IEEE floating point number. TEXT. The value is a text string, stored using the database encoding (UTF-8, UTF-16BE or UTF-16LE). BLOB. The value is a blob of data, stored exactly as it was input. Note that a storage class is slightly more general than a type. ©SoftMoore Consulting

SQLite Datatypes (continued) Each column in a SQLite database is assigned one of the following type affinities: TEXT – NUMERIC INTEGER – REAL NONE SQLite does not have a separate Boolean storage class. Boolean values are stored as integers 0 (false) and 1 (true). SQLite does not have a storage class set aside for storing dates and/or times. Instead, the built-in date and time functions of SQLite are capable of storing dates and times as TEXT, REAL, or INTEGER values. ©SoftMoore Consulting

Using the sqlite3 Command-Line In addition to accessing a SQLite database from an Android application, it is also possible to interact with the database on a virtual device using the sqlite3 command-line tool via the Android Debug Bridge (ADB) remote shell. Preparation add an environment variable ANDROID_SDK_HOME; e.g., ANDROID_SDK_HOME=C:\Java\android-sdk-windows add the following to your PATH environment variable: %ANDROID_SDK_HOME% %ANDROID_SDK_HOME%\tools %ANDROID_SDK_HOME%\platform-tools ©SoftMoore Consulting

Using the sqlite3 Command-Line (continued) Start a virtual device (emulator) and launch the ADB shell from a command prompt C:\>adb shell Connect to the database # sqlite3 /data/data/edu.citadel.android.emergency/databases/emergency.db sqlite3 /data/data/edu.citadel.android.emergency/databases/emergency.db SQLite version 3.6.22 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> Enter SQL statements and SQLite commands at the prompt. SQL statements must be terminated by a semicolon. SQLite commands start with a period. SQL statements and SQLite commands are echoed Note: Does not work with a real device. response ©SoftMoore Consulting

Selected SQLite Commands .databases List names/files of attached databases .exit Exit this program .header(s) ON|OFF Turn display of headers on or off .help Show all SQLite commands .import FILE TABLE Import data from FILE into TABLE .mode column Left-aligned columns. (See .width) .read FILENAME Execute SQL in FILENAME .schema Show the CREATE statements .width NUM NUM … Set column widths for “column” mode ©SoftMoore Consulting

Example: Using the sqlite3 Command-Line sqlite> .mode column .mode column sqlite> .width 3 15 12 .width 3 15 12 sqlite> .headers ON .headers ON sqlite> select * from emergency_contacts; select * from emergency_contacts; _id name phone_num --- --------------- ------------ 1 Emergency - 911 911 2 Home 843-123-4567 3 Kayran - Cell 843-234-5678 4 John - Cell 847-345-6789 5 Robert - Cell 202-456-7890 6 Angela - Cell 434-567-8901 sqlite> ©SoftMoore Consulting

Developing Applications Using SQLite Primary classes and interfaces android.database.sqlite.SQLiteDatabase android.database.sqlite.SQLiteOpenHelper (abstract) android.database.Cursor (interface) Using adapters to connect data and views Understanding relational databases and SQL ©SoftMoore Consulting

Class SQLiteOpenHelper Class SQLiteOpenHelper is an abstract helper class in package android.database.sqlite that can be used to manage database creation and versioning. Class SQLiteOpenHelper will open the database if it exists create the database if it does not exist upgrade the database as necessary To use class SQLiteOpenHelper, create a subclass that overrides abstract methods onCreate(), onUpgrade(). Note: Database names must be unique within an application, not across all applications. ©SoftMoore Consulting

Selected Methods in Class SQLiteOpenHelper SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) constructor to initialize a SQLiteOpenHelper object the factory parameter can be null for the default value void close() close an open database SQLiteDatabase getReadableDatabase() create and/or open a database for reading only SQLiteDatabase getWritableDatabase() create and/or open a database for both reading and writing ©SoftMoore Consulting

Selected Methods in Class SQLiteOpenHelper (continued) abstract void onCreate(SQLiteDatabase db) called when the database is created for the first time Note: You can “preload” a set of database values in this method. void onOpen(SQLiteDatabase db) called when the database is opened abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) called when the database needs to be upgraded ©SoftMoore Consulting

Contract Class Applications that use a database and/or implement a content provider (see next section) often implement a “contract” class. A contract class defines constants that help applications work with the content URIs, column names, intent actions, and other features of a content provider. Contract classes are not included automatically with a provider; the provider’s developer has to define them and make them available to other developers. ©SoftMoore Consulting

Example: Contract Class public final class EmergencyContract { public static final String DB_NAME = "emergency.db"; public static final int DB_VERSION = 1; public static final String TABLE_NAME = "emergency_contacts"; public static final String[] COLUMNS = { "_id", "name", "phone_num" }; public static final String AUTHORITY = "edu.citadel.android.emergency"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + TABLE_NAME); private EmergencyContract() {} // prevent instantiation } Useful for adding a content provider. ©SoftMoore Consulting

Example: Using SQLiteOpenHelper public class EmergencyDbOpenHelper extends SQLiteOpenHelper { /** * Construct a SQLiteOpenHelper object for the * emergency database. */ public EmergencyDbOpenHelper(Context context) super(context, EmergencyContract.DB_NAME, null, EmergencyContract.DB_VERSION); } (continued on next slide) ©SoftMoore Consulting

Example: Using SQLiteOpenHelper (continued) @Override public void onCreate(SQLiteDatabase db) { String createSql = "create table " + EmergencyContract.TABLE_NAME + "(" + " _id integer primary key autoincrement," + " name text not null," + " phone_num text not null" + ")"; db.execSQL(createSql); insertContacts(db); } (continued on next slide) ©SoftMoore Consulting

Example: Using SQLiteOpenHelper (continued) @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // This is version 1 so no actions are required. // Possible actions include dropping/recreating // tables, saving/restoring data in tables, etc. } private void insertContacts(SQLiteDatabase db) // perform inserts to initialize the database ©SoftMoore Consulting

Class SQLiteDatabase Class SQLiteDatabase (in package android.database.sqlite) exposes methods to manage a SQLite database. Class SQLiteDatabase has methods to create, delete, execute SQL commands, and to perform other common database management tasks. Class SQLiteDatabase has several “convenience” methods for constructing SQL queries, inserts, etc. Alternatively, other methods can be used to directly execute SQL commands passed as string parameters. ©SoftMoore Consulting

Selected Methods in Class SQLiteDatabase void beginTransaction() Begins a transaction. int delete(String table, String whereClause, String[] whereArgs) Convenience method for deleting rows in the database. void endTransaction() End a transaction. void execSQL(String sql) Execute a single SQL statement that does not return data. long insert(String table, String nullColumnHack, ContentValues values) Convenience method for inserting a row into the database. ©SoftMoore Consulting

Selected Methods in Class SQLiteDatabase (continued) Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) Query the given table, returning a Cursor over the result set. Cursor rawQuery(String sql, String[] selectionArgs) Runs the provided SQL and returns a Cursor over the result set. int update(String table, ContentValues values, String whereClause, String[] whereArgs) Convenience method for updating rows in the database. ©SoftMoore Consulting

Example: Using Query Methods in Class SQLiteDatabase SQLiteOpenHelper openHelper = new EmergencyDbOpenHelper(this); SQLiteDatabase db = openHelper.getReadableDatabase(); Query using convenience methods String tableName = "emergency_contacts"; String[] columns = {"name", "phone_num"}; String orderBy = "name"; Cursor cursor = db.query(tableName, columns, null, null, null, null, orderBy); Query using method rawQuery() String query = "select name, phone_num" + " from emergency_contacts" + " order by name"; Cursor cursor = db.rawQuery(query, null); ©SoftMoore Consulting

Example: Using Insert Methods in Class SQLiteDatabase SQLiteOpenHelper openHelper = new EmergencyDbOpenHelper(this); SQLiteDatabase db = openHelper.getWritableDatabase(); Insert using convenience methods String tableName = "emergency_contacts"; ContentValues values = new ContentValues(); values.put("name", "Emergency – 911"); values.put("phone_num", "911"); db.insert(tableName, null, values); Insert using method execSQL() String insertSql = "insert into emergency_contacts" + " (name, phone_num) values" + " (\"Emergency - 911\", \"911\")"; db.execSQL(insertSql); ©SoftMoore Consulting

Interface Cursor Interface Cursor (in package android.database) is used to iterate over the rows returned by a “select” query. analogous to a Java Iterator or a JDBC ResultSet Interface Cursor provides random read-write access to the result set returned by a database query. Methods in interface Cursor can be used to position the cursor within the result set (“move” methods) to retrieve column values from the row (“get” methods) to provide metadata about the query (e.g., getColumnNames()). ©SoftMoore Consulting

Selected Methods in Interface Cursor int getColumnIndex(String columnName) Returns zero-based index for the given column name double getDouble(int columnIndex) int getInt(int columnIndex) long getLong(int columnIndex) String getString(int columnIndex) boolean move(int offset) boolean moveToFirst() boolean moveToNext() boolean moveToPosition(int position) Returns the value of the requested column as the specified type. Moves the cursor as specified. ©SoftMoore Consulting

Using a Cursor Similar to using a JDBC ResultSet, initially a cursor is positioned before the first row. The various “move” methods can be used to move the cursor to a row. The moveToNext() method moves the cursor to the next row. Since it returns false when there are no more rows, it can be used in a while loop to iterate through the rows of a cursor. Example while (cursor.moveToNext()) { ... // retrieve/process data for one row } ©SoftMoore Consulting

Example: Using Interface Cursor SQLiteDatabase db = openHelper.getReadableDatabase(); String query = "select * from emergency_contacts"; Cursor cursor = db.rawQuery(query, null); while (cursor.moveToNext()) { int id = cursor.getInt(0); String name = cursor.getString(1); String phoneNum = cursor.getString(2); String message = "ID: " + id + ", Name: " + name + ", Phone Number: " + phoneNum; Toast toast = Toast.makeText(Emergency.this, message, Toast.LENGTH_SHORT); toast.show(); } ©SoftMoore Consulting

Data Binding The binding of data to views is simplified by using a few specialized classes and interfaces. Class ListActivity can be used to display a list of items by binding to a data source such as an array or Cursor. Class AdapterView is a view group whose children are determined by an Adapter. Commonly used subclasses include ListView and Spinner. Interface Adapter acts as a bridge between an AdapterView and the underlying data for that view. Commonly used classes that extend Adapter include ArrayAdapter<T> and CursorAdapter. ©SoftMoore Consulting

Data Binding (continued) ListActivity (an activity) AdapterView (a view group) Adapter data source ©SoftMoore Consulting

Class ListActivity Class ListActivity is a subclass of Activity used to display a list of items by binding to a data source such as an array or Cursor. It also exposes event handlers when the user selects an item. A ListActivity uses two layouts, a default layout for the screen and a row layout for the individual rows in the list. The default layout contains a ListView object with the id “@android:id/list” controlling the overall display of the list, and it can optionally contain another view with an id of "@android:id/empty" to display when the list is empty. ©SoftMoore Consulting

Selected Methods in Class ListActivity ListAdapter getListAdapter() Get the ListAdapter associated with this activity’s ListView. ListView getListView() Get the activity’s list view widget. void setListAdapter(ListAdapter adapter) Set the ListAdapter for the list view. void onListItemClick(ListView l, View v, int position, long id) Called when an item in the list is selected. (Equivalent to implementing an OnItemClickListener for the list view − see next slide.) ©SoftMoore Consulting

Selected Methods in Class ListActivity (continued) Implementing method onListItemClick() is equivalent to implementing an OnItemClickListener for the list view. ListView lv = getListView(); lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) ... } }); The above approach must be used if you want to implement a method to respond to long clicks; i.e., you must implement OnItemLongClickListener() for the list view. ©SoftMoore Consulting

Using Class ListActivity Extend class ListActivity (rather than Activity) public class MainActivity extends ListActivity { ... } Define the default layout for the screen. Define the row layout for the individual rows. ©SoftMoore Consulting

Example: Default Layout for ListActivity <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@android:id/list" android:layout_height="wrap_content" android:fastScrollEnabled="true" android:scrollbarSize="@dimen/scrollbarSize" android:divider="@color/dividerColor" android:dividerHeight="@dimen/dividerHeight" android:layout_weight="1.0"/> Note the id! No “+” sign tells Android to use an existing id and not to generate a new one.) (continued on next slide) ©SoftMoore Consulting

Example: Default Layout for ListActivity (continued) <TextView android:id="@android:id/empty" android:layout_width="match_parent" android:layout_height="wrap_content" android:textStyle="bold" android:textSize=“@dimen/emptyTextSize" android:text="@string/emptyList" /> ... other (e.g., a button) </LinearLayout> Note the id! ©SoftMoore Consulting

Example: Layout for each Row in the ListActivity <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:padding=" @dimen/contactPadding "> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textStyle="bold" android:textSize=" @dimen/nameTextSize " /> (continued on next slide) ©SoftMoore Consulting

Example: Row Layout for Each Row in the ListActivity (continued) <TextView android:id="@+id/phoneNum" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="@dimen/phoneTextSize" /> </LinearLayout> File name is contact.xml. ©SoftMoore Consulting

Class SimpleCursorAdapter Class CursorAdapter maps columns from a cursor to TextViews or ImageViews defined in an XML file. Class SimpleCursorAdapter is a subclass of CursorAdapter that is simple and easy to use. To use a SimpleCursorAdapter, specify the columns from the cursor, the views to display the columns (e.g., TextViews), and the XML files that defines the appearance of these views (i.e., the default layout and the row layout). Note: The Cursor must include a column named "_id" or this class will not work. ©SoftMoore Consulting

Example: SimpleCursorAdapter // in MainActivity, which extends ListActivity private static final String[] COLUMNS = { "name", "phone_num" }; private static final int[] VIEWS = { R.id.name, R.id.phoneNum }; private SQLiteOpenHelper openHelper; ... @Override public void onCreate(Bundle savedInstanceState) { openHelper = new EmergencyDbOpenHelper(this); setContactListAdapter(); } (continued on next slide) ©SoftMoore Consulting

Example: SimpleCursorAdapter (continued) private void setContactListAdapter() { try String query = "select * from " + EmergencyContract.TABLE_NAME; SQLiteDatabase db = openHelper.getReadableDatabase(); Cursor cursor = db.rawQuery(query, null); SimpleCursorAdapter adapter = new SimpleCursorAdapter (this, R.layout.contact, cursor, COLUMNS, VIEWS, 0); setListAdapter(adapter); } catch (Exception ex) String errorMsg = "Error retrieving emergency contacts"; Log.e(LOG_TAG, errorMsg, ex); layout for rows these columns get mapped to these views ©SoftMoore Consulting

Comments on the Example Not every column returned by the cursor needs to be mapped to a view; e.g., _id is not mapped to a view in this example. Calling setContactListAdapter() after a change to the database will requery the database and reset the list in the display. ©SoftMoore Consulting

Displaying the ListView ©SoftMoore Consulting

Example: Handling Item Click Events @Override protected void onListItemClick(ListView listView, View view, int position, long id) { ViewGroup vg = (ViewGroup) view; TextView nameView = (TextView) vg.getChildAt(0); String name = nameView.getText().toString(); TextView phoneNumView = (TextView) vg.getChildAt(1); String phoneNum = phoneNumView.getText().toString(); callContact(phoneNum); } Alternatively, use ListView lv = getListView(); lv.setOnItemClickListener(…); ©SoftMoore Consulting

Example: Handling Item Click Events (continued) private void callContact(String phoneNum) { Uri uri = Uri.parse("tel:" + phoneNum); Intent intent = new Intent(Intent.ACTION_CALL, uri); startActivity(intent); } Important: When making a phone call, remember to add <uses-permission android:name="android.permission.CALL_PHONE" /> before the application element in AndroidManifest.xml. ©SoftMoore Consulting

Parameters to Method onListItemClick() parent: The ListView where the click happened. view: The view within the ListView that was clicked position: The position of the view in the adapter. 0-based position numbers id: The row id of the item that was clicked. from the database ©SoftMoore Consulting

Comments on Using an Unmanaged Cursor The approach described in this section for creating a ListView using a SimpleCursorAdapter and a SQLite database is acceptable if the database is relatively small and the data doesn’t change (no re-query necessary). For larger databases or when re-query is necessary: Older versions of Android used a method named startManagingCursor(), deprecated in API 11, that managed the cursor’s lifecycle based on the activity’s lifecycle. As described in subsequent sections, the more modern approach is to implement a content provider and to use classes CursorLoader and LoaderManager. ©SoftMoore Consulting

Relevant Links Data Storage Class SQLiteDatabase http://developer.android.com/guide/topics/data/data-storage.html Class SQLiteDatabase http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html Class SQLiteOpenHelper http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html SQLite (home page) http://www.sqlite.org/ Android Database Example (slightly different approach) http://examples.javacodegeeks.com/android/core/database/android-database-example/ Appendix H - SQL Primer PowerPoint Slides for this course ©SoftMoore Consulting