Merge "Do not merge. This is a cherry-pick from froyo change I392406824607e2bdae646e3156433d82a9ed6521 Revise NotePad application to use better practices such as - inflating menus from XML and supporting API Level 3 without the need for version qualifiers on resource directories. - to NOT include items in the options menu based on the 'selected' item (that's what a context menu is for). - include all drawables in the app, instead of using system resources." into gingerbread

This commit is contained in:
Scott Main
2010-10-25 11:14:20 -07:00
committed by Android (Google) Code Review
34 changed files with 278 additions and 311 deletions

View File

@@ -20,16 +20,15 @@
own application, the package name must be changed from "com.example.*" own application, the package name must be changed from "com.example.*"
to come from a domain that you own or have control over. --> to come from a domain that you own or have control over. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.notepad" 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"> <application android:icon="@drawable/app_notes"
android:label="@string/app_name" >
<provider android:name="NotePadProvider"
android:authorities="com.example.notepad.provider.NotePad" />
<activity android:name="NotesList"
android:label="@string/title_notes_list">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
@@ -50,16 +49,13 @@
<activity android:name="NoteEditor" <activity android:name="NoteEditor"
android:theme="@android:style/Theme.Light" android:theme="@android:style/Theme.Light"
android:label="@string/title_note" android:configChanges="keyboardHidden|orientation">
android:screenOrientation="sensor"
android:configChanges="keyboardHidden|orientation"
>
<!-- This filter says that we can view or edit the data of <!-- This filter says that we can view or edit the data of
a single note --> a single note -->
<intent-filter android:label="@string/resolve_edit"> <intent-filter android:label="@string/resolve_edit">
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.EDIT" />
<action android:name="com.android.notepad.action.EDIT_NOTE" /> <action android:name="com.android.notes.action.EDIT_NOTE" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> <data android:mimeType="vnd.android.cursor.item/vnd.google.note" />
</intent-filter> </intent-filter>
@@ -77,6 +73,7 @@
<activity android:name="TitleEditor" <activity android:name="TitleEditor"
android:label="@string/title_edit_title" android:label="@string/title_edit_title"
android:theme="@android:style/Theme.Dialog" android:theme="@android:style/Theme.Dialog"
android:icon="@drawable/ic_menu_edit"
android:windowSoftInputMode="stateVisible"> android:windowSoftInputMode="stateVisible">
<!-- This activity implements an alternative action that can be <!-- This activity implements an alternative action that can be
performed on notes: editing their title. It can be used as performed on notes: editing their title. It can be used as
@@ -110,6 +107,6 @@
</application> </application>
<uses-sdk android:targetSdkVersion="4" android:minSdkVersion="3"/> <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="4"/>
</manifest> </manifest>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

BIN
samples/NotePad/res/drawable-hdpi/app_notes.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -13,17 +13,15 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<view xmlns:android="http://schemas.android.com/apk/res/android" <view xmlns:android="http://schemas.android.com/apk/res/android"
class="com.example.android.notepad.NoteEditor$LinedEditText" class="com.example.android.notepad.NoteEditor$LinedEditText"
android:id="@+id/note" android:id="@+id/note"
android:layout_width="match_parent" android:layout_width="fill_parent"
android:layout_height="match_parent" android:layout_height="fill_parent"
android:background="@android:color/transparent" android:background="@android:color/transparent"
android:padding="5dip" android:padding="5dp"
android:scrollbars="vertical" android:scrollbars="vertical"
android:fadingEdge="vertical" android:fadingEdge="vertical"
android:gravity="top" android:gravity="top"
android:textSize="22sp" android:textSize="22sp"
android:capitalize="sentences" android:capitalize="sentences" />
/>

View File

