Extract and check in NotepadCodeLab.zip for change tracking

The 3-part Notepad tutorial is currently only available in the zip archive
frameworks/base/docs/html/guide/tutorials/notepad/codelab/NotepadCodeLab.zip.
This CL adds the uncompressed code to the repository so that there is a
paper trail of future changes to the code.
diff --git a/tutorials/NotepadCodeLab/Notepadv1/AndroidManifest.xml b/tutorials/NotepadCodeLab/Notepadv1/AndroidManifest.xml
new file mode 100755
index 0000000..33f30da
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1/AndroidManifest.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.demo.notepad1">
+    <application android:icon="@drawable/icon">
+        <activity android:name=".Notepadv1" android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest> 
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv1/res/drawable/icon.png b/tutorials/NotepadCodeLab/Notepadv1/res/drawable/icon.png
new file mode 100755
index 0000000..64e3601
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1/res/drawable/icon.png
Binary files differ
diff --git a/tutorials/NotepadCodeLab/Notepadv1/res/layout/notepad_list.xml b/tutorials/NotepadCodeLab/Notepadv1/res/layout/notepad_list.xml
new file mode 100755
index 0000000..154888d
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1/res/layout/notepad_list.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv1/res/values/strings.xml b/tutorials/NotepadCodeLab/Notepadv1/res/values/strings.xml
new file mode 100755
index 0000000..5698961
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Notepad v1</string>
+    <string name="no_notes">No Notes Yet</string>
+</resources>
diff --git a/tutorials/NotepadCodeLab/Notepadv1/src/com/android/demo/notepad1/Notepadv1.java b/tutorials/NotepadCodeLab/Notepadv1/src/com/android/demo/notepad1/Notepadv1.java
new file mode 100755
index 0000000..43e7a77
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1/src/com/android/demo/notepad1/Notepadv1.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.demo.notepad1;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+
+public class Notepadv1 extends Activity {
+	private int mNoteNumber = 1;
+    
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        // TODO Auto-generated method stub
+        return super.onCreateOptionsMenu(menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        // TODO Auto-generated method stub
+        return super.onOptionsItemSelected(item);
+    }
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv1/src/com/android/demo/notepad1/NotesDbAdapter.java b/tutorials/NotepadCodeLab/Notepadv1/src/com/android/demo/notepad1/NotesDbAdapter.java
new file mode 100755
index 0000000..6f85bbd
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1/src/com/android/demo/notepad1/NotesDbAdapter.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.demo.notepad1;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+/**
+ * Simple notes database access helper class. Defines the basic CRUD operations
+ * for the notepad example, and gives the ability to list all notes as well as
+ * retrieve or modify a specific note.
+ * 
+ * This has been improved from the first version of this tutorial through the
+ * addition of better error handling and also using returning a Cursor instead
+ * of using a collection of inner classes (which is less scalable and not
+ * recommended).
+ */
+public class NotesDbAdapter {
+
+    public static final String KEY_TITLE = "title";
+    public static final String KEY_BODY = "body";
+    public static final String KEY_ROWID = "_id";
+
+    private static final String TAG = "NotesDbAdapter";
+    private DatabaseHelper mDbHelper;
+    private SQLiteDatabase mDb;
+    
+    /**
+     * Database creation sql statement
+     */
+    private static final String DATABASE_CREATE =
+            "create table notes (_id integer primary key autoincrement, "
+                    + "title text not null, body text not null);";
+
+    private static final String DATABASE_NAME = "data";
+    private static final String DATABASE_TABLE = "notes";
+    private static final int DATABASE_VERSION = 2;
+
+    private final Context mCtx;
+
+    private static class DatabaseHelper extends SQLiteOpenHelper {
+
+        DatabaseHelper(Context context) {
+            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+
+            db.execSQL(DATABASE_CREATE);
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+                    + newVersion + ", which will destroy all old data");
+            db.execSQL("DROP TABLE IF EXISTS notes");
+            onCreate(db);
+        }
+    }
+
+    /**
+     * Constructor - takes the context to allow the database to be
+     * opened/created
+     * 
+     * @param ctx the Context within which to work
+     */
+    public NotesDbAdapter(Context ctx) {
+        this.mCtx = ctx;
+    }
+
+    /**
+     * Open the notes database. If it cannot be opened, try to create a new
+     * instance of the database. If it cannot be created, throw an exception to
+     * signal the failure
+     * 
+     * @return this (self reference, allowing this to be chained in an
+     *         initialization call)
+     * @throws SQLException if the database could be neither opened or created
+     */
+    public NotesDbAdapter open() throws SQLException {
+        mDbHelper = new DatabaseHelper(mCtx);
+        mDb = mDbHelper.getWritableDatabase();
+        return this;
+    }
+    
+    public void close() {
+        mDbHelper.close();
+    }
+
+
+    /**
+     * Create a new note using the title and body provided. If the note is
+     * successfully created return the new rowId for that note, otherwise return
+     * a -1 to indicate failure.
+     * 
+     * @param title the title of the note
+     * @param body the body of the note
+     * @return rowId or -1 if failed
+     */
+    public long createNote(String title, String body) {
+        ContentValues initialValues = new ContentValues();
+        initialValues.put(KEY_TITLE, title);
+        initialValues.put(KEY_BODY, body);
+
+        return mDb.insert(DATABASE_TABLE, null, initialValues);
+    }
+
+    /**
+     * Delete the note with the given rowId
+     * 
+     * @param rowId id of note to delete
+     * @return true if deleted, false otherwise
+     */
+    public boolean deleteNote(long rowId) {
+
+        return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
+    }
+
+    /**
+     * Return a Cursor over the list of all notes in the database
+     * 
+     * @return Cursor over all notes
+     */
+    public Cursor fetchAllNotes() {
+
+        return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
+                KEY_BODY}, null, null, null, null, null);
+    }
+
+    /**
+     * Return a Cursor positioned at the note that matches the given rowId
+     * 
+     * @param rowId id of note to retrieve
+     * @return Cursor positioned to matching note, if found
+     * @throws SQLException if note could not be found/retrieved
+     */
+    public Cursor fetchNote(long rowId) throws SQLException {
+
+        Cursor mCursor =
+
+                mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
+                        KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
+                        null, null, null, null);
+        if (mCursor != null) {
+            mCursor.moveToFirst();
+        }
+        return mCursor;
+
+    }
+
+    /**
+     * Update the note using the details provided. The note to be updated is
+     * specified using the rowId, and it is altered to use the title and body
+     * values passed in
+     * 
+     * @param rowId id of note to update
+     * @param title value to set note title to
+     * @param body value to set note body to
+     * @return true if the note was successfully updated, false otherwise
+     */
+    public boolean updateNote(long rowId, String title, String body) {
+        ContentValues args = new ContentValues();
+        args.put(KEY_TITLE, title);
+        args.put(KEY_BODY, body);
+
+        return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
+    }
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv1Solution/AndroidManifest.xml b/tutorials/NotepadCodeLab/Notepadv1Solution/AndroidManifest.xml
new file mode 100755
index 0000000..99023fe
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1Solution/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.demo.notepad1">
+    <application android:icon="@drawable/icon">
+        <activity android:name=".Notepadv1" android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest> 
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv1Solution/res/drawable/icon.png b/tutorials/NotepadCodeLab/Notepadv1Solution/res/drawable/icon.png
new file mode 100755
index 0000000..64e3601
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1Solution/res/drawable/icon.png
Binary files differ
diff --git a/tutorials/NotepadCodeLab/Notepadv1Solution/res/layout/notepad_list.xml b/tutorials/NotepadCodeLab/Notepadv1Solution/res/layout/notepad_list.xml
new file mode 100755
index 0000000..0c8dbab
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1Solution/res/layout/notepad_list.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+	<ListView android:id="@id/android:list"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+  	<TextView android:id="@id/android:empty"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/no_notes"/>
+        
+</LinearLayout>
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv1Solution/res/layout/notes_row.xml b/tutorials/NotepadCodeLab/Notepadv1Solution/res/layout/notes_row.xml
new file mode 100755
index 0000000..6b1a65b
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1Solution/res/layout/notes_row.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView android:id="@+id/text1"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"/>
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv1Solution/res/values/strings.xml b/tutorials/NotepadCodeLab/Notepadv1Solution/res/values/strings.xml
new file mode 100755
index 0000000..265bc62
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1Solution/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Notepad v1</string>
+    <string name="no_notes">No Notes Yet</string>
+    <string name="menu_insert">Add Item</string>
+</resources>
diff --git a/tutorials/NotepadCodeLab/Notepadv1Solution/src/com/android/demo/notepad1/Notepadv1.java b/tutorials/NotepadCodeLab/Notepadv1Solution/src/com/android/demo/notepad1/Notepadv1.java
new file mode 100755
index 0000000..a1819ed
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1Solution/src/com/android/demo/notepad1/Notepadv1.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.demo.notepad1;
+
+import android.app.ListActivity;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.SimpleCursorAdapter;
+
+public class Notepadv1 extends ListActivity {
+	public static final int INSERT_ID = Menu.FIRST;
+	
+	private int mNoteNumber = 1;
+	private NotesDbAdapter mDbHelper;
+    
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.notepad_list);
+        mDbHelper = new NotesDbAdapter(this);
+        mDbHelper.open();
+        fillData();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+    	boolean result = super.onCreateOptionsMenu(menu);
+        menu.add(0, INSERT_ID, 0, R.string.menu_insert);
+        return result;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+    	switch (item.getItemId()) {
+        case INSERT_ID:
+            createNote();
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+    
+    private void createNote() {
+        String noteName = "Note " + mNoteNumber++;
+        mDbHelper.createNote(noteName, "");
+        fillData();
+    }
+    
+    private void fillData() {
+        // Get all of the notes from the database and create the item list
+        Cursor c = mDbHelper.fetchAllNotes();
+        startManagingCursor(c);
+
+        String[] from = new String[] { NotesDbAdapter.KEY_TITLE };
+        int[] to = new int[] { R.id.text1 };
+        
+        // Now create an array adapter and set it to display using our row
+        SimpleCursorAdapter notes =
+            new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
+        setListAdapter(notes);
+    }
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv1Solution/src/com/android/demo/notepad1/NotesDbAdapter.java b/tutorials/NotepadCodeLab/Notepadv1Solution/src/com/android/demo/notepad1/NotesDbAdapter.java
new file mode 100755
index 0000000..6f85bbd
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv1Solution/src/com/android/demo/notepad1/NotesDbAdapter.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.demo.notepad1;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+/**
+ * Simple notes database access helper class. Defines the basic CRUD operations
+ * for the notepad example, and gives the ability to list all notes as well as
+ * retrieve or modify a specific note.
+ * 
+ * This has been improved from the first version of this tutorial through the
+ * addition of better error handling and also using returning a Cursor instead
+ * of using a collection of inner classes (which is less scalable and not
+ * recommended).
+ */
+public class NotesDbAdapter {
+
+    public static final String KEY_TITLE = "title";
+    public static final String KEY_BODY = "body";
+    public static final String KEY_ROWID = "_id";
+
+    private static final String TAG = "NotesDbAdapter";
+    private DatabaseHelper mDbHelper;
+    private SQLiteDatabase mDb;
+    
+    /**
+     * Database creation sql statement
+     */
+    private static final String DATABASE_CREATE =
+            "create table notes (_id integer primary key autoincrement, "
+                    + "title text not null, body text not null);";
+
+    private static final String DATABASE_NAME = "data";
+    private static final String DATABASE_TABLE = "notes";
+    private static final int DATABASE_VERSION = 2;
+
+    private final Context mCtx;
+
+    private static class DatabaseHelper extends SQLiteOpenHelper {
+
+        DatabaseHelper(Context context) {
+            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+
+            db.execSQL(DATABASE_CREATE);
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+                    + newVersion + ", which will destroy all old data");
+            db.execSQL("DROP TABLE IF EXISTS notes");
+            onCreate(db);
+        }
+    }
+
+    /**
+     * Constructor - takes the context to allow the database to be
+     * opened/created
+     * 
+     * @param ctx the Context within which to work
+     */
+    public NotesDbAdapter(Context ctx) {
+        this.mCtx = ctx;
+    }
+
+    /**
+     * Open the notes database. If it cannot be opened, try to create a new
+     * instance of the database. If it cannot be created, throw an exception to
+     * signal the failure
+     * 
+     * @return this (self reference, allowing this to be chained in an
+     *         initialization call)
+     * @throws SQLException if the database could be neither opened or created
+     */
+    public NotesDbAdapter open() throws SQLException {
+        mDbHelper = new DatabaseHelper(mCtx);
+        mDb = mDbHelper.getWritableDatabase();
+        return this;
+    }
+    
+    public void close() {
+        mDbHelper.close();
+    }
+
+
+    /**
+     * Create a new note using the title and body provided. If the note is
+     * successfully created return the new rowId for that note, otherwise return
+     * a -1 to indicate failure.
+     * 
+     * @param title the title of the note
+     * @param body the body of the note
+     * @return rowId or -1 if failed
+     */
+    public long createNote(String title, String body) {
+        ContentValues initialValues = new ContentValues();
+        initialValues.put(KEY_TITLE, title);
+        initialValues.put(KEY_BODY, body);
+
+        return mDb.insert(DATABASE_TABLE, null, initialValues);
+    }
+
+    /**
+     * Delete the note with the given rowId
+     * 
+     * @param rowId id of note to delete
+     * @return true if deleted, false otherwise
+     */
+    public boolean deleteNote(long rowId) {
+
+        return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
+    }
+
+    /**
+     * Return a Cursor over the list of all notes in the database
+     * 
+     * @return Cursor over all notes
+     */
+    public Cursor fetchAllNotes() {
+
+        return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
+                KEY_BODY}, null, null, null, null, null);
+    }
+
+    /**
+     * Return a Cursor positioned at the note that matches the given rowId
+     * 
+     * @param rowId id of note to retrieve
+     * @return Cursor positioned to matching note, if found
+     * @throws SQLException if note could not be found/retrieved
+     */
+    public Cursor fetchNote(long rowId) throws SQLException {
+
+        Cursor mCursor =
+
+                mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
+                        KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
+                        null, null, null, null);
+        if (mCursor != null) {
+            mCursor.moveToFirst();
+        }
+        return mCursor;
+
+    }
+
+    /**
+     * Update the note using the details provided. The note to be updated is
+     * specified using the rowId, and it is altered to use the title and body
+     * values passed in
+     * 
+     * @param rowId id of note to update
+     * @param title value to set note title to
+     * @param body value to set note body to
+     * @return true if the note was successfully updated, false otherwise
+     */
+    public boolean updateNote(long rowId, String title, String body) {
+        ContentValues args = new ContentValues();
+        args.put(KEY_TITLE, title);
+        args.put(KEY_BODY, body);
+
+        return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
+    }
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv2/AndroidManifest.xml b/tutorials/NotepadCodeLab/Notepadv2/AndroidManifest.xml
new file mode 100755
index 0000000..738fb2a
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.demo.notepad2">
+    <application android:icon="@drawable/icon">
+        <activity android:name=".Notepadv2" android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest> 
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv2/res/drawable/icon.png b/tutorials/NotepadCodeLab/Notepadv2/res/drawable/icon.png
new file mode 100755
index 0000000..64e3601
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2/res/drawable/icon.png
Binary files differ
diff --git a/tutorials/NotepadCodeLab/Notepadv2/res/layout/note_edit.xml b/tutorials/NotepadCodeLab/Notepadv2/res/layout/note_edit.xml
new file mode 100755
index 0000000..b254552
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2/res/layout/note_edit.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	android:orientation="vertical" android:layout_width="fill_parent"
+	android:layout_height="fill_parent">
+	
+	<LinearLayout android:orientation="horizontal"
+		android:layout_width="fill_parent"
+		android:layout_height="wrap_content">
+
+		<TextView android:layout_width="wrap_content"
+			android:layout_height="wrap_content" 
+			android:text="@string/title" />
+		<EditText android:id="@+id/title" 
+		  android:layout_width="wrap_content"
+			android:layout_height="wrap_content" 
+			android:layout_weight="1"/>
+	</LinearLayout>
+
+	<TextView android:layout_width="wrap_content"
+		android:layout_height="wrap_content" 
+		android:text="@string/body" />
+	<EditText android:id="@+id/body" android:layout_width="fill_parent"
+		android:layout_height="wrap_content"
+		android:layout_weight="1"
+		android:scrollbars="vertical" />
+	
+	<Button android:id="@+id/confirm" 
+	  android:text="@string/confirm"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv2/res/layout/notes_list.xml b/tutorials/NotepadCodeLab/Notepadv2/res/layout/notes_list.xml
new file mode 100755
index 0000000..29ae886
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2/res/layout/notes_list.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="wrap_content"
+    	android:layout_height="wrap_content">
+    
+    <ListView android:id="@+id/android:list"
+          android:layout_width="wrap_content"
+        	android:layout_height="wrap_content"/>
+  	<TextView android:id="@+id/android:empty"
+          android:layout_width="wrap_content"
+        	android:layout_height="wrap_content"
+        	android:text="No Notes!"/>
+</LinearLayout>
diff --git a/tutorials/NotepadCodeLab/Notepadv2/res/layout/notes_row.xml b/tutorials/NotepadCodeLab/Notepadv2/res/layout/notes_row.xml
new file mode 100755
index 0000000..f28a41b
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2/res/layout/notes_row.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView android:id="@+id/text1" xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"/>
diff --git a/tutorials/NotepadCodeLab/Notepadv2/res/values/strings.xml b/tutorials/NotepadCodeLab/Notepadv2/res/values/strings.xml
new file mode 100755
index 0000000..b70c3f8
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2/res/values/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Notepad v2</string>
+    <string name="no_notes">No Notes Yet</string>
+    <string name="menu_insert">Add Note</string>
+    <string name="menu_delete">Delete Note</string>
+    <string name="title">Title</string>
+    <string name="body">Body</string>
+    <string name="confirm">Confirm</string>
+    <string name="edit_note">Edit Note</string>
+</resources>
diff --git a/tutorials/NotepadCodeLab/Notepadv2/src/com/android/demo/notepad2/Notepadv2.java b/tutorials/NotepadCodeLab/Notepadv2/src/com/android/demo/notepad2/Notepadv2.java
new file mode 100755
index 0000000..abfc538
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2/src/com/android/demo/notepad2/Notepadv2.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.demo.notepad2;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.SimpleCursorAdapter;
+
+public class Notepadv2 extends ListActivity {
+    private static final int ACTIVITY_CREATE=0;
+    private static final int ACTIVITY_EDIT=1;
+    
+    private static final int INSERT_ID = Menu.FIRST;
+    private static final int DELETE_ID = Menu.FIRST + 1;
+
+    private NotesDbAdapter mDbHelper;
+    private Cursor mNotesCursor;
+    
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.notes_list);
+        mDbHelper = new NotesDbAdapter(this);
+        mDbHelper.open();
+        fillData();
+    }
+    
+    private void fillData() {
+        // Get all of the rows from the database and create the item list
+        mNotesCursor = mDbHelper.fetchAllNotes();
+        startManagingCursor(mNotesCursor);
+        
+        // Create an array to specify the fields we want to display in the list (only TITLE)
+        String[] from = new String[]{NotesDbAdapter.KEY_TITLE};
+        
+        // and an array of the fields we want to bind those fields to (in this case just text1)
+        int[] to = new int[]{R.id.text1};
+        
+        // Now create a simple cursor adapter and set it to display
+        SimpleCursorAdapter notes = 
+        	    new SimpleCursorAdapter(this, R.layout.notes_row, mNotesCursor, from, to);
+        setListAdapter(notes);
+    }
+    
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        menu.add(0, INSERT_ID,0, R.string.menu_insert);
+        return true;
+    }
+
+    @Override
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        switch(item.getItemId()) {
+        case INSERT_ID:
+            createNote();
+            return true;
+        }
+        
+        return super.onMenuItemSelected(featureId, item);
+    }
+
+    @Override
+	public void onCreateContextMenu(ContextMenu menu, View v,
+			ContextMenuInfo menuInfo) {
+		super.onCreateContextMenu(menu, v, menuInfo);
+		
+        // TODO: fill in rest of method
+	}
+
+    @Override
+	public boolean onContextItemSelected(MenuItem item) {
+		return super.onContextItemSelected(item);
+		
+        // TODO: fill in rest of method
+	}
+
+    private void createNote() {
+        // TODO: fill in implementation
+
+    }
+    
+    @Override
+    protected void onListItemClick(ListView l, View v, int position, long id) {
+        super.onListItemClick(l, v, position, id);
+
+        // TODO: fill in rest of method
+        
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
+        super.onActivityResult(requestCode, resultCode, intent);
+        
+        // TODO: fill in rest of method
+        
+    }
+
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv2/src/com/android/demo/notepad2/NotesDbAdapter.java b/tutorials/NotepadCodeLab/Notepadv2/src/com/android/demo/notepad2/NotesDbAdapter.java
new file mode 100755
index 0000000..5bf51b1
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2/src/com/android/demo/notepad2/NotesDbAdapter.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.demo.notepad2;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+/**
+ * Simple notes database access helper class. Defines the basic CRUD operations
+ * for the notepad example, and gives the ability to list all notes as well as
+ * retrieve or modify a specific note.
+ * 
+ * This has been improved from the first version of this tutorial through the
+ * addition of better error handling and also using returning a Cursor instead
+ * of using a collection of inner classes (which is less scalable and not
+ * recommended).
+ */
+public class NotesDbAdapter {
+
+    public static final String KEY_TITLE = "title";
+    public static final String KEY_BODY = "body";
+    public static final String KEY_ROWID = "_id";
+
+    private static final String TAG = "NotesDbAdapter";
+    private DatabaseHelper mDbHelper;
+    private SQLiteDatabase mDb;
+    
+    /**
+     * Database creation sql statement
+     */
+    private static final String DATABASE_CREATE =
+            "create table notes (_id integer primary key autoincrement, "
+                    + "title text not null, body text not null);";
+
+    private static final String DATABASE_NAME = "data";
+    private static final String DATABASE_TABLE = "notes";
+    private static final int DATABASE_VERSION = 2;
+
+    private final Context mCtx;
+
+    private static class DatabaseHelper extends SQLiteOpenHelper {
+
+        DatabaseHelper(Context context) {
+            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+
+            db.execSQL(DATABASE_CREATE);
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+                    + newVersion + ", which will destroy all old data");
+            db.execSQL("DROP TABLE IF EXISTS notes");
+            onCreate(db);
+        }
+    }
+
+    /**
+     * Constructor - takes the context to allow the database to be
+     * opened/created
+     * 
+     * @param ctx the Context within which to work
+     */
+    public NotesDbAdapter(Context ctx) {
+        this.mCtx = ctx;
+    }
+
+    /**
+     * Open the notes database. If it cannot be opened, try to create a new
+     * instance of the database. If it cannot be created, throw an exception to
+     * signal the failure
+     * 
+     * @return this (self reference, allowing this to be chained in an
+     *         initialization call)
+     * @throws SQLException if the database could be neither opened or created
+     */
+    public NotesDbAdapter open() throws SQLException {
+        mDbHelper = new DatabaseHelper(mCtx);
+        mDb = mDbHelper.getWritableDatabase();
+        return this;
+    }
+    
+    public void close() {
+        mDbHelper.close();
+    }
+
+
+    /**
+     * Create a new note using the title and body provided. If the note is
+     * successfully created return the new rowId for that note, otherwise return
+     * a -1 to indicate failure.
+     * 
+     * @param title the title of the note
+     * @param body the body of the note
+     * @return rowId or -1 if failed
+     */
+    public long createNote(String title, String body) {
+        ContentValues initialValues = new ContentValues();
+        initialValues.put(KEY_TITLE, title);
+        initialValues.put(KEY_BODY, body);
+
+        return mDb.insert(DATABASE_TABLE, null, initialValues);
+    }
+
+    /**
+     * Delete the note with the given rowId
+     * 
+     * @param rowId id of note to delete
+     * @return true if deleted, false otherwise
+     */
+    public boolean deleteNote(long rowId) {
+
+        return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
+    }
+
+    /**
+     * Return a Cursor over the list of all notes in the database
+     * 
+     * @return Cursor over all notes
+     */
+    public Cursor fetchAllNotes() {
+
+        return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
+                KEY_BODY}, null, null, null, null, null);
+    }
+
+    /**
+     * Return a Cursor positioned at the note that matches the given rowId
+     * 
+     * @param rowId id of note to retrieve
+     * @return Cursor positioned to matching note, if found
+     * @throws SQLException if note could not be found/retrieved
+     */
+    public Cursor fetchNote(long rowId) throws SQLException {
+
+        Cursor mCursor =
+
+                mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
+                        KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
+                        null, null, null, null);
+        if (mCursor != null) {
+            mCursor.moveToFirst();
+        }
+        return mCursor;
+
+    }
+
+    /**
+     * Update the note using the details provided. The note to be updated is
+     * specified using the rowId, and it is altered to use the title and body
+     * values passed in
+     * 
+     * @param rowId id of note to update
+     * @param title value to set note title to
+     * @param body value to set note body to
+     * @return true if the note was successfully updated, false otherwise
+     */
+    public boolean updateNote(long rowId, String title, String body) {
+        ContentValues args = new ContentValues();
+        args.put(KEY_TITLE, title);
+        args.put(KEY_BODY, body);
+
+        return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
+    }
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv2Solution/AndroidManifest.xml b/tutorials/NotepadCodeLab/Notepadv2Solution/AndroidManifest.xml
new file mode 100755
index 0000000..dbfc9d0
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2Solution/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.demo.notepad2">
+    <application android:icon="@drawable/icon">
+        <activity android:name=".Notepadv2" android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    	<activity android:name=".NoteEdit"></activity>
+    </application>
+</manifest> 
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv2Solution/res/drawable/icon.png b/tutorials/NotepadCodeLab/Notepadv2Solution/res/drawable/icon.png
new file mode 100755
index 0000000..64e3601
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2Solution/res/drawable/icon.png
Binary files differ
diff --git a/tutorials/NotepadCodeLab/Notepadv2Solution/res/layout/note_edit.xml b/tutorials/NotepadCodeLab/Notepadv2Solution/res/layout/note_edit.xml
new file mode 100755
index 0000000..b254552
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2Solution/res/layout/note_edit.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	android:orientation="vertical" android:layout_width="fill_parent"
+	android:layout_height="fill_parent">
+	
+	<LinearLayout android:orientation="horizontal"
+		android:layout_width="fill_parent"
+		android:layout_height="wrap_content">
+
+		<TextView android:layout_width="wrap_content"
+			android:layout_height="wrap_content" 
+			android:text="@string/title" />
+		<EditText android:id="@+id/title" 
+		  android:layout_width="wrap_content"
+			android:layout_height="wrap_content" 
+			android:layout_weight="1"/>
+	</LinearLayout>
+
+	<TextView android:layout_width="wrap_content"
+		android:layout_height="wrap_content" 
+		android:text="@string/body" />
+	<EditText android:id="@+id/body" android:layout_width="fill_parent"
+		android:layout_height="wrap_content"
+		android:layout_weight="1"
+		android:scrollbars="vertical" />
+	
+	<Button android:id="@+id/confirm" 
+	  android:text="@string/confirm"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv2Solution/res/layout/notes_list.xml b/tutorials/NotepadCodeLab/Notepadv2Solution/res/layout/notes_list.xml
new file mode 100755
index 0000000..29ae886
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2Solution/res/layout/notes_list.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="wrap_content"
+    	android:layout_height="wrap_content">
+    
+    <ListView android:id="@+id/android:list"
+          android:layout_width="wrap_content"
+        	android:layout_height="wrap_content"/>
+  	<TextView android:id="@+id/android:empty"
+          android:layout_width="wrap_content"
+        	android:layout_height="wrap_content"
+        	android:text="No Notes!"/>
+</LinearLayout>
diff --git a/tutorials/NotepadCodeLab/Notepadv2Solution/res/layout/notes_row.xml b/tutorials/NotepadCodeLab/Notepadv2Solution/res/layout/notes_row.xml
new file mode 100755
index 0000000..f28a41b
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2Solution/res/layout/notes_row.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView android:id="@+id/text1" xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"/>
diff --git a/tutorials/NotepadCodeLab/Notepadv2Solution/res/values/strings.xml b/tutorials/NotepadCodeLab/Notepadv2Solution/res/values/strings.xml
new file mode 100755
index 0000000..b70c3f8
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2Solution/res/values/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Notepad v2</string>
+    <string name="no_notes">No Notes Yet</string>
+    <string name="menu_insert">Add Note</string>
+    <string name="menu_delete">Delete Note</string>
+    <string name="title">Title</string>
+    <string name="body">Body</string>
+    <string name="confirm">Confirm</string>
+    <string name="edit_note">Edit Note</string>
+</resources>
diff --git a/tutorials/NotepadCodeLab/Notepadv2Solution/src/com/android/demo/notepad2/NoteEdit.java b/tutorials/NotepadCodeLab/Notepadv2Solution/src/com/android/demo/notepad2/NoteEdit.java
new file mode 100755
index 0000000..6c5e664
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2Solution/src/com/android/demo/notepad2/NoteEdit.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.savedInstanceState
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.demo.notepad2;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+
+public class NoteEdit extends Activity {
+
+	private EditText mTitleText;
+    private EditText mBodyText;
+    private Long mRowId;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.note_edit);
+       
+        mTitleText = (EditText) findViewById(R.id.title);
+        mBodyText = (EditText) findViewById(R.id.body);
+      
+        Button confirmButton = (Button) findViewById(R.id.confirm);
+       
+        mRowId = null;
+        Bundle extras = getIntent().getExtras();
+        if (extras != null) {
+            String title = extras.getString(NotesDbAdapter.KEY_TITLE);
+            String body = extras.getString(NotesDbAdapter.KEY_BODY);
+            mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
+          
+            if (title != null) {
+                mTitleText.setText(title);
+            }
+            if (body != null) {
+                mBodyText.setText(body);
+            }
+        }
+       
+        confirmButton.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                Bundle bundle = new Bundle();
+               
+                bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
+                bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
+                if (mRowId != null) {
+                    bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
+                }
+                
+                Intent mIntent = new Intent();
+                mIntent.putExtras(bundle);
+                setResult(RESULT_OK, mIntent);
+                finish();
+            }
+            
+        });
+    }
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv2Solution/src/com/android/demo/notepad2/Notepadv2.java b/tutorials/NotepadCodeLab/Notepadv2Solution/src/com/android/demo/notepad2/Notepadv2.java
new file mode 100755
index 0000000..1b33982
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2Solution/src/com/android/demo/notepad2/Notepadv2.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.demo.notepad2;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.widget.ListView;
+import android.widget.SimpleCursorAdapter;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+
+public class Notepadv2 extends ListActivity {
+    private static final int ACTIVITY_CREATE=0;
+    private static final int ACTIVITY_EDIT=1;
+    
+    private static final int INSERT_ID = Menu.FIRST;
+    private static final int DELETE_ID = Menu.FIRST + 1;
+
+    private NotesDbAdapter mDbHelper;
+    private Cursor mNotesCursor;
+    
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.notes_list);
+        mDbHelper = new NotesDbAdapter(this);
+        mDbHelper.open();
+        fillData();
+        registerForContextMenu(getListView());
+    }
+    
+    private void fillData() {
+        // Get all of the rows from the database and create the item list
+        mNotesCursor = mDbHelper.fetchAllNotes();
+        startManagingCursor(mNotesCursor);
+        
+        // Create an array to specify the fields we want to display in the list (only TITLE)
+        String[] from = new String[]{NotesDbAdapter.KEY_TITLE};
+        
+        // and an array of the fields we want to bind those fields to (in this case just text1)
+        int[] to = new int[]{R.id.text1};
+        
+        // Now create a simple cursor adapter and set it to display
+        SimpleCursorAdapter notes = 
+        	    new SimpleCursorAdapter(this, R.layout.notes_row, mNotesCursor, from, to);
+        setListAdapter(notes);
+    }
+    
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        menu.add(0, INSERT_ID,0, R.string.menu_insert);
+        return true;
+    }
+    
+    @Override
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        switch(item.getItemId()) {
+        case INSERT_ID:
+            createNote();
+            return true;
+	    }        
+        return super.onMenuItemSelected(featureId, item);
+    }
+
+    @Override
+	public void onCreateContextMenu(ContextMenu menu, View v,
+			ContextMenuInfo menuInfo) {
+		super.onCreateContextMenu(menu, v, menuInfo);
+        menu.add(0, DELETE_ID, 0, R.string.menu_delete);
+	}
+
+    @Override
+	public boolean onContextItemSelected(MenuItem item) {
+		switch(item.getItemId()) {
+    	case DELETE_ID:
+    		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
+	        mDbHelper.deleteNote(info.id);
+	        fillData();
+	        return true;
+		}
+		return super.onContextItemSelected(item);
+	}
+
+	private void createNote() {
+    	Intent i = new Intent(this, NoteEdit.class);
+    	 startActivityForResult(i, ACTIVITY_CREATE);
+    }
+    
+    @Override
+    protected void onListItemClick(ListView l, View v, int position, long id) {
+    	super.onListItemClick(l, v, position, id);
+        Cursor c = mNotesCursor;
+        c.moveToPosition(position);
+        Intent i = new Intent(this, NoteEdit.class);
+        i.putExtra(NotesDbAdapter.KEY_ROWID, id);
+        i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(
+                c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
+        i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
+                c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
+        startActivityForResult(i, ACTIVITY_EDIT);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
+        super.onActivityResult(requestCode, resultCode, intent);
+        Bundle extras = intent.getExtras();
+        switch(requestCode) {
+        case ACTIVITY_CREATE:
+            String title = extras.getString(NotesDbAdapter.KEY_TITLE);
+            String body = extras.getString(NotesDbAdapter.KEY_BODY);
+            mDbHelper.createNote(title, body);
+            fillData();
+            break;
+        case ACTIVITY_EDIT:
+            Long rowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
+            if (rowId != null) {
+                String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE);
+                String editBody = extras.getString(NotesDbAdapter.KEY_BODY);
+                mDbHelper.updateNote(rowId, editTitle, editBody);
+            }
+            fillData();
+            break;
+        }
+    }
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv2Solution/src/com/android/demo/notepad2/NotesDbAdapter.java b/tutorials/NotepadCodeLab/Notepadv2Solution/src/com/android/demo/notepad2/NotesDbAdapter.java
new file mode 100755
index 0000000..5bf51b1
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv2Solution/src/com/android/demo/notepad2/NotesDbAdapter.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.demo.notepad2;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+/**
+ * Simple notes database access helper class. Defines the basic CRUD operations
+ * for the notepad example, and gives the ability to list all notes as well as
+ * retrieve or modify a specific note.
+ * 
+ * This has been improved from the first version of this tutorial through the
+ * addition of better error handling and also using returning a Cursor instead
+ * of using a collection of inner classes (which is less scalable and not
+ * recommended).
+ */
+public class NotesDbAdapter {
+
+    public static final String KEY_TITLE = "title";
+    public static final String KEY_BODY = "body";
+    public static final String KEY_ROWID = "_id";
+
+    private static final String TAG = "NotesDbAdapter";
+    private DatabaseHelper mDbHelper;
+    private SQLiteDatabase mDb;
+    
+    /**
+     * Database creation sql statement
+     */
+    private static final String DATABASE_CREATE =
+            "create table notes (_id integer primary key autoincrement, "
+                    + "title text not null, body text not null);";
+
+    private static final String DATABASE_NAME = "data";
+    private static final String DATABASE_TABLE = "notes";
+    private static final int DATABASE_VERSION = 2;
+
+    private final Context mCtx;
+
+    private static class DatabaseHelper extends SQLiteOpenHelper {
+
+        DatabaseHelper(Context context) {
+            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+
+            db.execSQL(DATABASE_CREATE);
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+                    + newVersion + ", which will destroy all old data");
+            db.execSQL("DROP TABLE IF EXISTS notes");
+            onCreate(db);
+        }
+    }
+
+    /**
+     * Constructor - takes the context to allow the database to be
+     * opened/created
+     * 
+     * @param ctx the Context within which to work
+     */
+    public NotesDbAdapter(Context ctx) {
+        this.mCtx = ctx;
+    }
+
+    /**
+     * Open the notes database. If it cannot be opened, try to create a new
+     * instance of the database. If it cannot be created, throw an exception to
+     * signal the failure
+     * 
+     * @return this (self reference, allowing this to be chained in an
+     *         initialization call)
+     * @throws SQLException if the database could be neither opened or created
+     */
+    public NotesDbAdapter open() throws SQLException {
+        mDbHelper = new DatabaseHelper(mCtx);
+        mDb = mDbHelper.getWritableDatabase();
+        return this;
+    }
+    
+    public void close() {
+        mDbHelper.close();
+    }
+
+
+    /**
+     * Create a new note using the title and body provided. If the note is
+     * successfully created return the new rowId for that note, otherwise return
+     * a -1 to indicate failure.
+     * 
+     * @param title the title of the note
+     * @param body the body of the note
+     * @return rowId or -1 if failed
+     */
+    public long createNote(String title, String body) {
+        ContentValues initialValues = new ContentValues();
+        initialValues.put(KEY_TITLE, title);
+        initialValues.put(KEY_BODY, body);
+
+        return mDb.insert(DATABASE_TABLE, null, initialValues);
+    }
+
+    /**
+     * Delete the note with the given rowId
+     * 
+     * @param rowId id of note to delete
+     * @return true if deleted, false otherwise
+     */
+    public boolean deleteNote(long rowId) {
+
+        return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
+    }
+
+    /**
+     * Return a Cursor over the list of all notes in the database
+     * 
+     * @return Cursor over all notes
+     */
+    public Cursor fetchAllNotes() {
+
+        return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
+                KEY_BODY}, null, null, null, null, null);
+    }
+
+    /**
+     * Return a Cursor positioned at the note that matches the given rowId
+     * 
+     * @param rowId id of note to retrieve
+     * @return Cursor positioned to matching note, if found
+     * @throws SQLException if note could not be found/retrieved
+     */
+    public Cursor fetchNote(long rowId) throws SQLException {
+
+        Cursor mCursor =
+
+                mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
+                        KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
+                        null, null, null, null);
+        if (mCursor != null) {
+            mCursor.moveToFirst();
+        }
+        return mCursor;
+
+    }
+
+    /**
+     * Update the note using the details provided. The note to be updated is
+     * specified using the rowId, and it is altered to use the title and body
+     * values passed in
+     * 
+     * @param rowId id of note to update
+     * @param title value to set note title to
+     * @param body value to set note body to
+     * @return true if the note was successfully updated, false otherwise
+     */
+    public boolean updateNote(long rowId, String title, String body) {
+        ContentValues args = new ContentValues();
+        args.put(KEY_TITLE, title);
+        args.put(KEY_BODY, body);
+
+        return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
+    }
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv3/AndroidManifest.xml b/tutorials/NotepadCodeLab/Notepadv3/AndroidManifest.xml
new file mode 100755
index 0000000..adb07ff
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.demo.notepad3">
+    <application android:icon="@drawable/icon">
+        <activity android:name=".Notepadv3" android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".NoteEdit"/>
+    </application>
+</manifest> 
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv3/res/drawable/icon.png b/tutorials/NotepadCodeLab/Notepadv3/res/drawable/icon.png
new file mode 100755
index 0000000..64e3601
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3/res/drawable/icon.png
Binary files differ
diff --git a/tutorials/NotepadCodeLab/Notepadv3/res/layout/note_edit.xml b/tutorials/NotepadCodeLab/Notepadv3/res/layout/note_edit.xml
new file mode 100755
index 0000000..b254552
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3/res/layout/note_edit.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	android:orientation="vertical" android:layout_width="fill_parent"
+	android:layout_height="fill_parent">
+	
+	<LinearLayout android:orientation="horizontal"
+		android:layout_width="fill_parent"
+		android:layout_height="wrap_content">
+
+		<TextView android:layout_width="wrap_content"
+			android:layout_height="wrap_content" 
+			android:text="@string/title" />
+		<EditText android:id="@+id/title" 
+		  android:layout_width="wrap_content"
+			android:layout_height="wrap_content" 
+			android:layout_weight="1"/>
+	</LinearLayout>
+
+	<TextView android:layout_width="wrap_content"
+		android:layout_height="wrap_content" 
+		android:text="@string/body" />
+	<EditText android:id="@+id/body" android:layout_width="fill_parent"
+		android:layout_height="wrap_content"
+		android:layout_weight="1"
+		android:scrollbars="vertical" />
+	
+	<Button android:id="@+id/confirm" 
+	  android:text="@string/confirm"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv3/res/layout/notes_list.xml b/tutorials/NotepadCodeLab/Notepadv3/res/layout/notes_list.xml
new file mode 100755
index 0000000..29ae886
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3/res/layout/notes_list.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="wrap_content"
+    	android:layout_height="wrap_content">
+    
+    <ListView android:id="@+id/android:list"
+          android:layout_width="wrap_content"
+        	android:layout_height="wrap_content"/>
+  	<TextView android:id="@+id/android:empty"
+          android:layout_width="wrap_content"
+        	android:layout_height="wrap_content"
+        	android:text="No Notes!"/>
+</LinearLayout>
diff --git a/tutorials/NotepadCodeLab/Notepadv3/res/layout/notes_row.xml b/tutorials/NotepadCodeLab/Notepadv3/res/layout/notes_row.xml
new file mode 100755
index 0000000..f28a41b
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3/res/layout/notes_row.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView android:id="@+id/text1" xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"/>
diff --git a/tutorials/NotepadCodeLab/Notepadv3/res/values/strings.xml b/tutorials/NotepadCodeLab/Notepadv3/res/values/strings.xml
new file mode 100755
index 0000000..ae63b83
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3/res/values/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Notepad v3</string>
+    <string name="no_notes">No Notes Yet</string>
+    <string name="menu_insert">Add Note</string>
+    <string name="menu_delete">Delete Note</string>
+    <string name="title">Title</string>
+    <string name="body">Body</string>
+    <string name="confirm">Confirm</string>
+    <string name="edit_note">Edit Note</string>
+</resources>
diff --git a/tutorials/NotepadCodeLab/Notepadv3/src/com/android/demo/notepad3/NoteEdit.java b/tutorials/NotepadCodeLab/Notepadv3/src/com/android/demo/notepad3/NoteEdit.java
new file mode 100755
index 0000000..af3a234
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3/src/com/android/demo/notepad3/NoteEdit.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.demo.notepad3;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+
+public class NoteEdit extends Activity {
+
+	private EditText mTitleText;
+    private EditText mBodyText;
+    private Long mRowId;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.note_edit);
+       
+        mTitleText = (EditText) findViewById(R.id.title);
+        mBodyText = (EditText) findViewById(R.id.body);
+      
+        Button confirmButton = (Button) findViewById(R.id.confirm);
+       
+        mRowId = null;
+        Bundle extras = getIntent().getExtras();
+        if (extras != null) {
+            String title = extras.getString(NotesDbAdapter.KEY_TITLE);
+            String body = extras.getString(NotesDbAdapter.KEY_BODY);
+            mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
+          
+            if (title != null) {
+                mTitleText.setText(title);
+            }
+            if (body != null) {
+                mBodyText.setText(body);
+            }
+        }
+       
+        confirmButton.setOnClickListener(new View.OnClickListener() {
+
+            public void onClick(View view) {
+                Bundle bundle = new Bundle();
+               
+                bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
+                bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
+                if (mRowId != null) {
+                    bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
+                }
+               
+                Intent mIntent = new Intent();
+                mIntent.putExtras(bundle);
+                setResult(RESULT_OK, mIntent);
+                finish();
+            }
+          
+        });
+    }
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv3/src/com/android/demo/notepad3/Notepadv3.java b/tutorials/NotepadCodeLab/Notepadv3/src/com/android/demo/notepad3/Notepadv3.java
new file mode 100755
index 0000000..f50f371
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3/src/com/android/demo/notepad3/Notepadv3.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")savedInstanceState;
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.demo.notepad3;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.widget.ListView;
+import android.widget.SimpleCursorAdapter;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+
+public class Notepadv3 extends ListActivity {
+    private static final int ACTIVITY_CREATE=0;
+    private static final int ACTIVITY_EDIT=1;
+    
+    private static final int INSERT_ID = Menu.FIRST;
+    private static final int DELETE_ID = Menu.FIRST + 1;
+
+    private NotesDbAdapter mDbHelper;
+    private Cursor mNotesCursor;
+    
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.notes_list);
+        mDbHelper = new NotesDbAdapter(this);
+        mDbHelper.open();
+        fillData();
+        registerForContextMenu(getListView());
+    }
+    
+    private void fillData() {
+        // Get all of the rows from the database and create the item list
+        mNotesCursor = mDbHelper.fetchAllNotes();
+        startManagingCursor(mNotesCursor);
+        
+        // Create an array to specify the fields we want to display in the list (only TITLE)
+        String[] from = new String[]{NotesDbAdapter.KEY_TITLE};
+        
+        // and an array of the fields we want to bind those fields to (in this case just text1)
+        int[] to = new int[]{R.id.text1};
+        
+        // Now create a simple cursor adapter and set it to display
+        SimpleCursorAdapter notes = 
+        	    new SimpleCursorAdapter(this, R.layout.notes_row, mNotesCursor, from, to);
+        setListAdapter(notes);
+    }
+    
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        menu.add(0, INSERT_ID, 0, R.string.menu_insert);
+        return true;
+    }
+
+    @Override
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        switch(item.getItemId()) {
+        case INSERT_ID:
+            createNote();
+            return true;
+        }
+       
+        return super.onMenuItemSelected(featureId, item);
+    }
+	
+    @Override
+	public void onCreateContextMenu(ContextMenu menu, View v,
+			ContextMenuInfo menuInfo) {
+		super.onCreateContextMenu(menu, v, menuInfo);
+        menu.add(0, DELETE_ID, 0, R.string.menu_delete);
+	}
+
+    @Override
+	public boolean onContextItemSelected(MenuItem item) {
+		switch(item.getItemId()) {
+    	case DELETE_ID:
+    		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
+	        mDbHelper.deleteNote(info.id);
+	        fillData();
+	        return true;
+		}
+		return super.onContextItemSelected(item);
+	}
+	
+    private void createNote() {
+        Intent i = new Intent(this, NoteEdit.class);
+        startActivityForResult(i, ACTIVITY_CREATE);
+    }
+    
+    @Override
+    protected void onListItemClick(ListView l, View v, int position, long id) {
+        super.onListItemClick(l, v, position, id);
+        Cursor c = mNotesCursor;
+        c.moveToPosition(position);
+        Intent i = new Intent(this, NoteEdit.class);
+        i.putExtra(NotesDbAdapter.KEY_ROWID, id);
+        i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(
+        		c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
+        i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
+        		c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
+        startActivityForResult(i, ACTIVITY_EDIT);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
+        super.onActivityResult(requestCode, resultCode, intent);
+        Bundle extras = intent.getExtras();
+        switch(requestCode) {
+        case ACTIVITY_CREATE:
+            String title = extras.getString(NotesDbAdapter.KEY_TITLE);
+            String body = extras.getString(NotesDbAdapter.KEY_BODY);
+            mDbHelper.createNote(title, body);
+            fillData();
+            break;
+        case ACTIVITY_EDIT:
+            Long rowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
+            if (rowId != null) {
+                String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE);
+                String editBody = extras.getString(NotesDbAdapter.KEY_BODY);
+                mDbHelper.updateNote(rowId, editTitle, editBody);
+            }
+            fillData();
+            break;
+        }
+    }
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv3/src/com/android/demo/notepad3/NotesDbAdapter.java b/tutorials/NotepadCodeLab/Notepadv3/src/com/android/demo/notepad3/NotesDbAdapter.java
new file mode 100755
index 0000000..61ad046
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3/src/com/android/demo/notepad3/NotesDbAdapter.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.demo.notepad3;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+/**
+ * Simple notes database access helper class. Defines the basic CRUD operations
+ * for the notepad example, and gives the ability to list all notes as well as
+ * retrieve or modify a specific note.
+ * 
+ * This has been improved from the first version of this tutorial through the
+ * addition of better error handling and also using returning a Cursor instead
+ * of using a collection of inner classes (which is less scalable and not
+ * recommended).
+ */
+public class NotesDbAdapter {
+
+    public static final String KEY_TITLE = "title";
+    public static final String KEY_BODY = "body";
+    public static final String KEY_ROWID = "_id";
+
+    private static final String TAG = "NotesDbAdapter";
+    private DatabaseHelper mDbHelper;
+    private SQLiteDatabase mDb;
+    
+    /**
+     * Database creation sql statement
+     */
+    private static final String DATABASE_CREATE =
+            "create table notes (_id integer primary key autoincrement, "
+                    + "title text not null, body text not null);";
+
+    private static final String DATABASE_NAME = "data";
+    private static final String DATABASE_TABLE = "notes";
+    private static final int DATABASE_VERSION = 2;
+
+    private final Context mCtx;
+
+    private static class DatabaseHelper extends SQLiteOpenHelper {
+
+        DatabaseHelper(Context context) {
+            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+
+            db.execSQL(DATABASE_CREATE);
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+                    + newVersion + ", which will destroy all old data");
+            db.execSQL("DROP TABLE IF EXISTS notes");
+            onCreate(db);
+        }
+    }
+
+    /**
+     * Constructor - takes the context to allow the database to be
+     * opened/created
+     * 
+     * @param ctx the Context within which to work
+     */
+    public NotesDbAdapter(Context ctx) {
+        this.mCtx = ctx;
+    }
+
+    /**
+     * Open the notes database. If it cannot be opened, try to create a new
+     * instance of the database. If it cannot be created, throw an exception to
+     * signal the failure
+     * 
+     * @return this (self reference, allowing this to be chained in an
+     *         initialization call)
+     * @throws SQLException if the database could be neither opened or created
+     */
+    public NotesDbAdapter open() throws SQLException {
+        mDbHelper = new DatabaseHelper(mCtx);
+        mDb = mDbHelper.getWritableDatabase();
+        return this;
+    }
+    
+    public void close() {
+        mDbHelper.close();
+    }
+
+
+    /**
+     * Create a new note using the title and body provided. If the note is
+     * successfully created return the new rowId for that note, otherwise return
+     * a -1 to indicate failure.
+     * 
+     * @param title the title of the note
+     * @param body the body of the note
+     * @return rowId or -1 if failed
+     */
+    public long createNote(String title, String body) {
+        ContentValues initialValues = new ContentValues();
+        initialValues.put(KEY_TITLE, title);
+        initialValues.put(KEY_BODY, body);
+
+        return mDb.insert(DATABASE_TABLE, null, initialValues);
+    }
+
+    /**
+     * Delete the note with the given rowId
+     * 
+     * @param rowId id of note to delete
+     * @return true if deleted, false otherwise
+     */
+    public boolean deleteNote(long rowId) {
+
+        return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
+    }
+
+    /**
+     * Return a Cursor over the list of all notes in the database
+     * 
+     * @return Cursor over all notes
+     */
+    public Cursor fetchAllNotes() {
+
+        return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
+                KEY_BODY}, null, null, null, null, null);
+    }
+
+    /**
+     * Return a Cursor positioned at the note that matches the given rowId
+     * 
+     * @param rowId id of note to retrieve
+     * @return Cursor positioned to matching note, if found
+     * @throws SQLException if note could not be found/retrieved
+     */
+    public Cursor fetchNote(long rowId) throws SQLException {
+
+        Cursor mCursor =
+
+                mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
+                        KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
+                        null, null, null, null);
+        if (mCursor != null) {
+            mCursor.moveToFirst();
+        }
+        return mCursor;
+
+    }
+
+    /**
+     * Update the note using the details provided. The note to be updated is
+     * specified using the rowId, and it is altered to use the title and body
+     * values passed in
+     * 
+     * @param rowId id of note to update
+     * @param title value to set note title to
+     * @param body value to set note body to
+     * @return true if the note was successfully updated, false otherwise
+     */
+    public boolean updateNote(long rowId, String title, String body) {
+        ContentValues args = new ContentValues();
+        args.put(KEY_TITLE, title);
+        args.put(KEY_BODY, body);
+
+        return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
+    }
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv3Solution/AndroidManifest.xml b/tutorials/NotepadCodeLab/Notepadv3Solution/AndroidManifest.xml
new file mode 100755
index 0000000..adb07ff
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3Solution/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.demo.notepad3">
+    <application android:icon="@drawable/icon">
+        <activity android:name=".Notepadv3" android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".NoteEdit"/>
+    </application>
+</manifest> 
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv3Solution/res/drawable/icon.png b/tutorials/NotepadCodeLab/Notepadv3Solution/res/drawable/icon.png
new file mode 100755
index 0000000..64e3601
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3Solution/res/drawable/icon.png
Binary files differ
diff --git a/tutorials/NotepadCodeLab/Notepadv3Solution/res/layout/note_edit.xml b/tutorials/NotepadCodeLab/Notepadv3Solution/res/layout/note_edit.xml
new file mode 100755
index 0000000..b254552
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3Solution/res/layout/note_edit.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	android:orientation="vertical" android:layout_width="fill_parent"
+	android:layout_height="fill_parent">
+	
+	<LinearLayout android:orientation="horizontal"
+		android:layout_width="fill_parent"
+		android:layout_height="wrap_content">
+
+		<TextView android:layout_width="wrap_content"
+			android:layout_height="wrap_content" 
+			android:text="@string/title" />
+		<EditText android:id="@+id/title" 
+		  android:layout_width="wrap_content"
+			android:layout_height="wrap_content" 
+			android:layout_weight="1"/>
+	</LinearLayout>
+
+	<TextView android:layout_width="wrap_content"
+		android:layout_height="wrap_content" 
+		android:text="@string/body" />
+	<EditText android:id="@+id/body" android:layout_width="fill_parent"
+		android:layout_height="wrap_content"
+		android:layout_weight="1"
+		android:scrollbars="vertical" />
+	
+	<Button android:id="@+id/confirm" 
+	  android:text="@string/confirm"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tutorials/NotepadCodeLab/Notepadv3Solution/res/layout/notes_list.xml b/tutorials/NotepadCodeLab/Notepadv3Solution/res/layout/notes_list.xml
new file mode 100755
index 0000000..29ae886
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3Solution/res/layout/notes_list.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+      android:layout_width="wrap_content"
+    	android:layout_height="wrap_content">
+    
+    <ListView android:id="@+id/android:list"
+          android:layout_width="wrap_content"
+        	android:layout_height="wrap_content"/>
+  	<TextView android:id="@+id/android:empty"
+          android:layout_width="wrap_content"
+        	android:layout_height="wrap_content"
+        	android:text="No Notes!"/>
+</LinearLayout>
diff --git a/tutorials/NotepadCodeLab/Notepadv3Solution/res/layout/notes_row.xml b/tutorials/NotepadCodeLab/Notepadv3Solution/res/layout/notes_row.xml
new file mode 100755
index 0000000..f28a41b
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3Solution/res/layout/notes_row.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView android:id="@+id/text1" xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"/>
diff --git a/tutorials/NotepadCodeLab/Notepadv3Solution/res/values/strings.xml b/tutorials/NotepadCodeLab/Notepadv3Solution/res/values/strings.xml
new file mode 100755
index 0000000..ae63b83
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3Solution/res/values/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Notepad v3</string>
+    <string name="no_notes">No Notes Yet</string>
+    <string name="menu_insert">Add Note</string>
+    <string name="menu_delete">Delete Note</string>
+    <string name="title">Title</string>
+    <string name="body">Body</string>
+    <string name="confirm">Confirm</string>
+    <string name="edit_note">Edit Note</string>
+</resources>
diff --git a/tutorials/NotepadCodeLab/Notepadv3Solution/src/com/android/demo/notepad3/NoteEdit.java b/tutorials/NotepadCodeLab/Notepadv3Solution/src/com/android/demo/notepad3/NoteEdit.java
new file mode 100755
index 0000000..710ea33
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3Solution/src/com/android/demo/notepad3/NoteEdit.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.demo.notepad3;
+
+import android.app.Activity;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+
+public class NoteEdit extends Activity {
+
+	private EditText mTitleText;
+    private EditText mBodyText;
+    private Long mRowId;
+    private NotesDbAdapter mDbHelper;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mDbHelper = new NotesDbAdapter(this);
+        mDbHelper.open();
+        setContentView(R.layout.note_edit);
+        
+       
+        mTitleText = (EditText) findViewById(R.id.title);
+        mBodyText = (EditText) findViewById(R.id.body);
+      
+        Button confirmButton = (Button) findViewById(R.id.confirm);
+       
+        mRowId = savedInstanceState != null ? savedInstanceState.getLong(NotesDbAdapter.KEY_ROWID) 
+                							: null;
+		if (mRowId == null) {
+			Bundle extras = getIntent().getExtras();            
+			mRowId = extras != null ? extras.getLong(NotesDbAdapter.KEY_ROWID) 
+									: null;
+		}
+
+		populateFields();
+		
+        confirmButton.setOnClickListener(new View.OnClickListener() {
+
+        	public void onClick(View view) {
+        	    setResult(RESULT_OK);
+        	    finish();
+        	}
+          
+        });
+    }
+    
+    private void populateFields() {
+        if (mRowId != null) {
+            Cursor note = mDbHelper.fetchNote(mRowId);
+            startManagingCursor(note);
+            mTitleText.setText(note.getString(
+    	            note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
+            mBodyText.setText(note.getString(
+                    note.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
+        }
+    }
+    
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
+    }
+    
+    @Override
+    protected void onPause() {
+        super.onPause();
+        saveState();
+    }
+    
+    @Override
+    protected void onResume() {
+        super.onResume();
+        populateFields();
+    }
+    
+    private void saveState() {
+        String title = mTitleText.getText().toString();
+        String body = mBodyText.getText().toString();
+
+        if (mRowId == null) {
+            long id = mDbHelper.createNote(title, body);
+            if (id > 0) {
+                mRowId = id;
+            }
+        } else {
+            mDbHelper.updateNote(mRowId, title, body);
+        }
+    }
+    
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv3Solution/src/com/android/demo/notepad3/Notepadv3.java b/tutorials/NotepadCodeLab/Notepadv3Solution/src/com/android/demo/notepad3/Notepadv3.java
new file mode 100755
index 0000000..7f99037
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3Solution/src/com/android/demo/notepad3/Notepadv3.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")savedInstanceState;
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.demo.notepad3;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.widget.ListView;
+import android.widget.SimpleCursorAdapter;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+
+public class Notepadv3 extends ListActivity {
+    private static final int ACTIVITY_CREATE=0;
+    private static final int ACTIVITY_EDIT=1;
+    
+    private static final int INSERT_ID = Menu.FIRST;
+    private static final int DELETE_ID = Menu.FIRST + 1;
+
+    private NotesDbAdapter mDbHelper;
+    
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.notes_list);
+        mDbHelper = new NotesDbAdapter(this);
+        mDbHelper.open();
+        fillData();
+        registerForContextMenu(getListView());
+    }
+    
+    private void fillData() {
+        Cursor notesCursor = mDbHelper.fetchAllNotes();
+        startManagingCursor(notesCursor);
+        
+        // Create an array to specify the fields we want to display in the list (only TITLE)
+        String[] from = new String[]{NotesDbAdapter.KEY_TITLE};
+        
+        // and an array of the fields we want to bind those fields to (in this case just text1)
+        int[] to = new int[]{R.id.text1};
+        
+        // Now create a simple cursor adapter and set it to display
+        SimpleCursorAdapter notes = 
+        	    new SimpleCursorAdapter(this, R.layout.notes_row, notesCursor, from, to);
+        setListAdapter(notes);
+    }
+    
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        menu.add(0, INSERT_ID, 0, R.string.menu_insert);
+        return true;
+    }
+
+    @Override
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        switch(item.getItemId()) {
+        case INSERT_ID:
+            createNote();
+            return true;
+        }
+       
+        return super.onMenuItemSelected(featureId, item);
+    }
+	
+    @Override
+	public void onCreateContextMenu(ContextMenu menu, View v,
+			ContextMenuInfo menuInfo) {
+		super.onCreateContextMenu(menu, v, menuInfo);
+        menu.add(0, DELETE_ID, 0, R.string.menu_delete);
+	}
+
+    @Override
+	public boolean onContextItemSelected(MenuItem item) {
+		switch(item.getItemId()) {
+    	case DELETE_ID:
+    		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
+	        mDbHelper.deleteNote(info.id);
+	        fillData();
+	        return true;
+		}
+		return super.onContextItemSelected(item);
+	}
+	
+    private void createNote() {
+        Intent i = new Intent(this, NoteEdit.class);
+        startActivityForResult(i, ACTIVITY_CREATE);
+    }
+    
+    @Override
+    protected void onListItemClick(ListView l, View v, int position, long id) {
+        super.onListItemClick(l, v, position, id);
+        Intent i = new Intent(this, NoteEdit.class);
+        i.putExtra(NotesDbAdapter.KEY_ROWID, id);
+        startActivityForResult(i, ACTIVITY_EDIT);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, 
+                                    Intent intent) {
+        super.onActivityResult(requestCode, resultCode, intent);
+        fillData();
+    }
+}
diff --git a/tutorials/NotepadCodeLab/Notepadv3Solution/src/com/android/demo/notepad3/NotesDbAdapter.java b/tutorials/NotepadCodeLab/Notepadv3Solution/src/com/android/demo/notepad3/NotesDbAdapter.java
new file mode 100755
index 0000000..61ad046
--- /dev/null
+++ b/tutorials/NotepadCodeLab/Notepadv3Solution/src/com/android/demo/notepad3/NotesDbAdapter.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.demo.notepad3;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+/**
+ * Simple notes database access helper class. Defines the basic CRUD operations
+ * for the notepad example, and gives the ability to list all notes as well as
+ * retrieve or modify a specific note.
+ * 
+ * This has been improved from the first version of this tutorial through the
+ * addition of better error handling and also using returning a Cursor instead
+ * of using a collection of inner classes (which is less scalable and not
+ * recommended).
+ */
+public class NotesDbAdapter {
+
+    public static final String KEY_TITLE = "title";
+    public static final String KEY_BODY = "body";
+    public static final String KEY_ROWID = "_id";
+
+    private static final String TAG = "NotesDbAdapter";
+    private DatabaseHelper mDbHelper;
+    private SQLiteDatabase mDb;
+    
+    /**
+     * Database creation sql statement
+     */
+    private static final String DATABASE_CREATE =
+            "create table notes (_id integer primary key autoincrement, "
+                    + "title text not null, body text not null);";
+
+    private static final String DATABASE_NAME = "data";
+    private static final String DATABASE_TABLE = "notes";
+    private static final int DATABASE_VERSION = 2;
+
+    private final Context mCtx;
+
+    private static class DatabaseHelper extends SQLiteOpenHelper {
+
+        DatabaseHelper(Context context) {
+            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+
+            db.execSQL(DATABASE_CREATE);
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+                    + newVersion + ", which will destroy all old data");
+            db.execSQL("DROP TABLE IF EXISTS notes");
+            onCreate(db);
+        }
+    }
+
+    /**
+     * Constructor - takes the context to allow the database to be
+     * opened/created
+     * 
+     * @param ctx the Context within which to work
+     */
+    public NotesDbAdapter(Context ctx) {
+        this.mCtx = ctx;
+    }
+
+    /**
+     * Open the notes database. If it cannot be opened, try to create a new
+     * instance of the database. If it cannot be created, throw an exception to
+     * signal the failure
+     * 
+     * @return this (self reference, allowing this to be chained in an
+     *         initialization call)
+     * @throws SQLException if the database could be neither opened or created
+     */
+    public NotesDbAdapter open() throws SQLException {
+        mDbHelper = new DatabaseHelper(mCtx);
+        mDb = mDbHelper.getWritableDatabase();
+        return this;
+    }
+    
+    public void close() {
+        mDbHelper.close();
+    }
+
+
+    /**
+     * Create a new note using the title and body provided. If the note is
+     * successfully created return the new rowId for that note, otherwise return
+     * a -1 to indicate failure.
+     * 
+     * @param title the title of the note
+     * @param body the body of the note
+     * @return rowId or -1 if failed
+     */
+    public long createNote(String title, String body) {
+        ContentValues initialValues = new ContentValues();
+        initialValues.put(KEY_TITLE, title);
+        initialValues.put(KEY_BODY, body);
+
+        return mDb.insert(DATABASE_TABLE, null, initialValues);
+    }
+
+    /**
+     * Delete the note with the given rowId
+     * 
+     * @param rowId id of note to delete
+     * @return true if deleted, false otherwise
+     */
+    public boolean deleteNote(long rowId) {
+
+        return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
+    }
+
+    /**
+     * Return a Cursor over the list of all notes in the database
+     * 
+     * @return Cursor over all notes
+     */
+    public Cursor fetchAllNotes() {
+
+        return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_TITLE,
+                KEY_BODY}, null, null, null, null, null);
+    }
+
+    /**
+     * Return a Cursor positioned at the note that matches the given rowId
+     * 
+     * @param rowId id of note to retrieve
+     * @return Cursor positioned to matching note, if found
+     * @throws SQLException if note could not be found/retrieved
+     */
+    public Cursor fetchNote(long rowId) throws SQLException {
+
+        Cursor mCursor =
+
+                mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
+                        KEY_TITLE, KEY_BODY}, KEY_ROWID + "=" + rowId, null,
+                        null, null, null, null);
+        if (mCursor != null) {
+            mCursor.moveToFirst();
+        }
+        return mCursor;
+
+    }
+
+    /**
+     * Update the note using the details provided. The note to be updated is
+     * specified using the rowId, and it is altered to use the title and body
+     * values passed in
+     * 
+     * @param rowId id of note to update
+     * @param title value to set note title to
+     * @param body value to set note body to
+     * @return true if the note was successfully updated, false otherwise
+     */
+    public boolean updateNote(long rowId, String title, String body) {
+        ContentValues args = new ContentValues();
+        args.put(KEY_TITLE, title);
+        args.put(KEY_BODY, body);
+
+        return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0;
+    }
+}