auto import from //depot/cupcake/@135843
diff --git a/samples/NotePad/Android.mk b/samples/NotePad/Android.mk
new file mode 100644
index 0000000..7939212
--- /dev/null
+++ b/samples/NotePad/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := NotePad
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/samples/NotePad/AndroidManifest.xml b/samples/NotePad/AndroidManifest.xml
new file mode 100644
index 0000000..5c56daf
--- /dev/null
+++ b/samples/NotePad/AndroidManifest.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ 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.
+-->
+
+<!-- Declare the contents of this Android application. The namespace
+ attribute brings in the Android platform namespace, and the package
+ supplies a unique name for the application. When writing your
+ own application, the package name must be changed from "com.example.*"
+ to come from a domain that you own or have control over. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.notepad"
+>
+ <application android:icon="@drawable/app_notes"
+ android:label="@string/app_name"
+ >
+ <provider android:name="NotePadProvider"
+ android:authorities="com.google.provider.NotePad"
+ />
+
+ <activity android:name="NotesList" android:label="@string/title_notes_list">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <action android:name="android.intent.action.EDIT" />
+ <action android:name="android.intent.action.PICK" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.GET_CONTENT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="NoteEditor"
+ android:theme="@android:style/Theme.Light"
+ android:label="@string/title_note"
+ android:screenOrientation="sensor"
+ android:configChanges="keyboardHidden|orientation"
+ >
+ <!-- This filter says that we can view or edit the data of
+ a single note -->
+ <intent-filter android:label="@string/resolve_edit">
+ <action android:name="android.intent.action.VIEW" />
+ <action android:name="android.intent.action.EDIT" />
+ <action android:name="com.android.notepad.action.EDIT_NOTE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
+ </intent-filter>
+
+ <!-- This filter says that we can create a new note inside
+ of a directory of notes. -->
+ <intent-filter>
+ <action android:name="android.intent.action.INSERT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />
+ </intent-filter>
+
+ </activity>
+
+ <activity android:name="TitleEditor" android:label="@string/title_edit_title"
+ android:theme="@android:style/Theme.Dialog"
+ android:windowSoftInputMode="stateVisible">
+ <!-- This activity implements an alternative action that can be
+ performed on notes: editing their title. It can be used as
+ a default operation if the user invokes this action, and is
+ available as an alternative action for any note data. -->
+ <intent-filter android:label="@string/resolve_title">
+ <!-- This is the action we perform. It is a custom action we
+ define for our application, not a generic VIEW or EDIT
+ action since we are not a general note viewer/editor. -->
+ <action android:name="com.android.notepad.action.EDIT_TITLE" />
+ <!-- DEFAULT: execute if being directly invoked. -->
+ <category android:name="android.intent.category.DEFAULT" />
+ <!-- ALTERNATIVE: show as an alternative action when the user is
+ working with this type of data. -->
+ <category android:name="android.intent.category.ALTERNATIVE" />
+ <!-- SELECTED_ALTERNATIVE: show as an alternative action the user
+ can perform when selecting this type of data. -->
+ <category android:name="android.intent.category.SELECTED_ALTERNATIVE" />
+ <!-- This is the data type we operate on. -->
+ <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
+ </intent-filter>
+ </activity>
+
+ </application>
+</manifest>
+
diff --git a/samples/NotePad/_index.html b/samples/NotePad/_index.html
new file mode 100644
index 0000000..2a18969
--- /dev/null
+++ b/samples/NotePad/_index.html
@@ -0,0 +1,12 @@
+<p>A simple note pad application.
+It demonstrates...
+<ul>
+<li>using views
+<li>accessing a database
+<li>using an intent to open a new window
+<li>managing activity lifecycle
+<li>and many other goodies...
+</ul>
+</p>
+<img alt="Note Pad Example" class="gallery" src="sample_notepad.png" >
+<img alt="Note Pad Example" class="gallery" src="sample_note.png" >
diff --git a/samples/NotePad/res/drawable/app_notes.png b/samples/NotePad/res/drawable/app_notes.png
new file mode 100644
index 0000000..0479138
--- /dev/null
+++ b/samples/NotePad/res/drawable/app_notes.png
Binary files differ
diff --git a/samples/NotePad/res/layout/note_editor.xml b/samples/NotePad/res/layout/note_editor.xml
new file mode 100644
index 0000000..c54a963
--- /dev/null
+++ b/samples/NotePad/res/layout/note_editor.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ 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.
+-->
+
+<view xmlns:android="http://schemas.android.com/apk/res/android"
+ class="com.example.android.notepad.NoteEditor$LinedEditText"
+ android:id="@+id/note"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@android:color/transparent"
+ android:padding="5dip"
+ android:scrollbars="vertical"
+ android:fadingEdge="vertical"
+ android:gravity="top"
+ android:textSize="22sp"
+ android:capitalize="sentences"
+/>
diff --git a/samples/NotePad/res/layout/noteslist_item.xml b/samples/NotePad/res/layout/noteslist_item.xml
new file mode 100644
index 0000000..b167734
--- /dev/null
+++ b/samples/NotePad/res/layout/noteslist_item.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+ 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:gravity="center_vertical"
+ android:paddingLeft="5dip"
+ android:singleLine="true"
+/>
diff --git a/samples/NotePad/res/layout/title_editor.xml b/samples/NotePad/res/layout/title_editor.xml
new file mode 100644
index 0000000..3593ec6
--- /dev/null
+++ b/samples/NotePad/res/layout/title_editor.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingLeft="6dip"
+ android:paddingRight="6dip"
+ android:paddingBottom="3dip">
+
+ <EditText android:id="@+id/title"
+ android:maxLines="1"
+ android:layout_marginTop="2dip"
+ android:layout_width="wrap_content"
+ android:ems="25"
+ android:layout_height="wrap_content"
+ android:autoText="true"
+ android:capitalize="sentences"
+ android:scrollHorizontally="true" />
+
+ <Button android:id="@+id/ok"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right"
+ android:text="@string/button_ok" />
+
+</LinearLayout>
diff --git a/samples/NotePad/res/values/strings.xml b/samples/NotePad/res/values/strings.xml
new file mode 100644
index 0000000..b4bf671
--- /dev/null
+++ b/samples/NotePad/res/values/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ 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.
+-->
+
+<resources>
+ <string name="menu_delete">Delete</string>
+ <string name="menu_insert">Add note</string>
+ <string name="menu_revert">Revert</string>
+ <string name="menu_discard">Discard</string>
+
+ <string name="resolve_edit">Edit note</string>
+ <string name="resolve_title">Edit title</string>
+
+ <string name="title_create">Create note</string>
+ <string name="title_edit">Edit note</string>
+ <string name="title_notes_list">Note pad</string>
+ <string name="title_note">Note</string>
+ <string name="title_edit_title">Note title:</string>
+
+ <string name="app_name">Note Pad</string>
+
+ <string name="button_ok">OK</string>
+
+ <string name="error_title">Error</string>
+ <string name="error_message">Error loading note</string>
+</resources>
diff --git a/samples/NotePad/sample_note.png b/samples/NotePad/sample_note.png
new file mode 100644
index 0000000..cea1a08
--- /dev/null
+++ b/samples/NotePad/sample_note.png
Binary files differ
diff --git a/samples/NotePad/sample_notepad.png b/samples/NotePad/sample_notepad.png
new file mode 100644
index 0000000..c498847
--- /dev/null
+++ b/samples/NotePad/sample_notepad.png
Binary files differ
diff --git a/samples/NotePad/src/com/example/android/notepad/NoteEditor.java b/samples/NotePad/src/com/example/android/notepad/NoteEditor.java
new file mode 100644
index 0000000..e45efd8
--- /dev/null
+++ b/samples/NotePad/src/com/example/android/notepad/NoteEditor.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.example.android.notepad;
+
+import com.example.android.notepad.NotePad.Notes;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.EditText;
+
+/**
+ * A generic activity for editing a note in a database. This can be used
+ * either to simply view a note {@link Intent#ACTION_VIEW}, view and edit a note
+ * {@link Intent#ACTION_EDIT}, or create a new note {@link Intent#ACTION_INSERT}.
+ */
+public class NoteEditor extends Activity {
+ private static final String TAG = "Notes";
+
+ /**
+ * Standard projection for the interesting columns of a normal note.
+ */
+ private static final String[] PROJECTION = new String[] {
+ Notes._ID, // 0
+ Notes.NOTE, // 1
+ };
+ /** The index of the note column */
+ private static final int COLUMN_INDEX_NOTE = 1;
+
+ // This is our state data that is stored when freezing.
+ private static final String ORIGINAL_CONTENT = "origContent";
+
+ // Identifiers for our menu items.
+ private static final int REVERT_ID = Menu.FIRST;
+ private static final int DISCARD_ID = Menu.FIRST + 1;
+ private static final int DELETE_ID = Menu.FIRST + 2;
+
+ // The different distinct states the activity can be run in.
+ private static final int STATE_EDIT = 0;
+ private static final int STATE_INSERT = 1;
+
+ private int mState;
+ private boolean mNoteOnly = false;
+ private Uri mUri;
+ private Cursor mCursor;
+ private EditText mText;
+ private String mOriginalContent;
+
+ /**
+ * A custom EditText that draws lines between each line of text that is displayed.
+ */
+ public static class LinedEditText extends EditText {
+ private Rect mRect;
+ private Paint mPaint;
+
+ // we need this constructor for LayoutInflater
+ public LinedEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mRect = new Rect();
+ mPaint = new Paint();
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(0x800000FF);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ int count = getLineCount();
+ Rect r = mRect;
+ Paint paint = mPaint;
+
+ for (int i = 0; i < count; i++) {
+ int baseline = getLineBounds(i, r);
+
+ canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint);
+ }
+
+ super.onDraw(canvas);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final Intent intent = getIntent();
+
+ // Do some setup based on the action being performed.
+
+ final String action = intent.getAction();
+ if (Intent.ACTION_EDIT.equals(action)) {
+ // Requested to edit: set that state, and the data being edited.
+ mState = STATE_EDIT;
+ mUri = intent.getData();
+ } else if (Intent.ACTION_INSERT.equals(action)) {
+ // Requested to insert: set that state, and create a new entry
+ // in the container.
+ mState = STATE_INSERT;
+ mUri = getContentResolver().insert(intent.getData(), null);
+
+ // If we were unable to create a new note, then just finish
+ // this activity. A RESULT_CANCELED will be sent back to the
+ // original activity if they requested a result.
+ if (mUri == null) {
+ Log.e(TAG, "Failed to insert new note into " + getIntent().getData());
+ finish();
+ return;
+ }
+
+ // The new entry was created, so assume all will end well and
+ // set the result to be returned.
+ setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
+
+ } else {
+ // Whoops, unknown action! Bail.
+ Log.e(TAG, "Unknown action, exiting");
+ finish();
+ return;
+ }
+
+ // Set the layout for this activity. You can find it in res/layout/note_editor.xml
+ setContentView(R.layout.note_editor);
+
+ // The text view for our note, identified by its ID in the XML file.
+ mText = (EditText) findViewById(R.id.note);
+
+ // Get the note!
+ mCursor = managedQuery(mUri, PROJECTION, null, null, null);
+
+ // If an instance of this activity had previously stopped, we can
+ // get the original text it started with.
+ if (savedInstanceState != null) {
+ mOriginalContent = savedInstanceState.getString(ORIGINAL_CONTENT);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ // If we didn't have any trouble retrieving the data, it is now
+ // time to get at the stuff.
+ if (mCursor != null) {
+ // Make sure we are at the one and only row in the cursor.
+ mCursor.moveToFirst();
+
+ // Modify our overall title depending on the mode we are running in.
+ if (mState == STATE_EDIT) {
+ setTitle(getText(R.string.title_edit));
+ } else if (mState == STATE_INSERT) {
+ setTitle(getText(R.string.title_create));
+ }
+
+ // This is a little tricky: we may be resumed after previously being
+ // paused/stopped. We want to put the new text in the text view,
+ // but leave the user where they were (retain the cursor position
+ // etc). This version of setText does that for us.
+ String note = mCursor.getString(COLUMN_INDEX_NOTE);
+ mText.setTextKeepState(note);
+
+ // If we hadn't previously retrieved the original text, do so
+ // now. This allows the user to revert their changes.
+ if (mOriginalContent == null) {
+ mOriginalContent = note;
+ }
+
+ } else {
+ setTitle(getText(R.string.error_title));
+ mText.setText(getText(R.string.error_message));
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ // Save away the original text, so we still have it if the activity
+ // needs to be killed while paused.
+ outState.putString(ORIGINAL_CONTENT, mOriginalContent);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ // The user is going somewhere else, so make sure their current
+ // changes are safely saved away in the provider. We don't need
+ // to do this if only editing.
+ if (mCursor != null) {
+ String text = mText.getText().toString();
+ int length = text.length();
+
+ // If this activity is finished, and there is no text, then we
+ // do something a little special: simply delete the note entry.
+ // Note that we do this both for editing and inserting... it
+ // would be reasonable to only do it when inserting.
+ if (isFinishing() && (length == 0) && !mNoteOnly) {
+ setResult(RESULT_CANCELED);
+ deleteNote();
+
+ // Get out updates into the provider.
+ } else {
+ ContentValues values = new ContentValues();
+
+ // This stuff is only done when working with a full-fledged note.
+ if (!mNoteOnly) {
+ // Bump the modification time to now.
+ values.put(Notes.MODIFIED_DATE, System.currentTimeMillis());
+
+ // If we are creating a new note, then we want to also create
+ // an initial title for it.
+ if (mState == STATE_INSERT) {
+ String title = text.substring(0, Math.min(30, length));
+ if (length > 30) {
+ int lastSpace = title.lastIndexOf(' ');
+ if (lastSpace > 0) {
+ title = title.substring(0, lastSpace);
+ }
+ }
+ values.put(Notes.TITLE, title);
+ }
+ }
+
+ // Write our text back into the provider.
+ values.put(Notes.NOTE, text);
+
+ // Commit all of our changes to persistent storage. When the update completes
+ // the content provider will notify the cursor of the change, which will
+ // cause the UI to be updated.
+ getContentResolver().update(mUri, values, null, null);
+ }
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ // Build the menus that are shown when editing.
+ if (mState == STATE_EDIT) {
+ menu.add(0, REVERT_ID, 0, R.string.menu_revert)
+ .setShortcut('0', 'r')
+ .setIcon(android.R.drawable.ic_menu_revert);
+ if (!mNoteOnly) {
+ menu.add(0, DELETE_ID, 0, R.string.menu_delete)
+ .setShortcut('1', 'd')
+ .setIcon(android.R.drawable.ic_menu_delete);
+ }
+
+ // Build the menus that are shown when inserting.
+ } else {
+ menu.add(0, DISCARD_ID, 0, R.string.menu_discard)
+ .setShortcut('0', 'd')
+ .setIcon(android.R.drawable.ic_menu_delete);
+ }
+
+ // If we are working on a full note, then append to the
+ // menu items for any other activities that can do stuff with it
+ // as well. This does a query on the system for any activities that
+ // implement the ALTERNATIVE_ACTION for our data, adding a menu item
+ // for each one that is found.
+ if (!mNoteOnly) {
+ Intent intent = new Intent(null, getIntent().getData());
+ intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
+ menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
+ new ComponentName(this, NoteEditor.class), null, intent, 0, null);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle all of the possible menu actions.
+ switch (item.getItemId()) {
+ case DELETE_ID:
+ deleteNote();
+ finish();
+ break;
+ case DISCARD_ID:
+ cancelNote();
+ break;
+ case REVERT_ID:
+ cancelNote();
+ break;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * Take care of canceling work on a note. Deletes the note if we
+ * had created it, otherwise reverts to the original text.
+ */
+ private final void cancelNote() {
+ if (mCursor != null) {
+ if (mState == STATE_EDIT) {
+ // Put the original note text back into the database
+ mCursor.close();
+ mCursor = null;
+ ContentValues values = new ContentValues();
+ values.put(Notes.NOTE, mOriginalContent);
+ getContentResolver().update(mUri, values, null, null);
+ } else if (mState == STATE_INSERT) {
+ // We inserted an empty note, make sure to delete it
+ deleteNote();
+ }
+ }
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+
+ /**
+ * Take care of deleting a note. Simply deletes the entry.
+ */
+ private final void deleteNote() {
+ if (mCursor != null) {
+ mCursor.close();
+ mCursor = null;
+ getContentResolver().delete(mUri, null, null);
+ mText.setText("");
+ }
+ }
+}
diff --git a/samples/NotePad/src/com/example/android/notepad/NotePad.java b/samples/NotePad/src/com/example/android/notepad/NotePad.java
new file mode 100644
index 0000000..25be23e
--- /dev/null
+++ b/samples/NotePad/src/com/example/android/notepad/NotePad.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.example.android.notepad;
+
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+/**
+ * Convenience definitions for NotePadProvider
+ */
+public final class NotePad {
+ public static final String AUTHORITY = "com.google.provider.NotePad";
+
+ // This class cannot be instantiated
+ private NotePad() {}
+
+ /**
+ * Notes table
+ */
+ public static final class Notes implements BaseColumns {
+ // This class cannot be instantiated
+ private Notes() {}
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/notes");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of notes.
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.note";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} sub-directory of a single note.
+ */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.note";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "modified DESC";
+
+ /**
+ * The title of the note
+ * <P>Type: TEXT</P>
+ */
+ public static final String TITLE = "title";
+
+ /**
+ * The note itself
+ * <P>Type: TEXT</P>
+ */
+ public static final String NOTE = "note";
+
+ /**
+ * The timestamp for when the note was created
+ * <P>Type: INTEGER (long from System.curentTimeMillis())</P>
+ */
+ public static final String CREATED_DATE = "created";
+
+ /**
+ * The timestamp for when the note was last modified
+ * <P>Type: INTEGER (long from System.curentTimeMillis())</P>
+ */
+ public static final String MODIFIED_DATE = "modified";
+ }
+}
diff --git a/samples/NotePad/src/com/example/android/notepad/NotePadProvider.java b/samples/NotePad/src/com/example/android/notepad/NotePadProvider.java
new file mode 100644
index 0000000..f1d3fdc
--- /dev/null
+++ b/samples/NotePad/src/com/example/android/notepad/NotePadProvider.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.example.android.notepad;
+
+import com.example.android.notepad.NotePad.Notes;
+
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.HashMap;
+
+/**
+ * Provides access to a database of notes. Each note has a title, the note
+ * itself, a creation date and a modified data.
+ */
+public class NotePadProvider extends ContentProvider {
+
+ private static final String TAG = "NotePadProvider";
+
+ private static final String DATABASE_NAME = "note_pad.db";
+ private static final int DATABASE_VERSION = 2;
+ private static final String NOTES_TABLE_NAME = "notes";
+
+ private static HashMap<String, String> sNotesProjectionMap;
+
+ private static final int NOTES = 1;
+ private static final int NOTE_ID = 2;
+
+ private static final UriMatcher sUriMatcher;
+
+ /**
+ * This class helps open, create, and upgrade the database file.
+ */
+ private static class DatabaseHelper extends SQLiteOpenHelper {
+
+ DatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE " + NOTES_TABLE_NAME + " ("
+ + Notes._ID + " INTEGER PRIMARY KEY,"
+ + Notes.TITLE + " TEXT,"
+ + Notes.NOTE + " TEXT,"
+ + Notes.CREATED_DATE + " INTEGER,"
+ + Notes.MODIFIED_DATE + " INTEGER"
+ + ");");
+ }
+
+ @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);
+ }
+ }
+
+ private DatabaseHelper mOpenHelper;
+
+ @Override
+ public boolean onCreate() {
+ mOpenHelper = new DatabaseHelper(getContext());
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+
+ switch (sUriMatcher.match(uri)) {
+ case NOTES:
+ qb.setTables(NOTES_TABLE_NAME);
+ qb.setProjectionMap(sNotesProjectionMap);
+ break;
+
+ case NOTE_ID:
+ qb.setTables(NOTES_TABLE_NAME);
+ qb.setProjectionMap(sNotesProjectionMap);
+ qb.appendWhere(Notes._ID + "=" + uri.getPathSegments().get(1));
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ // If no sort order is specified use the default
+ String orderBy;
+ if (TextUtils.isEmpty(sortOrder)) {
+ orderBy = NotePad.Notes.DEFAULT_SORT_ORDER;
+ } else {
+ orderBy = sortOrder;
+ }
+
+ // Get the database and run the query
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
+
+ // Tell the cursor what uri to watch, so it knows when its source data changes
+ c.setNotificationUri(getContext().getContentResolver(), uri);
+ return c;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ switch (sUriMatcher.match(uri)) {
+ case NOTES:
+ return Notes.CONTENT_TYPE;
+
+ case NOTE_ID:
+ return Notes.CONTENT_ITEM_TYPE;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues initialValues) {
+ // Validate the requested uri
+ if (sUriMatcher.match(uri) != NOTES) {
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ ContentValues values;
+ if (initialValues != null) {
+ values = new ContentValues(initialValues);
+ } else {
+ values = new ContentValues();
+ }
+
+ Long now = Long.valueOf(System.currentTimeMillis());
+
+ // Make sure that the fields are all set
+ if (values.containsKey(NotePad.Notes.CREATED_DATE) == false) {
+ values.put(NotePad.Notes.CREATED_DATE, now);
+ }
+
+ if (values.containsKey(NotePad.Notes.MODIFIED_DATE) == false) {
+ values.put(NotePad.Notes.MODIFIED_DATE, now);
+ }
+
+ if (values.containsKey(NotePad.Notes.TITLE) == false) {
+ Resources r = Resources.getSystem();
+ values.put(NotePad.Notes.TITLE, r.getString(android.R.string.untitled));
+ }
+
+ if (values.containsKey(NotePad.Notes.NOTE) == false) {
+ values.put(NotePad.Notes.NOTE, "");
+ }
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ long rowId = db.insert(NOTES_TABLE_NAME, Notes.NOTE, values);
+ if (rowId > 0) {
+ Uri noteUri = ContentUris.withAppendedId(NotePad.Notes.CONTENT_URI, rowId);
+ getContext().getContentResolver().notifyChange(noteUri, null);
+ return noteUri;
+ }
+
+ throw new SQLException("Failed to insert row into " + uri);
+ }
+
+ @Override
+ public int delete(Uri uri, String where, String[] whereArgs) {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count;
+ switch (sUriMatcher.match(uri)) {
+ case NOTES:
+ count = db.delete(NOTES_TABLE_NAME, where, whereArgs);
+ break;
+
+ case NOTE_ID:
+ String noteId = uri.getPathSegments().get(1);
+ count = db.delete(NOTES_TABLE_NAME, Notes._ID + "=" + noteId
+ + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ getContext().getContentResolver().notifyChange(uri, null);
+ return count;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count;
+ switch (sUriMatcher.match(uri)) {
+ case NOTES:
+ count = db.update(NOTES_TABLE_NAME, values, where, whereArgs);
+ break;
+
+ case NOTE_ID:
+ String noteId = uri.getPathSegments().get(1);
+ count = db.update(NOTES_TABLE_NAME, values, Notes._ID + "=" + noteId
+ + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ getContext().getContentResolver().notifyChange(uri, null);
+ return count;
+ }
+
+ static {
+ sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ sUriMatcher.addURI(NotePad.AUTHORITY, "notes", NOTES);
+ sUriMatcher.addURI(NotePad.AUTHORITY, "notes/#", NOTE_ID);
+
+ sNotesProjectionMap = new HashMap<String, String>();
+ sNotesProjectionMap.put(Notes._ID, Notes._ID);
+ sNotesProjectionMap.put(Notes.TITLE, Notes.TITLE);
+ sNotesProjectionMap.put(Notes.NOTE, Notes.NOTE);
+ sNotesProjectionMap.put(Notes.CREATED_DATE, Notes.CREATED_DATE);
+ sNotesProjectionMap.put(Notes.MODIFIED_DATE, Notes.MODIFIED_DATE);
+ }
+}
diff --git a/samples/NotePad/src/com/example/android/notepad/NotesList.java b/samples/NotePad/src/com/example/android/notepad/NotesList.java
new file mode 100644
index 0000000..ceaaa3c
--- /dev/null
+++ b/samples/NotePad/src/com/example/android/notepad/NotesList.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.example.android.notepad;
+
+import com.example.android.notepad.NotePad.Notes;
+
+import android.app.ListActivity;
+import android.content.ComponentName;
+import android.content.ContentUris;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.SimpleCursorAdapter;
+
+/**
+ * Displays a list of notes. Will display notes from the {@link Uri}
+ * provided in the intent if there is one, otherwise defaults to displaying the
+ * contents of the {@link NotePadProvider}
+ */
+public class NotesList extends ListActivity {
+ private static final String TAG = "NotesList";
+
+ // Menu item ids
+ public static final int MENU_ITEM_DELETE = Menu.FIRST;
+ public static final int MENU_ITEM_INSERT = Menu.FIRST + 1;
+
+ /**
+ * The columns we are interested in from the database
+ */
+ private static final String[] PROJECTION = new String[] {
+ Notes._ID, // 0
+ Notes.TITLE, // 1
+ };
+
+ /** The index of the title column */
+ private static final int COLUMN_INDEX_TITLE = 1;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
+
+ // If no data was given in the intent (because we were started
+ // as a MAIN activity), then use our default content provider.
+ Intent intent = getIntent();
+ if (intent.getData() == null) {
+ intent.setData(Notes.CONTENT_URI);
+ }
+
+ // Inform the list we provide context menus for items
+ getListView().setOnCreateContextMenuListener(this);
+
+ // Perform a managed query. The Activity will handle closing and requerying the cursor
+ // when needed.
+ Cursor cursor = managedQuery(getIntent().getData(), PROJECTION, null, null,
+ Notes.DEFAULT_SORT_ORDER);
+
+ // Used to map notes entries from the database to views
+ SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.noteslist_item, cursor,
+ new String[] { Notes.TITLE }, new int[] { android.R.id.text1 });
+ setListAdapter(adapter);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+
+ // This is our one standard application action -- inserting a
+ // new note into the list.
+ menu.add(0, MENU_ITEM_INSERT, 0, R.string.menu_insert)
+ .setShortcut('3', 'a')
+ .setIcon(android.R.drawable.ic_menu_add);
+
+ // Generate any additional actions that can be performed on the
+ // overall list. In a normal install, there are no additional
+ // actions found here, but this allows other applications to extend
+ // our menu with their own actions.
+ Intent intent = new Intent(null, getIntent().getData());
+ intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
+ menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
+ new ComponentName(this, NotesList.class), null, intent, 0, null);
+
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ final boolean haveItems = getListAdapter().getCount() > 0;
+
+ // If there are any notes in the list (which implies that one of
+ // them is selected), then we need to generate the actions that
+ // can be performed on the current selection. This will be a combination
+ // of our own specific actions along with any extensions that can be
+ // found.
+ if (haveItems) {
+ // This is the selected item.
+ Uri uri = ContentUris.withAppendedId(getIntent().getData(), getSelectedItemId());
+
+ // Build menu... always starts with the EDIT action...
+ Intent[] specifics = new Intent[1];
+ specifics[0] = new Intent(Intent.ACTION_EDIT, uri);
+ MenuItem[] items = new MenuItem[1];
+
+ // ... is followed by whatever other actions are available...
+ Intent intent = new Intent(null, uri);
+ intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
+ menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, null, specifics, intent, 0,
+ items);
+
+ // Give a shortcut to the edit action.
+ if (items[0] != null) {
+ items[0].setShortcut('1', 'e');
+ }
+ } else {
+ menu.removeGroup(Menu.CATEGORY_ALTERNATIVE);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case MENU_ITEM_INSERT:
+ // Launch activity to insert a new item
+ startActivity(new Intent(Intent.ACTION_INSERT, getIntent().getData()));
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
+ AdapterView.AdapterContextMenuInfo info;
+ try {
+ info = (AdapterView.AdapterContextMenuInfo) menuInfo;
+ } catch (ClassCastException e) {
+ Log.e(TAG, "bad menuInfo", e);
+ return;
+ }
+
+ Cursor cursor = (Cursor) getListAdapter().getItem(info.position);
+ if (cursor == null) {
+ // For some reason the requested item isn't available, do nothing
+ return;
+ }
+
+ // Setup the menu header
+ menu.setHeaderTitle(cursor.getString(COLUMN_INDEX_TITLE));
+
+ // Add a menu item to delete the note
+ menu.add(0, MENU_ITEM_DELETE, 0, R.string.menu_delete);
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ AdapterView.AdapterContextMenuInfo info;
+ try {
+ info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
+ } catch (ClassCastException e) {
+ Log.e(TAG, "bad menuInfo", e);
+ return false;
+ }
+
+ switch (item.getItemId()) {
+ case MENU_ITEM_DELETE: {
+ // Delete the note that the context menu is for
+ Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id);
+ getContentResolver().delete(noteUri, null, null);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ Uri uri = ContentUris.withAppendedId(getIntent().getData(), id);
+
+ String action = getIntent().getAction();
+ if (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action)) {
+ // The caller is waiting for us to return a note selected by
+ // the user. The have clicked on one, so return it now.
+ setResult(RESULT_OK, new Intent().setData(uri));
+ } else {
+ // Launch activity to view/edit the currently selected item
+ startActivity(new Intent(Intent.ACTION_EDIT, uri));
+ }
+ }
+}
diff --git a/samples/NotePad/src/com/example/android/notepad/TitleEditor.java b/samples/NotePad/src/com/example/android/notepad/TitleEditor.java
new file mode 100644
index 0000000..50d38e5
--- /dev/null
+++ b/samples/NotePad/src/com/example/android/notepad/TitleEditor.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.example.android.notepad;
+
+import com.example.android.notepad.NotePad.Notes;
+
+import android.app.Activity;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+
+/**
+ * An activity that will edit the title of a note. Displays a floating
+ * window with a text field.
+ */
+public class TitleEditor extends Activity implements View.OnClickListener {
+
+ /**
+ * This is a special intent action that means "edit the title of a note".
+ */
+ public static final String EDIT_TITLE_ACTION = "com.android.notepad.action.EDIT_TITLE";
+
+ /**
+ * An array of the columns we are interested in.
+ */
+ private static final String[] PROJECTION = new String[] {
+ NotePad.Notes._ID, // 0
+ NotePad.Notes.TITLE, // 1
+ };
+ /** Index of the title column */
+ private static final int COLUMN_INDEX_TITLE = 1;
+
+ /**
+ * Cursor which will provide access to the note whose title we are editing.
+ */
+ private Cursor mCursor;
+
+ /**
+ * The EditText field from our UI. Keep track of this so we can extract the
+ * text when we are finished.
+ */
+ private EditText mText;
+
+ /**
+ * The content URI to the note that's being edited.
+ */
+ private Uri mUri;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.title_editor);
+
+ // Get the uri of the note whose title we want to edit
+ mUri = getIntent().getData();
+
+ // Get a cursor to access the note
+ mCursor = managedQuery(mUri, PROJECTION, null, null, null);
+
+ // Set up click handlers for the text field and button
+ mText = (EditText) this.findViewById(R.id.title);
+ mText.setOnClickListener(this);
+
+ Button b = (Button) findViewById(R.id.ok);
+ b.setOnClickListener(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ // Initialize the text with the title column from the cursor
+ if (mCursor != null) {
+ mCursor.moveToFirst();
+ mText.setText(mCursor.getString(COLUMN_INDEX_TITLE));
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ if (mCursor != null) {
+ // Write the title back to the note
+ ContentValues values = new ContentValues();
+ values.put(Notes.TITLE, mText.getText().toString());
+ getContentResolver().update(mUri, values, null, null);
+ }
+ }
+
+ public void onClick(View v) {
+ // When the user clicks, just finish this activity.
+ // onPause will be called, and we save our data there.
+ finish();
+ }
+}
diff --git a/samples/NotePad/src/com/google/provider/NotePad.java b/samples/NotePad/src/com/google/provider/NotePad.java
new file mode 100644
index 0000000..f8de69b
--- /dev/null
+++ b/samples/NotePad/src/com/google/provider/NotePad.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.google.provider;
+
+import android.net.Uri;
+import android.provider.BaseColumns;
+
+/**
+ * Convenience definitions for NotePadProvider
+ */
+public final class NotePad {
+ /**
+ * Notes table
+ */
+ public static final class Notes implements BaseColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI
+ = Uri.parse("content://com.google.provider.NotePad/notes");
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "modified DESC";
+
+ /**
+ * The title of the note
+ * <P>Type: TEXT</P>
+ */
+ public static final String TITLE = "title";
+
+ /**
+ * The note itself
+ * <P>Type: TEXT</P>
+ */
+ public static final String NOTE = "note";
+
+ /**
+ * The timestamp for when the note was created
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String CREATED_DATE = "created";
+
+ /**
+ * The timestamp for when the note was last modified
+ * <P>Type: INTEGER (long)</P>
+ */
+ public static final String MODIFIED_DATE = "modified";
+ }
+}
diff --git a/samples/NotePad/tests/Android.mk b/samples/NotePad/tests/Android.mk
new file mode 100644
index 0000000..43efafc
--- /dev/null
+++ b/samples/NotePad/tests/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := NotePadTests
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_INSTRUMENTATION_FOR := NotePad
+
+include $(BUILD_PACKAGE)
diff --git a/samples/NotePad/tests/AndroidManifest.xml b/samples/NotePad/tests/AndroidManifest.xml
new file mode 100644
index 0000000..afd502b
--- /dev/null
+++ b/samples/NotePad/tests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.notepad.tests">
+
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.example.android.notepad"
+ android:label="NotePad sample tests">
+ </instrumentation>
+
+</manifest>
diff --git a/samples/NotePad/tests/src/com/example/android/notepad/NotePadTest.java b/samples/NotePad/tests/src/com/example/android/notepad/NotePadTest.java
new file mode 100644
index 0000000..452c599
--- /dev/null
+++ b/samples/NotePad/tests/src/com/example/android/notepad/NotePadTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.example.android.notepad;
+
+import android.test.ActivityInstrumentationTestCase;
+
+import com.example.android.notepad.NotesList;
+
+/**
+ * Make sure that the main launcher activity opens up properly, which will be
+ * verified by {@link ActivityTestCase#testActivityTestCaseSetUpProperly}.
+ */
+public class NotePadTest extends ActivityInstrumentationTestCase<NotesList> {
+
+ public NotePadTest() {
+ super("com.example.android.notepad", NotesList.class);
+ }
+
+}