@@ -16,7 +16,7 @@
<TextView xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1" android:id="@android:id/text1"
android:layout_width="match_parent" android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight" android:layout_height="?android:attr/listPreferredItemHeight"
android:textAppearance="?android:attr/textAppearanceLarge" android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_vertical" android:gravity="center_vertical"

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_save"
android:icon="@drawable/ic_menu_save"
android:alphabeticShortcut='s'
android:title="@string/menu_save" />
<group android:id="@+id/menu_group_edit">
<item android:id="@+id/menu_revert"
android:icon="@drawable/ic_menu_revert"
android:title="@string/menu_revert" />
<item android:id="@+id/menu_delete"
android:icon="@drawable/ic_menu_delete"
android:title="@string/menu_delete" />
</group>
<group android:id="@+id/menu_group_insert">
<item android:id="@+id/menu_discard"
android:icon="@drawable/ic_menu_discard"
android:title="@string/menu_discard" />
</group>
</menu>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/context_open"
android:title="@string/menu_open" />
<item android:id="@+id/context_delete"
android:title="@string/menu_delete" />
</menu>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- This is our one standard application action (creating a new note). -->
<item android:id="@+id/menu_add"
android:icon="@drawable/ic_menu_compose"
android:alphabeticShortcut='a'
android:title="@string/menu_add" />
</menu>

View File

@@ -15,25 +15,28 @@
--> -->
<resources> <resources>
<string name="app_name">NotePad</string>
<string name="live_folder_name">Notes</string>
<string name="title_edit_title">Note title:</string>
<string name="title_create">Create note</string>
<string name="title_edit">Edit: \"%1$s\"</string>
<string name="title_notes_list">Notes</string>
<string name="menu_add">Add note</string>
<string name="menu_save">Save</string>
<string name="menu_delete">Delete</string> <string name="menu_delete">Delete</string>
<string name="menu_insert">Add note</string> <string name="menu_open">Open</string>
<string name="menu_revert">Revert</string> <string name="menu_revert">Revert changes</string>
<string name="menu_discard">Discard</string> <string name="menu_discard">Discard</string>
<string name="button_ok">OK</string>
<string name="text_title">Title:</string>
<string name="resolve_edit">Edit note</string> <string name="resolve_edit">Edit note</string>
<string name="resolve_title">Edit title</string> <string name="resolve_title">Edit title</string>
<string name="title_create">Create note</string> <string name="error_title">Error</string>
<string name="title_edit">Edit note</string> <string name="error_message">Error loading note</string>
<string name="title_notes_list">Note pad</string> <string name="nothing_to_save">There is nothing to save</string>
<string name="title_note">Note</string>
<string name="title_edit_title">Note title:</string>
<string name="app_name">Note Pad</string>
<string name="live_folder_name">Notes</string>
<string name="button_ok">OK</string>
<string name="error_title">Error</string>
<string name="error_message">Error loading note</string>
</resources> </resources>

View File

