summaryrefslogtreecommitdiffstats
path: root/docs/html/resources/tutorials/notepad/notepad-ex2.jd
diff options
context:
space:
mode:
Diffstat (limited to 'docs/html/resources/tutorials/notepad/notepad-ex2.jd')
-rw-r--r--docs/html/resources/tutorials/notepad/notepad-ex2.jd647
1 files changed, 647 insertions, 0 deletions
diff --git a/docs/html/resources/tutorials/notepad/notepad-ex2.jd b/docs/html/resources/tutorials/notepad/notepad-ex2.jd
new file mode 100644
index 0000000..bab9471
--- /dev/null
+++ b/docs/html/resources/tutorials/notepad/notepad-ex2.jd
@@ -0,0 +1,647 @@
+Rpage.title=Notepad Exercise 2
+parent.title=Notepad Tutorial
+parent.link=index.html
+@jd:body
+
+
+<p><em>In this exercise, you will add a second Activity to your notepad application, to let the user
+create and edit notes. You will also allow the user to delete existing notes through a context menu.
+The new Activity assumes responsibility for creating new notes by
+collecting user input and packing it into a return Bundle provided by the intent. This exercise
+demonstrates:</em></p>
+<ul>
+<li><em>Constructing a new Activity and adding it to the Android manifest</em></li>
+<li><em>Invoking another Activity asynchronously using <code>startActivityForResult()</code></em></li>
+<li><em>Passing data between Activity in Bundle objects</em></li>
+<li><em>How to use a more advanced screen layout</em></li>
+<li><em>How to create a context menu</em></li>
+</ul>
+
+<div style="float:right;white-space:nowrap">
+ [<a href="notepad-ex1.html">Exercise 1</a>]
+ <span style="color:#BBB;">
+ [<a href="notepad-ex2.html" style="color:#DDD;">Exercise 2</a>]
+ </span>
+ [<a href="notepad-ex3.html">Exercise 3</a>]
+ [<a href="notepad-extra-credit.html">Extra Credit</a>]
+</div>
+
+<h2>Step 1</h2>
+
+<p>Create a new Android project using the sources from <code>Notepadv2</code> under the
+<code>NotepadCodeLab</code> folder, just like you did for the first exercise. If you see an error about
+<code>AndroidManifest.xml</code>, or some problems related to an
+<code>android.zip</code> file, right click on the project and select <strong>Android
+Tools</strong> &gt; <strong>Fix Project Properties</strong>.</p>
+
+<p>Open the <code>Notepadv2</code> project and take a look around:</p>
+<ul>
+ <li>
+ Open and look at the <code>strings.xml</code> file under
+ <code>res/values</code> &mdash; there are several new strings which we will use
+ for our new functionality
+ </li>
+ <li>
+ Also, open and take a look at the top of the <code>Notepadv2</code> class,
+ you will notice several new constants have been defined along with a new <code>mNotesCursor</code>
+ field used to hold the cursor we are using.
+ </li>
+ <li>
+ Note also that the <code>fillData()</code> method has a few more comments and now uses
+ the new field to store the notes Cursor. The <code>onCreate()</code> method is
+ unchanged from the first exercise. Also notice that the member field used to store the
+ notes Cursor is now called <code>mNotesCursor</code>. The <code>m</code> denotes a member
+ field and is part of the Android coding style standards.
+ </li>
+ <li>
+ There are also a couple of new overridden methods
+ (<code>onCreateContextMenu()</code>, <code>onContextItemSelected()</code>,
+ <code>onListItemClick()</code> and <code>onActivityResult()</code>)
+ which we will be filling in below.
+ </li>
+</ul>
+
+
+<h2>Step 2</h2>
+
+<div class="sidebox">
+<p>Context menus should always be used when performing actions upon specific elements in the UI.
+When you register a View to a context menu, the context menu is revealed by performing a "long-click"
+on the UI component (press and hold the touchscreen or highlight and hold down the selection key for about two seconds).</p>
+</div>
+
+<p>First, let's create the context menu that will allow users to delete individual notes.
+Open the Notepadv2 class.</p>
+
+<ol>
+ <li>In order for each list item in the ListView to register for the context menu, we call
+ <code>registerForContextMenu()</code> and pass it our ListView. So, at the very end of
+ the <code>onCreate()</code> method add this line:
+ <pre>registerForContextMenu(getListView());</pre>
+ <p>Because our Activity extends the ListActivity class, <code>getListView()</code> will return us
+ the local ListView object for the Activity. Now, each list item in this ListView will activate the
+ context menu.
+ <li>
+ Now fill in the <code>onCreateContextMenu()</code> method. This callback is similar to the other
+ menu callback used for the options menu. Here, we add just one line, which will add a menu item
+ to delete a note. Call <code>menu.add()</code> like so:
+ <pre>
+public boolean onCreateContextMenu(Menu menu, View v
+ ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ menu.add(0, DELETE_ID, 0, R.string.menu_delete);
+}</pre>
+ <p>The <code>onCreateContextMenu()</code> callback some passes other information in addition to the Menu object,
+ such as the View that has been triggered for the menu and
+ an extra object that may contain additional information about the object selected. However, we don't care about
+ these here, because we only have one kind of object in the Activity that uses context menus. In the next
+ step, we'll handle the menu item selection.</p>
+ </li>
+</ol>
+
+<h2>Step 3</h2>
+ <p>Now that the we've registered our ListView for a context menu and defined our context menu item, we need
+ to handle the callback when it is selected. For this, we need to identify the list ID of the
+ selected item, then delete it. So fill in the
+ <code>onContextItemSelected()</code> method like this:</p>
+<pre>
+public boolean onContextItemSelected(MenuItem item) {
+ switch(item.getItemId()) {
+ case DELETE_ID:
+ AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
+ mDbHelper.deleteNote(info.id);
+ fillData();
+ return true;
+ }
+ return super.onContextItemSelected(item);
+}</pre>
+<p>Here, we retrieve the {@link android.widget.AdapterView.AdapterContextMenuInfo AdapterContextMenuInfo}
+with {@link android.view.MenuItem#getMenuInfo()}. The <var>id</var> field of this object tells us
+the position of the item in the ListView. We then pass this to the <code>deleteNote()</code>
+method of our NotesDbAdapter and the note is deleted. That's it for the context menu &mdash; notes
+can now be deleted.</p>
+
+<h2 style="clear:right;">Step 4</h2>
+<div class="sidebox" style="border:2px solid #FFFFDD;float:right;
+ background-color:#FFFFEE;margin-right:0px;
+ margin-bottom:.5em;margin-top:1em;padding:0em;width:240px;">
+ <h2 style="border:0;font-size:12px;padding:.5em .5em .5em 1em;margin:0;
+ background-color:#FFFFDD;">Starting Other Activities</h2>
+ <p style="padding-left:.5em;font-size:12px;margin:0;
+ padding:.0em .5em .5em 1em;">In this example our Intent uses a class name specifically.
+ As well as
+ <a href="{@docRoot}resources/faq/commontasks.html#intentexamples">starting intents</a> in
+ classes we already know about, be they in our own application or another
+ application, we can also create Intents without knowing exactly which
+ application will handle it.</p>
+ <p style="padding-left:.5em;font-size:12px;margin:0;
+ padding:.0em .5em .5em 1em;">For example, we might want to open a page in a
+ browser, and for this we still use
+ an Intent. But instead of specifying a class to handle it, we use
+ a predefined Intent constant, and a content URI that describes what we
+ want to do. See {@link android.content.Intent
+ android.content.Intent} for more information.</p>
+</div>
+
+ <p>Fill in the body of the <code>createNote()</code> method:
+ <p>Create a new <code>Intent</code> to create a note
+ (<code>ACTIVITY_CREATE</code>) using the <code>NoteEdit</code> class.
+ Then fire the Intent using the <code>startActivityForResult()</code> method
+ call:</p>
+ <pre style="overflow:auto">
+Intent i = new Intent(this, NoteEdit.class);
+startActivityForResult(i, ACTIVITY_CREATE);</pre>
+ <p>This form of the Intent call targets a specific class in our Activity, in this case
+ <code>NoteEdit</code>. Since the Intent class will need to communicate with the Android
+ operating system to route requests, we also have to provide a Context (<code>this</code>).</p>
+ <p>The <code>startActivityForResult()</code> method fires the Intent in a way that causes a method
+ in our Activity to be called when the new Activity is completed. The method in our Activity
+ that receives the callback is called
+ <code>onActivityResult()</code> and we will implement it in a later step. The other way
+ to call an Activity is using <code>startActivity()</code> but this is a "fire-and-forget" way
+ of calling it &mdash; in this manner, our Activity is not informed when the Activity is completed, and there is
+ no way to return result information from the called Activity with <code>startActivity()</code>.
+ <p>Don't worry about the fact that <code>NoteEdit</code> doesn't exist yet,
+ we will fix that soon. </p>
+ </li>
+
+
+<h2>Step 5</h2>
+
+ <p>Fill in the body of the <code>onListItemClick()</code> override.</p>
+ <p><code>onListItemClick()</code> is a callback method that we'll override. It is called when
+ the user selects an item from the list. It is passed four parameters: the
+ <code>ListView</code> object it was invoked from, the <code>View</code>
+ inside the <code>ListView</code> that was clicked on, the
+ <code>position</code> in the list that was clicked, and the
+ <code>mRowId</code> of the item that was clicked. In this instance we can
+ ignore the first two parameters (we only have one <code>ListView</code> it
+ could be), and we ignore the <code>mRowId</code> as well. All we are
+ interested in is the <code>position</code> that the user selected. We use
+ this to get the data from the correct row, and bundle it up to send to
+ the <code>NoteEdit</code> Activity.</p>
+ <p>In our implementation of the callback, the method creates an
+ <code>Intent</code> to edit the note using
+ the <code>NoteEdit</code> class. It then adds data into the extras Bundle of
+ the Intent, which will be passed to the called Activity. We use it
+ to pass in the title and body text, and the <code>mRowId</code> for the note we are
+ editing. Finally, it will fire the Intent using the
+ <code>startActivityForResult()</code> method call. Here's the code that
+ belongs in <code>onListItemClick()</code>:</p>
+ <pre>
+super.onListItemClick(l, v, position, id);
+Cursor c = mNotesCursor;
+c.moveToPosition(position);
+Intent i = new Intent(this, NoteEdit.class);
+i.putExtra(NotesDbAdapter.KEY_ROWID, id);
+i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(
+ c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
+i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
+ c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
+startActivityForResult(i, ACTIVITY_EDIT);</pre>
+ <ul>
+ <li>
+ <code>putExtra()</code> is the method to add items into the extras Bundle
+ to pass in to intent invocations. Here, we are
+ using the Bundle to pass in the title, body and mRowId of the note we want to edit.
+ </li>
+ <li>
+ The details of the note are pulled out from our query Cursor, which we move to the
+ proper position for the element that was selected in the list, with
+ the <code>moveToPosition()</code> method.</li>
+ <li>With the extras added to the Intent, we invoke the Intent on the
+ <code>NoteEdit</code> class by passing <code>startActivityForResult()</code>
+ the Intent and the request code. (The request code will be
+ returned to <code>onActivityResult</code> as the <code>requestCode</code> parameter.)</li>
+ </ul>
+ <p class="note"><b>Note:</b> We assign the mNotesCursor field to a local variable at the
+ start of the method. This is done as an optimization of the Android code. Accessing a local
+ variable is much more efficient than accessing a field in the Dalvik VM, so by doing this
+ we make only one access to the field, and five accesses to the local variable, making the
+ routine much more efficient. It is recommended that you use this optimization when possible.</p>
+
+
+<h2>Step 6</h2>
+
+<p>The above <code>createNote()</code> and <code>onListItemClick()</code>
+ methods use an asynchronous Intent invocation. We need a handler for the callback, so here we fill
+ in the body of the <code>onActivityResult()</code>. </p>
+<p><code>onActivityResult()</code> is the overridden method
+ which will be called when an Activity returns with a result. (Remember, an Activity
+ will only return a result if launched with <code>startActivityForResult</code>.) The parameters provided
+ to the callback are: </p>
+ <ul>
+ <li><code>requestCode</code> &mdash; the original request code
+ specified in the Intent invocation (either <code>ACTIVITY_CREATE</code> or
+ <code>ACTIVITY_EDIT</code> for us).
+ </li>
+ <li><code>resultCode</code> &mdash; the result (or error code) of the call, this
+ should be zero if everything was OK, but may have a non-zero code indicating
+ that something failed. There are standard result codes available, and you
+ can also create your own constants to indicate specific problems.
+ </li>
+ <li><code>intent</code> &mdash; this is an Intent created by the Activity returning
+ results. It can be used to return data in the Intent "extras."
+ </li>
+ </ul>
+ <p>The combination of <code>startActivityForResult()</code> and
+ <code>onActivityResult()</code> can be thought of as an asynchronous RPC
+ (remote procedure call) and forms the recommended way for an Activity to invoke
+ another and share services.</p>
+ <p>Here's the code that belongs in your <code>onActivityResult()</code>:</p>
+ <pre>
+super.onActivityResult(requestCode, resultCode, intent);
+Bundle extras = intent.getExtras();
+
+switch(requestCode) {
+case ACTIVITY_CREATE:
+ String title = extras.getString(NotesDbAdapter.KEY_TITLE);
+ String body = extras.getString(NotesDbAdapter.KEY_BODY);
+ mDbHelper.createNote(title, body);
+ fillData();
+ break;
+case ACTIVITY_EDIT:
+ Long mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
+ if (mRowId != null) {
+ String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE);
+ String editBody = extras.getString(NotesDbAdapter.KEY_BODY);
+ mDbHelper.updateNote(mRowId, editTitle, editBody);
+ }
+ fillData();
+ break;
+}</pre>
+
+ <ul>
+ <li>
+ We are handling both the <code>ACTIVITY_CREATE</code> and
+ <code>ACTIVITY_EDIT</code> activity results in this method.
+ </li>
+ <li>
+ In the case of a create, we pull the title and body from the extras (retrieved from the
+ returned Intent) and use them to create a new note.
+ </li>
+ <li>
+ In the case of an edit, we pull the mRowId as well, and use that to update
+ the note in the database.
+ </li>
+ <li>
+ <code>fillData()</code> at the end ensures everything is up to date .
+ </li>
+ </ul>
+
+
+<h2>Step 7</h2>
+
+ <div class="sidebox" style="border:2px solid #FFFFDD;float:right;
+ background-color:#FFFFEE;margin-right:0px;
+ margin-bottom:.5em;margin-top:1em;padding:0em;width:240px;">
+ <h2 style="border:0;font-size:12px;padding:.5em .5em .5em 1em;margin:0;
+ background-color:#FFFFDD;">The Art of Layout</h2>
+ <p style="padding-left:.5em;font-size:12px;margin:0; padding:.0em .5em .5em 1em;">The provided
+ note_edit.xml layout file is the most sophisticated one in the application we will be building,
+ but that doesn't mean it is even close to the kind of sophistication you will be likely to want
+ in real Android applications.</p>
+ <p style="padding-left:.5em;font-size:12px;margin:0; padding:.0em .5em .5em 1em;">Creating a
+ good UI is part art and part science, and the rest is work. Mastery of <a
+ href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a> is an essential part of creating
+ a good looking Android application.</p>
+ <p style="padding-left:.5em;font-size:12px;margin:0;
+ padding:.0em .5em .5em 1em;">Take a look at the
+ <a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a>
+ for some example layouts and how to use them. The ApiDemos sample project is also a
+ great resource from which to learn how to create different layouts.</p>
+ </div>
+
+<p>Open the file <code>note_edit.xml</code> that has been provided and take a
+ look at it. This is the UI code for the Note Editor.</p>
+ <p>This is the most
+ sophisticated UI we have dealt with yet. The file is given to you to avoid
+ problems that may sneak in when typing the code. (The XML is very strict
+ about case sensitivity and structure, mistakes in these are the usual cause
+ of problems with layout.)</p>
+ <p>There is a new parameter used
+ here that we haven't seen before: <code>android:layout_weight</code> (in
+ this case set to use the value 1 in each case).</p>
+ <p><code>layout_weight</code> is used in LinearLayouts
+ to assign "importance" to Views within the layout. All Views have a default
+ <code>layout_weight</code> of zero, meaning they take up only as much room
+ on the screen as they need to be displayed. Assigning a value higher than
+ zero will split up the rest of the available space in the parent View, according
+ to the value of each View's <code>layout_weight</code> and its ratio to the
+ overall <code>layout_weight</code> specified in the current layout for this
+ and other View elements.</p>
+ <p>To give an example: let's say we have a text label
+ and two text edit elements in a horizontal row. The label has no
+ <code>layout_weight</code> specified, so it takes up the minimum space
+ required to render. If the <code>layout_weight</code> of each of the two
+ text edit elements is set to 1, the remaining width in the parent layout will
+ be split equally between them (because we claim they are equally important).
+ If the first one has a <code>layout_weight</code> of 1
+ and the second has a <code>layout_weight</code> of 2, then one third of the
+ remaining space will be given to the first, and two thirds to the
+ second (because we claim the second one is more important).</p>
+ <p>This layout also demonstrates how to nest multiple layouts
+ inside each other to achieve a more complex and pleasant layout. In this
+ example, a horizontal linear layout is nested inside the vertical one to
+ allow the title label and text field to be alongside each other,
+ horizontally.</p>
+
+
+<h2 style="clear:right;">Step 8</h2>
+
+ <p>Create a <code>NoteEdit</code> class that extends
+ <code>android.app.Activity</code>.</p>
+ <p>This is the first time we will have
+ created an Activity without the Android Eclipse plugin doing it for us. When
+ you do so, the <code>onCreate()</code> method is not automatically
+ overridden for you. It is hard to imagine an Activity that doesn't override
+ the <code>onCreate()</code> method, so this should be the first thing you do.</p>
+ <ol>
+ <li>Right click on the <code>com.android.demo.notepad2</code> package
+ in the Package Explorer, and select <strong>New</strong> &gt; <strong>Class</strong> from the popup
+ menu.</li>
+ <li>Fill in <code>NoteEdit</code> for the <code>Name:</code> field in the
+ dialog.</li>
+ <li>In the <code>Superclass:</code> field, enter
+ <code>android.app.Activity</code> (you can also just type Activity and hit
+ Ctrl-Space on Windows and Linux or Cmd-Space on the Mac, to invoke code
+ assist and find the right package and class).</li>
+ <li>Click <strong>Finish</strong>.</li>
+ <li>In the resulting <code>NoteEdit</code> class, right click in the editor
+ window and select <strong>Source</strong> &gt; <strong>Override/Implement Methods...</strong></li>
+ <li>Scroll down through the checklist in the dialog until you see
+ <code>onCreate(Bundle)</code> &mdash; and check the box next to it.</li>
+ <li>Click <strong>OK</strong>.<p>The method should now appear in your class.</p></li>
+ </ol>
+
+<h2>Step 9</h2>
+
+<p>Fill in the body of the <code>onCreate()</code> method for <code>NoteEdit</code>.</p>
+
+<p>This will set the title of our new Activity to say "Edit Note" (one
+ of the strings defined in <code>strings.xml</code>). It will also set the
+ content view to use our <code>note_edit.xml</code> layout file. We can then
+ grab handles to the title and body text edit views, and the confirm button,
+ so that our class can use them to set and get the note title and body,
+ and attach an event to the confirm button for when it is pressed by the
+ user.</p>
+ <p>We can then unbundle the values that were passed in to the Activity
+ with the extras Bundle attached to the calling Intent. We'll use them to pre-populate
+ the title and body text edit views so that the user can edit them.
+ Then we will grab and store the <code>mRowId</code> so we can keep
+ track of what note the user is editing.</p>
+
+ <ol>
+ <li>
+ Inside <code>onCreate()</code>, set up the layout:<br>
+ <pre>setContentView(R.layout.note_edit);</pre>
+ </li>
+ <li>
+ Find the edit and button components we need:
+ <p>These are found by the
+ IDs associated to them in the R class, and need to be cast to the right
+ type of <code>View</code> (<code>EditText</code> for the two text views,
+ and <code>Button</code> for the confirm button):</p>
+ <pre>
+mTitleText = (EditText) findViewById(R.id.title);
+mBodyText = (EditText) findViewById(R.id.body);
+Button confirmButton = (Button) findViewById(R.id.confirm);</pre>
+ <p>Note that <code>mTitleText</code> and <code>mBodyText</code> are member
+ fields (you need to declare them at the top of the class definition).</p>
+ </li>
+ <li>At the top of the class, declare a <code>Long mRowId</code> private field to store
+ the current <code>mRowId</code> being edited (if any).
+ </li>
+ <li>Continuing inside <code>onCreate()</code>,
+ add code to initialize the <code>title</code>, <code>body</code> and
+ <code>mRowId</code> from the extras Bundle in
+ the Intent (if it is present):<br>
+ <pre>
+mRowId = null;
+Bundle extras = getIntent().getExtras();
+if (extras != null) {
+ String title = extras.getString(NotesDbAdapter.KEY_TITLE);
+ String body = extras.getString(NotesDbAdapter.KEY_BODY);
+ mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
+
+ if (title != null) {
+ mTitleText.setText(title);
+ }
+ if (body != null) {
+ mBodyText.setText(body);
+ }
+}</pre>
+ <ul>
+ <li>
+ We are pulling the <code>title</code> and
+ <code>body</code> out of the
+ <code>extras</code> Bundle that was set from the
+ Intent invocation.
+ </li><li>
+ We also null-protect the text field setting (i.e., we don't want to set
+ the text fields to null accidentally).</li>
+ </ul>
+ </li>
+ <li>
+ Create an <code>onClickListener()</code> for the button:
+ <p>Listeners can be one of the more confusing aspects of UI
+ implementation, but
+ what we are trying to achieve in this case is simple. We want an
+ <code>onClick()</code> method to be called when the user presses the
+ confirm button, and use that to do some work and return the values
+ of the edited note to the Intent caller. We do this using something called
+ an anonymous inner class. This is a bit confusing to look at unless you
+ have seen them before, but all you really need to take away from this is
+ that you can refer to this code in the future to see how to create a
+ listener and attach it to a button. (Listeners are a common idiom
+ in Java development, particularly for user interfaces.) Here's the empty listener:<br>
+ <pre>
+confirmButton.setOnClickListener(new View.OnClickListener() {
+
+ public void onClick(View view) {
+
+ }
+
+});</pre>
+ </li>
+ </ol>
+<h2>Step 10</h2>
+
+<p>Fill in the body of the <code>onClick()</code> method of the <code>OnClickListener</code> created in the last step.</p>
+
+ <p>This is the code that will be run when the user clicks on the
+ confirm button. We want this to grab the title and body text from the edit
+ text fields, and put them into the return Bundle so that they can be passed
+ back to the Activity that invoked this <code>NoteEdit</code> Activity. If the
+ operation is an edit rather than a create, we also want to put the
+ <code>mRowId</code> into the Bundle so that the
+ <code>Notepadv2</code> class can save the changes back to the correct
+ note.</p>
+ <ol>
+ <li>
+ Create a <code>Bundle</code> and put the title and body text into it using the
+ constants defined in Notepadv2 as keys:<br>
+ <pre>
+Bundle bundle = new Bundle();
+
+bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
+bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
+if (mRowId != null) {
+ bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
+}</pre>
+ </li>
+ <li>
+ Set the result information (the Bundle) in a new Intent and finish the Activity:
+ <pre>
+Intent mIntent = new Intent();
+mIntent.putExtras(bundle);
+setResult(RESULT_OK, mIntent);
+finish();</pre>
+ <ul>
+ <li>The Intent is simply our data carrier that carries our Bundle
+ (with the title, body and mRowId).</li>
+ <li>The <code>setResult()</code> method is used to set the result
+ code and return Intent to be passed back to the
+ Intent caller. In this case everything worked, so we return RESULT_OK for the
+ result code.</li>
+ <li>The <code>finish()</code> call is used to signal that the Activity
+ is done (like a return call). Anything set in the Result will then be
+ returned to the caller, along with execution control.</li>
+ </ul>
+ </li>
+ </ol>
+ <p>The full <code>onCreate()</code> method (plus supporting class fields) should
+ now look like this:</p>
+ <pre>
+private EditText mTitleText;
+private EditText mBodyText;
+private Long mRowId;
+
+&#64;Override
+protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.note_edit);
+
+ mTitleText = (EditText) findViewById(R.id.title);
+ mBodyText = (EditText) findViewById(R.id.body);
+
+ Button confirmButton = (Button) findViewById(R.id.confirm);
+
+ mRowId = null;
+ Bundle extras = getIntent().getExtras();
+ if (extras != null) {
+ String title = extras.getString(NotesDbAdapter.KEY_TITLE);
+ String body = extras.getString(NotesDbAdapter.KEY_BODY);
+ mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
+
+ if (title != null) {
+ mTitleText.setText(title);
+ }
+ if (body != null) {
+ mBodyText.setText(body);
+ }
+ }
+
+ confirmButton.setOnClickListener(new View.OnClickListener() {
+
+ public void onClick(View view) {
+ Bundle bundle = new Bundle();
+
+ bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
+ bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
+ if (mRowId != null) {
+ bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
+ }
+
+ Intent mIntent = new Intent();
+ mIntent.putExtras(bundle);
+ setResult(RESULT_OK, mIntent);
+ finish();
+ }
+ });
+}</pre>
+ </li>
+ </ol>
+
+<h2>Step 11</h2>
+
+<div class="sidebox" style="border:2px solid #FFFFDD;float:right;
+ background-color:#FFFFEE;margin-right:0px;
+ margin-bottom:.5em;margin-top:1em;padding:0em;width:240px;">
+ <h2 style="border:0;font-size:12px;padding:.5em .5em .5em 1em;margin:0;
+ background-color:#FFFFDD;">The All-Important Android Manifest File</h2>
+ <p style="padding-left:.5em;font-size:12px;margin:0;
+ padding:.0em .5em .5em 1em;">The AndroidManifest.xml file is the way in which Android sees your
+ application. This file defines the category of the application, where
+ it shows up (or even if it shows up) in the launcher or settings, what
+ activities, services, and content providers it defines, what intents it can
+ receive, and more. </p>
+ <p style="padding-left:.5em;font-size:12px;margin:0;
+ padding:.0em .5em .5em 1em;">For more information, see the reference document
+ <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a></p>
+ </div>
+
+<p>Finally, the new Activity has to be defined in the manifest file:</p>
+ <p>Before the new Activity can be seen by Android, it needs its own
+ Activity entry in the <code>AndroidManifest.xml</code> file. This is to let
+ the system know that it is there and can be called. We could also specify
+ which IntentFilters the activity implements here, but we are going to skip
+ this for now and just let Android know that the Activity is
+ defined.</p>
+ <p>There is a Manifest editor included in the Eclipse plugin that makes it much easier
+ to edit the AndroidManifest file, and we will use this. If you prefer to edit the file directly
+ or are not using the Eclipse plugin, see the box at the end for information on how to do this
+ without using the new Manifest editor.<p>
+ <ol>
+ <li>Double click on the <code>AndroidManifest.xml</code> file in the package explorer to open it.
+ </li>
+ <li>Click the <strong>Application</strong> tab at the bottom of the Manifest editor.</li>
+ <li>Click <strong>Add...</strong> in the Application Nodes section.
+ <p>If you see a dialog with radiobuttons at the top, select the top radio button:
+ "Create a new element at the top level, in Application".</p></li>
+ <li>Make sure "(A) Activity" is selected in the selection pane of the dialog, and click <strong>OK</strong>.</li>
+ <li>Click on the new "Activity" node, in the Application Nodes section, then
+ type <code>.NoteEdit</code> into the <em>Name*</em>
+ field to the right. Press Return/Enter.</li>
+ </ol>
+ <p>The Android Manifest editor helps you add more complex entries into the AndroidManifest.xml
+ file, have a look around at some of the other options available (but be careful not to select
+ them otherwise they will be added to your Manifest). This editor should help you understand
+ and alter the AndroidManifest.xml file as you move on to more advanced Android applications.</p>
+
+ <p class="note">If you prefer to edit this file directly, simply open the
+ <code>AndroidManifest.xml</code> file and look at the source (use the
+ <code>AndroidManifest.xml</code> tab in the eclipse editor to see the source code directly).
+ Then edit the file as follows:<br>
+ <code>&lt;activity android:name=".NoteEdit"&gt;&lt;/activity&gt;</code><br><br>
+ This should be placed just below the line that reads:<br>
+ <code>&lt;/activity&gt;</code> for the <code>.Notepadv2</code> activity.</p>
+
+<h2 style="clear:right;">Step 12</h2>
+
+<p>Now Run it!</p>
+<p>You should now be able to add real notes from
+the menu, as well as delete an existing one. Notice that in order to delete, you must
+first use the directional controls on the device to highlight the note.
+Furthermore, selecting a note title from the list should bring up the note
+editor to let you edit it. Press confirm when finished to save the changes
+back to the database.
+
+<h2>Solution and Next Steps</h2>
+
+<p>You can see the solution to this exercise in <code>Notepadv2Solution</code>
+from the zip file to compare with your own.</p>
+<p>Now try editing a note, and then hitting the back button on the emulator
+instead of the confirm button (the back button is below the menu button). You
+will see an error come up. Clearly our application still has some problems.
+Worse still, if you did make some changes and hit the back button, when you go
+back into the notepad to look at the note you changed, you will find that all
+your changes have been lost. In the next exercise we will fix these
+problems.</p>
+
+<p>
+Once you are ready, move on to <a href="notepad-ex3.html">Tutorial
+Exercise 3</a> where you will fix the problems with the back button and lost
+edits by introducing a proper life cycle into the NoteEdit Activity.</p>
+
+