@@ -16,13 +16,12 @@
package com.example.android.notepad; package com.example.android.notepad;
import com.example.android.notepad.NotePad.Notes;
import android.app.Activity; import android.app.Activity;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
@@ -32,8 +31,12 @@ import android.os.Bundle;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.EditText; import android.widget.EditText;
import android.widget.Toast;
import com.example.android.notepad.NotePad.NoteColumns;
/** /**
* A generic activity for editing a note in a database. This can be used * A generic activity for editing a note in a database. This can be used
@@ -41,32 +44,29 @@ import android.widget.EditText;
* {@link Intent#ACTION_EDIT}, or create a new note {@link Intent#ACTION_INSERT}. * {@link Intent#ACTION_EDIT}, or create a new note {@link Intent#ACTION_INSERT}.
*/ */
public class NoteEditor extends Activity { public class NoteEditor extends Activity {
private static final String TAG = "Notes"; private static final String TAG = "NoteEditor";
/** /**
* Standard projection for the interesting columns of a normal note. * Standard projection for the interesting columns of a normal note.
*/ */
private static final String[] PROJECTION = new String[] { private static final String[] PROJECTION = new String[] {
Notes._ID, // 0 NoteColumns._ID, // 0
Notes.NOTE, // 1 NoteColumns.NOTE, // 1
NoteColumns.TITLE, // 2
}; };
/** The index of the note column */ /** The index of the note column */
private static final int COLUMN_INDEX_NOTE = 1; private static final int COLUMN_INDEX_NOTE = 1;
/** The index of the title column */
private static final int COLUMN_INDEX_TITLE = 2;
// This is our state data that is stored when freezing. // This is our state data that is stored when freezing.
private static final String ORIGINAL_CONTENT = "origContent"; 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. // The different distinct states the activity can be run in.
private static final int STATE_EDIT = 0; private static final int STATE_EDIT = 0;
private static final int STATE_INSERT = 1; private static final int STATE_INSERT = 1;
private int mState; private int mState;
private boolean mNoteOnly = false;
private Uri mUri; private Uri mUri;
private Cursor mCursor; private Cursor mCursor;
private EditText mText; private EditText mText;
@@ -112,7 +112,6 @@ public class NoteEditor extends Activity {
final Intent intent = getIntent(); final Intent intent = getIntent();
// Do some setup based on the action being performed. // Do some setup based on the action being performed.
final String action = intent.getAction(); final String action = intent.getAction();
if (Intent.ACTION_EDIT.equals(action)) { if (Intent.ACTION_EDIT.equals(action)) {
// Requested to edit: set that state, and the data being edited. // Requested to edit: set that state, and the data being edited.
@@ -163,16 +162,21 @@ public class NoteEditor extends Activity {
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
// If we didn't have any trouble retrieving the data, it is now // If we didn't have any trouble retrieving the data, it is now
// time to get at the stuff. // time to get at the stuff.
if (mCursor != null) { if (mCursor != null) {
// Requery in case something changed while paused (such as the title)
mCursor.requery();
// Make sure we are at the one and only row in the cursor. // Make sure we are at the one and only row in the cursor.
mCursor.moveToFirst(); mCursor.moveToFirst();
// Modify our overall title depending on the mode we are running in. // Modify our overall title depending on the mode we are running in.
if (mState == STATE_EDIT) { if (mState == STATE_EDIT) {
setTitle(getText(R.string.title_edit)); // Set the title of the Activity to include the note title
String title = mCursor.getString(COLUMN_INDEX_TITLE);
Resources res = getResources();
String text = String.format(res.getString(R.string.title_edit), title);
setTitle(text);
} else if (mState == STATE_INSERT) { } else if (mState == STATE_INSERT) {
setTitle(getText(R.string.title_create)); setTitle(getText(R.string.title_create));
} }
@@ -206,109 +210,129 @@ public class NoteEditor extends Activity {
@Override @Override
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
// The user is going somewhere, so make sure changes are saved
// The user is going somewhere else, so make sure their current String text = mText.getText().toString();
// changes are safely saved away in the provider. We don't need int length = text.length();
// 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 // If this activity is finished, and there is no text, then we
// do something a little special: simply delete the note entry. // simply delete the note entry.
// Note that we do this both for editing and inserting... it // Note that we do this both for editing and inserting... it
// would be reasonable to only do it when inserting. // would be reasonable to only do it when inserting.
if (isFinishing() && (length == 0) && !mNoteOnly) { if (isFinishing() && (length == 0) && mCursor != null) {
setResult(RESULT_CANCELED); setResult(RESULT_CANCELED);
deleteNote(); deleteNote();
} else {
// Get out updates into the provider. saveNote();
} 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 @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu); // Inflate menu from XML resource
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.editor_options_menu, menu);
// Build the menus that are shown when editing. // Append to the
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 // 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 // as well. This does a query on the system for any activities that
// implement the ALTERNATIVE_ACTION for our data, adding a menu item // implement the ALTERNATIVE_ACTION for our data, adding a menu item
// for each one that is found. // for each one that is found.
if (!mNoteOnly) { Intent intent = new Intent(null, getIntent().getData());
Intent intent = new Intent(null, getIntent().getData()); intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
intent.addCategory(Intent.CATEGORY_ALTERNATIVE); menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, new ComponentName(this, NoteEditor.class), null, intent, 0, null);
new ComponentName(this, NoteEditor.class), null, intent, 0, null);
}
return true; return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (mState == STATE_EDIT) {
menu.setGroupVisible(R.id.menu_group_edit, true);
menu.setGroupVisible(R.id.menu_group_insert, false);
// Check if note has changed and enable/disable the revert option
String savedNote = mCursor.getString(COLUMN_INDEX_NOTE);
String currentNote = mText.getText().toString();
if (savedNote.equals(currentNote)) {
menu.findItem(R.id.menu_revert).setEnabled(false);
} else {
menu.findItem(R.id.menu_revert).setEnabled(true);
}
} else {
menu.setGroupVisible(R.id.menu_group_edit, false);
menu.setGroupVisible(R.id.menu_group_insert, true);
}
return super.onPrepareOptionsMenu(menu);
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
// Handle all of the possible menu actions. // Handle all of the possible menu actions.
switch (item.getItemId()) { switch (item.getItemId()) {
case DELETE_ID: case R.id.menu_save:
saveNote();
finish();
break;
case R.id.menu_delete:
deleteNote(); deleteNote();
finish(); finish();
break; break;
case DISCARD_ID: case R.id.menu_revert:
cancelNote(); case R.id.menu_discard:
break;
case REVERT_ID:
cancelNote(); cancelNote();
break; break;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
}
private final void saveNote() {
// 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) {
// Get out updates into the provider.
ContentValues values = new ContentValues();
// Bump the modification time to now.
values.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
String text = mText.getText().toString();
int length = text.length();
// If we are creating a new note, then we want to also create
// an initial title for it.
if (mState == STATE_INSERT) {
if (length == 0) {
Toast.makeText(this, R.string.nothing_to_save, Toast.LENGTH_SHORT).show();
return;
}
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(NoteColumns.TITLE, title);
}
// Write our text back into the provider.
values.put(NoteColumns.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.
try {
getContentResolver().update(mUri, values, null, null);
} catch (NullPointerException e) {
Log.e(TAG, e.getMessage());
}
}
} }
/** /**
@@ -322,7 +346,7 @@ public class NoteEditor extends Activity {
mCursor.close(); mCursor.close();
mCursor = null; mCursor = null;
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(Notes.NOTE, mOriginalContent); values.put(NoteColumns.NOTE, mOriginalContent);
getContentResolver().update(mUri, values, null, null); getContentResolver().update(mUri, values, null, null);
} else if (mState == STATE_INSERT) { } else if (mState == STATE_INSERT) {
// We inserted an empty note, make sure to delete it // We inserted an empty note, make sure to delete it

View File

@@ -23,7 +23,7 @@ import android.provider.BaseColumns;
* Convenience definitions for NotePadProvider * Convenience definitions for NotePadProvider
*/ */
public final class NotePad { public final class NotePad {
public static final String AUTHORITY = "com.google.provider.NotePad"; public static final String AUTHORITY = "com.example.notepad.provider.NotePad";
// This class cannot be instantiated // This class cannot be instantiated
private NotePad() {} private NotePad() {}
@@ -31,9 +31,9 @@ public final class NotePad {
/** /**
* Notes table * Notes table
*/ */
public static final class Notes implements BaseColumns { public static final class NoteColumns implements BaseColumns {
// This class cannot be instantiated // This class cannot be instantiated
private Notes() {} private NoteColumns() {}
/** /**
* The content:// style URL for this table * The content:// style URL for this table

View File

@@ -16,7 +16,7 @@
package com.example.android.notepad; package com.example.android.notepad;
import com.example.android.notepad.NotePad.Notes; import com.example.android.notepad.NotePad.NoteColumns;
import android.content.ContentProvider; import android.content.ContentProvider;
import android.content.ContentUris; import android.content.ContentUris;
@@ -44,7 +44,7 @@ public class NotePadProvider extends ContentProvider {
private static final String TAG = "NotePadProvider"; private static final String TAG = "NotePadProvider";
private static final String DATABASE_NAME = "note_pad.db"; private static final String DATABASE_NAME = "notepad.db";
private static final int DATABASE_VERSION = 2; private static final int DATABASE_VERSION = 2;
private static final String NOTES_TABLE_NAME = "notes"; private static final String NOTES_TABLE_NAME = "notes";
@@ -69,11 +69,11 @@ public class NotePadProvider extends ContentProvider {
@Override @Override
public void onCreate(SQLiteDatabase db) { public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + NOTES_TABLE_NAME + " (" db.execSQL("CREATE TABLE " + NOTES_TABLE_NAME + " ("
+ Notes._ID + " INTEGER PRIMARY KEY," + NoteColumns._ID + " INTEGER PRIMARY KEY,"
+ Notes.TITLE + " TEXT," + NoteColumns.TITLE + " TEXT,"
+ Notes.NOTE + " TEXT," + NoteColumns.NOTE + " TEXT,"
+ Notes.CREATED_DATE + " INTEGER," + NoteColumns.CREATED_DATE + " INTEGER,"
+ Notes.MODIFIED_DATE + " INTEGER" + NoteColumns.MODIFIED_DATE + " INTEGER"
+ ");"); + ");");
} }
@@ -107,7 +107,7 @@ public class NotePadProvider extends ContentProvider {
case NOTE_ID: case NOTE_ID:
qb.setProjectionMap(sNotesProjectionMap); qb.setProjectionMap(sNotesProjectionMap);
qb.appendWhere(Notes._ID + "=" + uri.getPathSegments().get(1)); qb.appendWhere(NoteColumns._ID + "=" + uri.getPathSegments().get(1));
break; break;
case LIVE_FOLDER_NOTES: case LIVE_FOLDER_NOTES:
@@ -121,7 +121,7 @@ public class NotePadProvider extends ContentProvider {
// If no sort order is specified use the default // If no sort order is specified use the default
String orderBy; String orderBy;
if (TextUtils.isEmpty(sortOrder)) { if (TextUtils.isEmpty(sortOrder)) {
orderBy = NotePad.Notes.DEFAULT_SORT_ORDER; orderBy = NoteColumns.DEFAULT_SORT_ORDER;
} else { } else {
orderBy = sortOrder; orderBy = sortOrder;
} }
@@ -140,10 +140,10 @@ public class NotePadProvider extends ContentProvider {
switch (sUriMatcher.match(uri)) { switch (sUriMatcher.match(uri)) {
case NOTES: case NOTES:
case LIVE_FOLDER_NOTES: case LIVE_FOLDER_NOTES:
return Notes.CONTENT_TYPE; return NoteColumns.CONTENT_TYPE;
case NOTE_ID: case NOTE_ID:
return Notes.CONTENT_ITEM_TYPE; return NoteColumns.CONTENT_ITEM_TYPE;
default: default:
throw new IllegalArgumentException("Unknown URI " + uri); throw new IllegalArgumentException("Unknown URI " + uri);
@@ -167,27 +167,27 @@ public class NotePadProvider extends ContentProvider {
Long now = Long.valueOf(System.currentTimeMillis()); Long now = Long.valueOf(System.currentTimeMillis());
// Make sure that the fields are all set // Make sure that the fields are all set
if (values.containsKey(NotePad.Notes.CREATED_DATE) == false) { if (values.containsKey(NoteColumns.CREATED_DATE) == false) {
values.put(NotePad.Notes.CREATED_DATE, now); values.put(NoteColumns.CREATED_DATE, now);
} }
if (values.containsKey(NotePad.Notes.MODIFIED_DATE) == false) { if (values.containsKey(NoteColumns.MODIFIED_DATE) == false) {
values.put(NotePad.Notes.MODIFIED_DATE, now); values.put(NoteColumns.MODIFIED_DATE, now);
} }
if (values.containsKey(NotePad.Notes.TITLE) == false) { if (values.containsKey(NoteColumns.TITLE) == false) {
Resources r = Resources.getSystem(); Resources r = Resources.getSystem();
values.put(NotePad.Notes.TITLE, r.getString(android.R.string.untitled)); values.put(NoteColumns.TITLE, r.getString(android.R.string.untitled));
} }
if (values.containsKey(NotePad.Notes.NOTE) == false) { if (values.containsKey(NoteColumns.NOTE) == false) {
values.put(NotePad.Notes.NOTE, ""); values.put(NoteColumns.NOTE, "");
} }
SQLiteDatabase db = mOpenHelper.getWritableDatabase(); SQLiteDatabase db = mOpenHelper.getWritableDatabase();
long rowId = db.insert(NOTES_TABLE_NAME, Notes.NOTE, values); long rowId = db.insert(NOTES_TABLE_NAME, NoteColumns.NOTE, values);
if (rowId > 0) { if (rowId > 0) {
Uri noteUri = ContentUris.withAppendedId(NotePad.Notes.CONTENT_URI, rowId); Uri noteUri = ContentUris.withAppendedId(NoteColumns.CONTENT_URI, rowId);
getContext().getContentResolver().notifyChange(noteUri, null); getContext().getContentResolver().notifyChange(noteUri, null);
return noteUri; return noteUri;
} }
@@ -206,7 +206,7 @@ public class NotePadProvider extends ContentProvider {
case NOTE_ID: case NOTE_ID:
String noteId = uri.getPathSegments().get(1); String noteId = uri.getPathSegments().get(1);
count = db.delete(NOTES_TABLE_NAME, Notes._ID + "=" + noteId count = db.delete(NOTES_TABLE_NAME, NoteColumns._ID + "=" + noteId
+ (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs); + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
break; break;
@@ -229,7 +229,7 @@ public class NotePadProvider extends ContentProvider {
case NOTE_ID: case NOTE_ID:
String noteId = uri.getPathSegments().get(1); String noteId = uri.getPathSegments().get(1);
count = db.update(NOTES_TABLE_NAME, values, Notes._ID + "=" + noteId count = db.update(NOTES_TABLE_NAME, values, NoteColumns._ID + "=" + noteId
+ (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs); + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
break; break;
@@ -248,17 +248,17 @@ public class NotePadProvider extends ContentProvider {
sUriMatcher.addURI(NotePad.AUTHORITY, "live_folders/notes", LIVE_FOLDER_NOTES); sUriMatcher.addURI(NotePad.AUTHORITY, "live_folders/notes", LIVE_FOLDER_NOTES);
sNotesProjectionMap = new HashMap<String, String>(); sNotesProjectionMap = new HashMap<String, String>();
sNotesProjectionMap.put(Notes._ID, Notes._ID); sNotesProjectionMap.put(NoteColumns._ID, NoteColumns._ID);
sNotesProjectionMap.put(Notes.TITLE, Notes.TITLE); sNotesProjectionMap.put(NoteColumns.TITLE, NoteColumns.TITLE);
sNotesProjectionMap.put(Notes.NOTE, Notes.NOTE); sNotesProjectionMap.put(NoteColumns.NOTE, NoteColumns.NOTE);
sNotesProjectionMap.put(Notes.CREATED_DATE, Notes.CREATED_DATE); sNotesProjectionMap.put(NoteColumns.CREATED_DATE, NoteColumns.CREATED_DATE);
sNotesProjectionMap.put(Notes.MODIFIED_DATE, Notes.MODIFIED_DATE); sNotesProjectionMap.put(NoteColumns.MODIFIED_DATE, NoteColumns.MODIFIED_DATE);
// Support for Live Folders. // Support for Live Folders.
sLiveFolderProjectionMap = new HashMap<String, String>(); sLiveFolderProjectionMap = new HashMap<String, String>();
sLiveFolderProjectionMap.put(LiveFolders._ID, Notes._ID + " AS " + sLiveFolderProjectionMap.put(LiveFolders._ID, NoteColumns._ID + " AS " +
LiveFolders._ID); LiveFolders._ID);
sLiveFolderProjectionMap.put(LiveFolders.NAME, Notes.TITLE + " AS " + sLiveFolderProjectionMap.put(LiveFolders.NAME, NoteColumns.TITLE + " AS " +
LiveFolders.NAME); LiveFolders.NAME);
// Add more columns here for more robust Live Folders. // Add more columns here for more robust Live Folders.
} }

View File

@@ -16,8 +16,6 @@
package com.example.android.notepad; package com.example.android.notepad;
import com.example.android.notepad.NotePad.Notes;
import android.app.ListActivity; import android.app.ListActivity;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.ContentUris; import android.content.ContentUris;
@@ -28,6 +26,7 @@ import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ContextMenu.ContextMenuInfo; import android.view.ContextMenu.ContextMenuInfo;
@@ -35,24 +34,22 @@ import android.widget.AdapterView;
import android.widget.ListView; import android.widget.ListView;
import android.widget.SimpleCursorAdapter; import android.widget.SimpleCursorAdapter;
import com.example.android.notepad.NotePad.NoteColumns;
/** /**
* Displays a list of notes. Will display notes from the {@link Uri} * 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 * provided in the intent if there is one, otherwise defaults to displaying the
* contents of the {@link NotePadProvider} * contents of the {@link NoteProvider}
*/ */
public class NotesList extends ListActivity { public class NotesList extends ListActivity {
private static final String TAG = "NotesList"; 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 * The columns we are interested in from the database
*/ */
private static final String[] PROJECTION = new String[] { private static final String[] PROJECTION = new String[] {
Notes._ID, // 0 NoteColumns._ID, // 0
Notes.TITLE, // 1 NoteColumns.TITLE, // 1
}; };
/** The index of the title column */ /** The index of the title column */
@@ -68,7 +65,7 @@ public class NotesList extends ListActivity {
// as a MAIN activity), then use our default content provider. // as a MAIN activity), then use our default content provider.
Intent intent = getIntent(); Intent intent = getIntent();
if (intent.getData() == null) { if (intent.getData() == null) {
intent.setData(Notes.CONTENT_URI); intent.setData(NoteColumns.CONTENT_URI);
} }
// Inform the list we provide context menus for items // Inform the list we provide context menus for items
@@ -77,23 +74,19 @@ public class NotesList extends ListActivity {
// Perform a managed query. The Activity will handle closing and requerying the cursor // Perform a managed query. The Activity will handle closing and requerying the cursor
// when needed. // when needed.
Cursor cursor = managedQuery(getIntent().getData(), PROJECTION, null, null, Cursor cursor = managedQuery(getIntent().getData(), PROJECTION, null, null,
Notes.DEFAULT_SORT_ORDER); NoteColumns.DEFAULT_SORT_ORDER);
// Used to map notes entries from the database to views // Used to map notes entries from the database to views
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.noteslist_item, cursor, SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.noteslist_item, cursor,
new String[] { Notes.TITLE }, new int[] { android.R.id.text1 }); new String[] { NoteColumns.TITLE }, new int[] { android.R.id.text1 });
setListAdapter(adapter); setListAdapter(adapter);
} }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu); // Inflate menu from XML resource
MenuInflater inflater = getMenuInflater();
// This is our one standard application action -- inserting a inflater.inflate(R.menu.list_options_menu, menu);
// 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 // Generate any additional actions that can be performed on the
// overall list. In a normal install, there are no additional // overall list. In a normal install, there are no additional
@@ -104,54 +97,19 @@ public class NotesList extends ListActivity {
menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
new ComponentName(this, NotesList.class), null, intent, 0, null); new ComponentName(this, NotesList.class), null, intent, 0, null);
return true; return super.onCreateOptionsMenu(menu);
}
@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 @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case MENU_ITEM_INSERT: case R.id.menu_add:
// Launch activity to insert a new item // Launch activity to insert a new item
startActivity(new Intent(Intent.ACTION_INSERT, getIntent().getData())); startActivity(new Intent(Intent.ACTION_INSERT, getIntent().getData()));
return true; return true;
default:
return super.onOptionsItemSelected(item);
} }
return super.onOptionsItemSelected(item);
} }
@Override @Override
@@ -170,11 +128,23 @@ public class NotesList extends ListActivity {
return; return;
} }
// Setup the menu header // Inflate menu from XML resource
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.list_context_menu, menu);
// Set the context menu header
menu.setHeaderTitle(cursor.getString(COLUMN_INDEX_TITLE)); menu.setHeaderTitle(cursor.getString(COLUMN_INDEX_TITLE));
// Add a menu item to delete the note // Append to the
menu.add(0, MENU_ITEM_DELETE, 0, R.string.menu_delete); // 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.
Intent intent = new Intent(null, Uri.withAppendedPath(getIntent().getData(),
Integer.toString((int) info.id) ));
intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
new ComponentName(this, NotesList.class), null, intent, 0, null);
} }
@Override @Override
@@ -187,29 +157,34 @@ public class NotesList extends ListActivity {
return false; return false;
} }
Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id);
switch (item.getItemId()) { switch (item.getItemId()) {
case MENU_ITEM_DELETE: { case R.id.context_open:
// Delete the note that the context menu is for // Launch activity to view/edit the currently selected item
Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id); startActivity(new Intent(Intent.ACTION_EDIT, noteUri));
getContentResolver().delete(noteUri, null, null); return true;
return true; case R.id.context_delete:
} // Delete the note that the context menu is for
getContentResolver().delete(noteUri, null, null);
return true;
default:
return super.onContextItemSelected(item);
} }
return false;
} }
@Override @Override
protected void onListItemClick(ListView l, View v, int position, long id) { protected void onListItemClick(ListView l, View v, int position, long id) {
Uri uri = ContentUris.withAppendedId(getIntent().getData(), id); Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), id);
String action = getIntent().getAction(); String action = getIntent().getAction();
if (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action)) { 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 caller is waiting for us to return a note selected by
// the user. The have clicked on one, so return it now. // the user. The have clicked on one, so return it now.
setResult(RESULT_OK, new Intent().setData(uri)); setResult(RESULT_OK, new Intent().setData(noteUri));
} else { } else {
// Launch activity to view/edit the currently selected item // Launch activity to view/edit the currently selected item
startActivity(new Intent(Intent.ACTION_EDIT, uri)); startActivity(new Intent(Intent.ACTION_EDIT, noteUri));
} }
} }
} }

View File

@@ -16,8 +16,6 @@
package com.example.android.notepad; package com.example.android.notepad;
import com.example.android.notepad.NotePad.Notes;
import android.app.Activity; import android.app.Activity;
import android.content.ContentValues; import android.content.ContentValues;
import android.database.Cursor; import android.database.Cursor;
@@ -27,6 +25,8 @@ import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import com.example.android.notepad.NotePad.NoteColumns;
/** /**
* An activity that will edit the title of a note. Displays a floating * An activity that will edit the title of a note. Displays a floating
* window with a text field. * window with a text field.
@@ -42,8 +42,8 @@ public class TitleEditor extends Activity implements View.OnClickListener {
* An array of the columns we are interested in. * An array of the columns we are interested in.
*/ */
private static final String[] PROJECTION = new String[] { private static final String[] PROJECTION = new String[] {
NotePad.Notes._ID, // 0 NoteColumns._ID, // 0
NotePad.Notes.TITLE, // 1 NoteColumns.TITLE, // 1
}; };
/** Index of the title column */ /** Index of the title column */
private static final int COLUMN_INDEX_TITLE = 1; private static final int COLUMN_INDEX_TITLE = 1;
@@ -102,7 +102,7 @@ public class TitleEditor extends Activity implements View.OnClickListener {
if (mCursor != null) { if (mCursor != null) {
// Write the title back to the note // Write the title back to the note
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(Notes.TITLE, mText.getText().toString()); values.put(NoteColumns.TITLE, mText.getText().toString());
getContentResolver().update(mUri, values, null, null); getContentResolver().update(mUri, values, null, null);
} }
} }

View File

@@ -1,65 +0,0 @@
/*
* 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";
}
}