• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Notepad Exercise 2
2parent.title=Notepad Tutorial
3parent.link=index.html
4@jd:body
5
6
7<p><em>In this exercise, you will add a second Activity to your notepad application, to let the user
8create and edit notes. You will also allow the user to delete existing notes through a context menu.
9The new Activity assumes responsibility for creating new notes by
10collecting user input and packing it into a return Bundle provided by the intent. This exercise
11demonstrates:</em></p>
12<ul>
13<li><em>Constructing a new Activity and adding it to the Android manifest</em></li>
14<li><em>Invoking another Activity asynchronously using <code>startActivityForResult()</code></em></li>
15<li><em>Passing data between Activity in Bundle objects</em></li>
16<li><em>How to use a more advanced screen layout</em></li>
17<li><em>How to create a context menu</em></li>
18</ul>
19
20<div style="float:right;white-space:nowrap">
21	[<a href="notepad-ex1.html">Exercise 1</a>]
22	<span style="color:#BBB;">
23		[<a href="notepad-ex2.html" style="color:#DDD;">Exercise 2</a>]
24	</span>
25	[<a href="notepad-ex3.html">Exercise 3</a>]
26	[<a href="notepad-extra-credit.html">Extra Credit</a>]
27</div>
28
29<h2>Step 1</h2>
30
31<p>Create a new Android project using the sources from <code>Notepadv2</code> under the
32<code>NotepadCodeLab</code> folder, just like you did for the first exercise. If you see an error about
33<code>AndroidManifest.xml</code>, or some problems related to an
34<code>android.zip</code> file, right click on the project and select <strong>Android
35Tools</strong> &gt; <strong>Fix Project Properties</strong>.</p>
36
37<p>Open the <code>Notepadv2</code> project and take a look around:</p>
38<ul>
39    <li>
40      Open and look at the <code>strings.xml</code> file under
41      <code>res/values</code> &mdash; there are several new strings which we will use
42      for our new functionality
43    </li>
44    <li>
45      Also, open and take a look at the top of the <code>Notepadv2</code> class,
46      you will notice several new constants have been defined along with a new <code>mNotesCursor</code>
47      field used to hold the cursor we are using.
48    </li>
49    <li>
50      Note also that the <code>fillData()</code> method has a few more comments and now uses
51      the new field to store the notes Cursor. The <code>onCreate()</code> method is
52      unchanged from the first exercise. Also notice that the member field used to store the
53      notes Cursor is now called <code>mNotesCursor</code>. The <code>m</code> denotes a member
54      field and is part of the Android coding style standards.
55    </li>
56    <li>
57      There are also a couple of new overridden methods
58      (<code>onCreateContextMenu()</code>, <code>onContextItemSelected()</code>,
59      <code>onListItemClick()</code> and <code>onActivityResult()</code>)
60      which we will be filling in below.
61    </li>
62</ul>
63
64
65<h2>Step 2</h2>
66
67<div class="sidebox">
68<p>Context menus should always be used when performing actions upon specific elements in the UI.
69When you register a View to a context menu, the context menu is revealed by performing a "long-click"
70on the UI component (press and hold the touchscreen or highlight and hold down the selection key for about two seconds).</p>
71</div>
72
73<p>First, let's create the context menu that will allow users to delete individual notes.
74Open the Notepadv2 class.</p>
75
76<ol>
77    <li>In order for each list item in the ListView to register for the context menu, we call
78    <code>registerForContextMenu()</code> and pass it our ListView. So, at the very end of
79    the <code>onCreate()</code> method add this line:
80    <pre>registerForContextMenu(getListView());</pre>
81    <p>Because our Activity extends the ListActivity class, <code>getListView()</code> will return us
82    the local ListView object for the Activity. Now, each list item in this ListView will activate the
83    context menu.
84    <li>
85      Now fill in the <code>onCreateContextMenu()</code> method. This callback is similar to the other
86    menu callback used for the options menu. Here, we add just one line, which will add a menu item
87    to delete a note. Call <code>menu.add()</code> like so:
88      <pre>
89public boolean onCreateContextMenu(Menu menu, View v
90        ContextMenuInfo menuInfo) {
91    super.onCreateContextMenu(menu, v, menuInfo);
92    menu.add(0, DELETE_ID, 0, R.string.menu_delete);
93}</pre>
94    <p>The <code>onCreateContextMenu()</code> callback some passes other information in addition to the Menu object,
95    such as the View that has been triggered for the menu and
96    an extra object that may contain additional information about the object selected. However, we don't care about
97    these here, because we only have one kind of object in the Activity that uses context menus. In the next
98    step, we'll handle the menu item selection.</p>
99    </li>
100</ol>
101
102<h2>Step 3</h2>
103  <p>Now that the we've registered our ListView for a context menu and defined our context menu item, we need
104  to handle the callback when it is selected. For this, we need to identify the list ID of the
105  selected item, then delete it. So fill in the
106  <code>onContextItemSelected()</code> method like this:</p>
107<pre>
108public boolean onContextItemSelected(MenuItem item) {
109    switch(item.getItemId()) {
110    case DELETE_ID:
111        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
112        mDbHelper.deleteNote(info.id);
113        fillData();
114        return true;
115    }
116    return super.onContextItemSelected(item);
117}</pre>
118<p>Here, we retrieve the {@link android.widget.AdapterView.AdapterContextMenuInfo AdapterContextMenuInfo}
119with {@link android.view.MenuItem#getMenuInfo()}. The <var>id</var> field of this object tells us
120the position of the item in the ListView. We then pass this to the <code>deleteNote()</code>
121method of our NotesDbAdapter and the note is deleted. That's it for the context menu &mdash; notes
122can now be deleted.</p>
123
124<h2 style="clear:right;">Step 4</h2>
125<div class="sidebox" style="border:2px solid #FFFFDD;float:right;
126     background-color:#FFFFEE;margin-right:0px;
127     margin-bottom:.5em;margin-top:1em;padding:0em;width:240px;">
128    <h2 style="border:0;font-size:12px;padding:.5em .5em .5em 1em;margin:0;
129      background-color:#FFFFDD;">Starting Other Activities</h2>
130    <p style="padding-left:.5em;font-size:12px;margin:0;
131     padding:.0em .5em .5em 1em;">In this example our Intent uses a class name specifically.
132     As well as
133     <a href="{@docRoot}guide/appendix/faq/commontasks.html#intentexamples">starting intents</a> in
134    classes we already know about, be they in our own application or another
135    application, we can also create Intents without knowing exactly which
136    application will handle it.</p>
137    <p style="padding-left:.5em;font-size:12px;margin:0;
138     padding:.0em .5em .5em 1em;">For example, we might want to open a page in a
139    browser, and for this we still use
140    an Intent. But instead of specifying a class to handle it, we use
141    a predefined Intent constant, and a content URI that describes what we
142    want to do. See {@link android.content.Intent
143    android.content.Intent} for more information.</p>
144</div>
145
146	<p>Fill in the body of the <code>createNote()</code> method:
147    <p>Create a new <code>Intent</code> to create a note
148    (<code>ACTIVITY_CREATE</code>) using the <code>NoteEdit</code> class.
149    Then fire the Intent using the <code>startActivityForResult()</code> method
150    call:</p>
151    <pre style="overflow:auto">
152Intent i = new Intent(this, NoteEdit.class);
153startActivityForResult(i, ACTIVITY_CREATE);</pre>
154      <p>This form of the Intent call targets a specific class in our Activity, in this case
155      <code>NoteEdit</code>. Since the Intent class will need to communicate with the Android
156      operating system to route requests, we also have to provide a Context (<code>this</code>).</p>
157      <p>The <code>startActivityForResult()</code> method fires the Intent in a way that causes a method
158      in our Activity to be called when the new Activity is completed. The method in our Activity
159      that receives the callback is called
160      <code>onActivityResult()</code> and we will implement it in a later step. The other way
161      to call an Activity is using <code>startActivity()</code> but this is a "fire-and-forget" way
162      of calling it &mdash; in this manner, our Activity is not informed when the Activity is completed, and there is
163      no way to return result information from the called Activity with <code>startActivity()</code>.
164      <p>Don't worry about the fact that <code>NoteEdit</code> doesn't exist yet,
165      we will fix that soon. </p>
166  </li>
167
168
169<h2>Step 5</h2>
170
171	<p>Fill in the body of the <code>onListItemClick()</code> override.</p>
172    <p><code>onListItemClick()</code> is a callback method that we'll override. It is called when
173    the user selects an item from the list. It is passed four parameters: the
174    <code>ListView</code> object it was invoked from, the <code>View</code>
175    inside the <code>ListView</code> that was clicked on, the
176    <code>position</code> in the list that was clicked, and the
177    <code>mRowId</code> of the item that was clicked. In this instance we can
178    ignore the first two parameters (we only have one <code>ListView</code> it
179    could be), and we ignore the <code>mRowId</code> as well. All we are
180    interested in is the <code>position</code> that the user selected. We use
181    this to get the data from the correct row, and bundle it up to send to
182    the <code>NoteEdit</code> Activity.</p>
183   <p>In our implementation of the callback, the method creates an
184    <code>Intent</code> to edit the note using
185    the <code>NoteEdit</code> class. It then adds data into the extras Bundle of
186    the Intent, which will be passed to the called Activity. We use it
187    to pass in the title and body text, and the <code>mRowId</code> for the note we are
188    editing. Finally, it will fire the Intent using the
189    <code>startActivityForResult()</code> method call. Here's the code that
190    belongs in <code>onListItemClick()</code>:</p>
191    <pre>
192super.onListItemClick(l, v, position, id);
193Cursor c = mNotesCursor;
194c.moveToPosition(position);
195Intent i = new Intent(this, NoteEdit.class);
196i.putExtra(NotesDbAdapter.KEY_ROWID, id);
197i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(
198        c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
199i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
200        c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
201startActivityForResult(i, ACTIVITY_EDIT);</pre>
202  <ul>
203    <li>
204      <code>putExtra()</code> is the method to add items into the extras Bundle
205      to pass in to intent invocations. Here, we are
206      using the Bundle to pass in the title, body and mRowId of the note we want to edit.
207    </li>
208    <li>
209      The details of the note are pulled out from our query Cursor, which we move to the
210      proper position for the element that was selected in the list, with
211      the <code>moveToPosition()</code> method.</li>
212    <li>With the extras added to the Intent, we invoke the Intent on the
213      <code>NoteEdit</code> class by passing <code>startActivityForResult()</code>
214      the Intent and the request code. (The request code will be
215      returned to <code>onActivityResult</code> as the <code>requestCode</code> parameter.)</li>
216  </ul>
217    <p class="note"><b>Note:</b> We assign the mNotesCursor field to a local variable at the
218    start of the method. This is done as an optimization of the Android code. Accessing a local
219    variable is much more efficient than accessing a field in the Dalvik VM, so by doing this
220    we make only one access to the field, and five accesses to the local variable, making the
221    routine much more efficient. It is recommended that you use this optimization when possible.</p>
222
223
224<h2>Step 6</h2>
225
226<p>The above <code>createNote()</code> and <code>onListItemClick()</code>
227    methods use an asynchronous Intent invocation. We need a handler for the callback, so here we fill
228    in the body of the <code>onActivityResult()</code>. </p>
229<p><code>onActivityResult()</code> is the overridden method
230    which will be called when an Activity returns with a result. (Remember, an Activity
231    will only return a result if launched with <code>startActivityForResult</code>.) The parameters provided
232    to the callback are: </p>
233  <ul>
234    <li><code>requestCode</code> &mdash; the original request code
235    specified in the Intent invocation (either <code>ACTIVITY_CREATE</code> or
236    <code>ACTIVITY_EDIT</code> for us).
237    </li>
238    <li><code>resultCode</code> &mdash; the result (or error code) of the call, this
239    should be zero if everything was OK, but may have a non-zero code indicating
240    that something failed. There are standard result codes available, and you
241    can also create your own constants to indicate specific problems.
242    </li>
243    <li><code>intent</code> &mdash; this is an Intent created by the Activity returning
244    results. It can be used to return data in the Intent "extras."
245    </li>
246  </ul>
247  <p>The combination of <code>startActivityForResult()</code> and
248  <code>onActivityResult()</code> can be thought of as an asynchronous RPC
249  (remote procedure call) and forms the recommended way for an Activity to invoke
250  another and share services.</p>
251  <p>Here's the code that belongs in your <code>onActivityResult()</code>:</p>
252    <pre>
253super.onActivityResult(requestCode, resultCode, intent);
254Bundle extras = intent.getExtras();
255
256switch(requestCode) {
257case ACTIVITY_CREATE:
258    String title = extras.getString(NotesDbAdapter.KEY_TITLE);
259    String body = extras.getString(NotesDbAdapter.KEY_BODY);
260    mDbHelper.createNote(title, body);
261    fillData();
262    break;
263case ACTIVITY_EDIT:
264    Long mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
265    if (mRowId != null) {
266        String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE);
267        String editBody = extras.getString(NotesDbAdapter.KEY_BODY);
268        mDbHelper.updateNote(mRowId, editTitle, editBody);
269    }
270    fillData();
271    break;
272}</pre>
273
274  <ul>
275    <li>
276      We are handling both the <code>ACTIVITY_CREATE</code> and
277      <code>ACTIVITY_EDIT</code> activity results in this method.
278    </li>
279    <li>
280      In the case of a create, we pull the title and body from the extras (retrieved from the
281      returned Intent) and use them to create a new note.
282    </li>
283    <li>
284      In the case of an edit, we pull the mRowId as well, and use that to update
285      the note in the database.
286    </li>
287    <li>
288      <code>fillData()</code> at the end ensures everything is up to date .
289    </li>
290  </ul>
291
292
293<h2>Step 7</h2>
294
295  <div class="sidebox" style="border:2px solid #FFFFDD;float:right;
296      background-color:#FFFFEE;margin-right:0px;
297      margin-bottom:.5em;margin-top:1em;padding:0em;width:240px;">
298    <h2 style="border:0;font-size:12px;padding:.5em .5em .5em 1em;margin:0;
299      background-color:#FFFFDD;">The Art of Layout</h2>
300    <p style="padding-left:.5em;font-size:12px;margin:0; padding:.0em .5em .5em 1em;">The provided
301    note_edit.xml layout file is the most sophisticated one in the application we will be building,
302    but that doesn't mean it is even close to the kind of sophistication you will be likely to want
303    in real Android applications.</p>
304    <p style="padding-left:.5em;font-size:12px;margin:0; padding:.0em .5em .5em 1em;">Creating a
305    good UI is part art and part science, and the rest is work. Mastery of <a
306    href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a> is an essential part of creating
307    a good looking Android application.</p>
308    <p style="padding-left:.5em;font-size:12px;margin:0;
309     padding:.0em .5em .5em 1em;">Take a look at the
310    <a href="{@docRoot}guide/tutorials/views/index.html">Hello Views</a>
311    for some example layouts and how to use them. The ApiDemos sample project is also a
312    great resource from which to learn how to create different layouts.</p>
313  </div>
314
315<p>Open the file <code>note_edit.xml</code> that has been provided and take a
316    look at it. This is the UI code for the Note Editor.</p>
317    <p>This is the most
318    sophisticated UI we have dealt with yet. The file is given to you to avoid
319    problems that may sneak in when typing the code. (The XML is very strict
320    about case sensitivity and structure, mistakes in these are the usual cause
321    of problems with layout.)</p>
322    <p>There is a new parameter used
323    here that we haven't seen before: <code>android:layout_weight</code> (in
324    this case set to use the value 1 in each case).</p>
325    <p><code>layout_weight</code> is used in LinearLayouts
326    to assign "importance" to Views within the layout. All Views have a default
327    <code>layout_weight</code> of zero, meaning they take up only as much room
328    on the screen as they need to be displayed. Assigning a value higher than
329    zero will split up the rest of the available space in the parent View, according
330    to the value of each View's <code>layout_weight</code> and its ratio to the
331    overall <code>layout_weight</code> specified in the current layout for this
332    and other View elements.</p>
333    <p>To give an example: let's say we have a text label
334    and two text edit elements in a horizontal row. The label has no
335    <code>layout_weight</code> specified, so it takes up the minimum space
336    required to render. If the <code>layout_weight</code> of each of the two
337    text edit elements is set to 1, the remaining width in the parent layout will
338    be split equally between them (because we claim they are equally important).
339    If the first one has a <code>layout_weight</code> of 1
340    and the second has a <code>layout_weight</code> of 2, then one third of the
341    remaining space will be given to the first, and two thirds to the
342    second (because we claim the second one is more important).</p>
343    <p>This layout also demonstrates how to nest multiple layouts
344    inside each other to achieve a more complex and pleasant layout. In this
345    example, a horizontal linear layout is nested inside the vertical one to
346    allow the title label and text field to be alongside each other,
347    horizontally.</p>
348
349
350<h2 style="clear:right;">Step 8</h2>
351
352	<p>Create a <code>NoteEdit</code> class that extends
353    <code>android.app.Activity</code>.</p>
354    <p>This is the first time we will have
355    created an Activity without the Android Eclipse plugin doing it for us. When
356    you do so, the <code>onCreate()</code> method is not automatically
357    overridden for you. It is hard to imagine an Activity that doesn't override
358    the <code>onCreate()</code> method, so this should be the first thing you do.</p>
359  <ol>
360    <li>Right click on the <code>com.android.demo.notepad2</code> package
361    in the Package Explorer, and select <strong>New</strong> &gt; <strong>Class</strong> from the popup
362    menu.</li>
363    <li>Fill in <code>NoteEdit</code> for the <code>Name:</code> field in the
364    dialog.</li>
365    <li>In the <code>Superclass:</code> field, enter
366    <code>android.app.Activity</code> (you can also just type Activity and hit
367    Ctrl-Space on Windows and Linux or Cmd-Space on the Mac, to invoke code
368    assist and find the right package and class).</li>
369    <li>Click <strong>Finish</strong>.</li>
370    <li>In the resulting <code>NoteEdit</code> class, right click in the editor
371    window and select <strong>Source</strong> &gt; <strong>Override/Implement Methods...</strong></li>
372    <li>Scroll down through the checklist in the dialog until you see
373    <code>onCreate(Bundle)</code> &mdash; and check the box next to it.</li>
374    <li>Click <strong>OK</strong>.<p>The method should now appear in your class.</p></li>
375  </ol>
376
377<h2>Step 9</h2>
378
379<p>Fill in the body of the <code>onCreate()</code> method for <code>NoteEdit</code>.</p>
380
381<p>This will set the title of our new Activity to say "Edit Note" (one
382    of the strings defined in <code>strings.xml</code>). It will also set the
383    content view to use our <code>note_edit.xml</code> layout file. We can then
384    grab handles to the title and body text edit views, and the confirm button,
385    so that our class can use them to set and get the note title and body,
386    and attach an event to the confirm button for when it is pressed by the
387    user.</p>
388    <p>We can then unbundle the values that were passed in to the Activity
389    with the extras Bundle attached to the calling Intent. We'll use them to pre-populate
390    the title and body text edit views so that the user can edit them.
391    Then we will grab and store the <code>mRowId</code> so we can keep
392    track of what note the user is editing.</p>
393
394  <ol>
395    <li>
396      Inside <code>onCreate()</code>, set up the layout:<br>
397      <pre>setContentView(R.layout.note_edit);</pre>
398    </li>
399    <li>
400      Find the edit and button components we need:
401      <p>These are found by the
402      IDs associated to them in the R class, and need to be cast to the right
403      type of <code>View</code> (<code>EditText</code> for the two text views,
404      and <code>Button</code> for the confirm button):</p>
405      <pre>
406mTitleText = (EditText) findViewById(R.id.title);
407mBodyText = (EditText) findViewById(R.id.body);
408Button confirmButton = (Button) findViewById(R.id.confirm);</pre>
409      <p>Note that <code>mTitleText</code> and <code>mBodyText</code> are member
410      fields (you need to declare them at the top of the class definition).</p>
411    </li>
412    <li>At the top of the class, declare a <code>Long mRowId</code> private field to store
413      the current <code>mRowId</code> being edited (if any).
414    </li>
415    <li>Continuing inside <code>onCreate()</code>,
416      add code to initialize the <code>title</code>, <code>body</code> and
417      <code>mRowId</code> from the extras Bundle in
418      the Intent (if it is present):<br>
419      <pre>
420mRowId = null;
421Bundle extras = getIntent().getExtras();
422if (extras != null) {
423    String title = extras.getString(NotesDbAdapter.KEY_TITLE);
424    String body = extras.getString(NotesDbAdapter.KEY_BODY);
425    mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
426
427    if (title != null) {
428        mTitleText.setText(title);
429    }
430    if (body != null) {
431        mBodyText.setText(body);
432    }
433}</pre>
434     <ul>
435      <li>
436        We are pulling the <code>title</code> and
437        <code>body</code> out of the
438        <code>extras</code> Bundle that was set from the
439        Intent invocation.
440      </li><li>
441        We also null-protect the text field setting (i.e., we don't want to set
442        the text fields to null accidentally).</li>
443     </ul>
444    </li>
445    <li>
446      Create an <code>onClickListener()</code> for the button:
447      <p>Listeners can be one of the more confusing aspects of UI
448      implementation, but
449      what we are trying to achieve in this case is simple. We want an
450      <code>onClick()</code> method to be called when the user presses the
451      confirm button, and use that to do some work and return the values
452      of the edited note to the Intent caller. We do this using something called
453      an anonymous inner class. This is a bit confusing to look at unless you
454      have seen them before, but all you really need to take away from this is
455      that you can refer to this code in the future to see how to create a
456      listener and attach it to a button. (Listeners are a common idiom
457      in Java development, particularly for user interfaces.) Here's the empty listener:<br>
458      <pre>
459confirmButton.setOnClickListener(new View.OnClickListener() {
460
461    public void onClick(View view) {
462
463    }
464
465});</pre>
466    </li>
467  </ol>
468<h2>Step 10</h2>
469
470<p>Fill in the body of the <code>onClick()</code> method of the <code>OnClickListener</code> created in the last step.</p>
471
472    <p>This is the code that will be run when the user clicks on the
473    confirm button. We want this to grab the title and body text from the edit
474    text fields, and put them into the return Bundle so that they can be passed
475    back to the Activity that invoked this <code>NoteEdit</code> Activity. If the
476    operation is an edit rather than a create, we also want to put the
477    <code>mRowId</code> into the Bundle so that the
478    <code>Notepadv2</code> class can save the changes back to the correct
479    note.</p>
480  <ol>
481    <li>
482      Create a <code>Bundle</code> and put the title and body text into it using the
483      constants defined in Notepadv2 as keys:<br>
484      <pre>
485Bundle bundle = new Bundle();
486
487bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
488bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
489if (mRowId != null) {
490    bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
491}</pre>
492    </li>
493    <li>
494      Set the result information (the Bundle) in a new Intent and finish the Activity:
495      <pre>
496Intent mIntent = new Intent();
497mIntent.putExtras(bundle);
498setResult(RESULT_OK, mIntent);
499finish();</pre>
500      <ul>
501      <li>The Intent is simply our data carrier that carries our Bundle
502      (with the title, body and mRowId).</li>
503      <li>The <code>setResult()</code> method is used to set the result
504      code and return Intent to be passed back to the
505      Intent caller. In this case everything worked, so we return RESULT_OK for the
506      result code.</li>
507      <li>The <code>finish()</code> call is used to signal that the Activity
508      is done (like a return call). Anything set in the Result will then be
509      returned to the caller, along with execution control.</li>
510      </ul>
511    </li>
512   </ol>
513   <p>The full <code>onCreate()</code> method (plus supporting class fields) should
514      now look like this:</p>
515      <pre>
516private EditText mTitleText;
517private EditText mBodyText;
518private Long mRowId;
519
520&#64;Override
521protected void onCreate(Bundle savedInstanceState) {
522    super.onCreate(savedInstanceState);
523    setContentView(R.layout.note_edit);
524
525    mTitleText = (EditText) findViewById(R.id.title);
526    mBodyText = (EditText) findViewById(R.id.body);
527
528    Button confirmButton = (Button) findViewById(R.id.confirm);
529
530    mRowId = null;
531    Bundle extras = getIntent().getExtras();
532    if (extras != null) {
533        String title = extras.getString(NotesDbAdapter.KEY_TITLE);
534        String body = extras.getString(NotesDbAdapter.KEY_BODY);
535        mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
536
537        if (title != null) {
538            mTitleText.setText(title);
539        }
540        if (body != null) {
541            mBodyText.setText(body);
542        }
543    }
544
545    confirmButton.setOnClickListener(new View.OnClickListener() {
546
547        public void onClick(View view) {
548            Bundle bundle = new Bundle();
549
550            bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
551            bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
552            if (mRowId != null) {
553                bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
554            }
555
556            Intent mIntent = new Intent();
557            mIntent.putExtras(bundle);
558            setResult(RESULT_OK, mIntent);
559            finish();
560        }
561    });
562}</pre>
563    </li>
564  </ol>
565
566<h2>Step 11</h2>
567
568<div class="sidebox" style="border:2px solid #FFFFDD;float:right;
569      background-color:#FFFFEE;margin-right:0px;
570      margin-bottom:.5em;margin-top:1em;padding:0em;width:240px;">
571    <h2 style="border:0;font-size:12px;padding:.5em .5em .5em 1em;margin:0;
572      background-color:#FFFFDD;">The All-Important Android Manifest File</h2>
573  <p style="padding-left:.5em;font-size:12px;margin:0;
574     padding:.0em .5em .5em 1em;">The AndroidManifest.xml file is the way in which Android sees your
575    application. This file defines the category of the application, where
576    it shows up (or even if it shows up) in the launcher or settings, what
577    activities, services, and content providers it defines, what intents it can
578    receive, and more. </p>
579    <p style="padding-left:.5em;font-size:12px;margin:0;
580     padding:.0em .5em .5em 1em;">For more information, see the reference document
581    <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a></p>
582  </div>
583
584<p>Finally, the new Activity has to be defined in the manifest file:</p>
585    <p>Before the new Activity can be seen by Android, it needs its own
586    Activity entry in the <code>AndroidManifest.xml</code> file. This is to let
587    the system know that it is there and can be called. We could also specify
588    which IntentFilters the activity implements here, but we are going to skip
589    this for now and just let Android know that the Activity is
590    defined.</p>
591    <p>There is a Manifest editor included in the Eclipse plugin that makes it much easier
592    to edit the AndroidManifest file, and we will use this. If you prefer to edit the file directly
593    or are not using the Eclipse plugin, see the box at the end for information on how to do this
594    without using the new Manifest editor.<p>
595    <ol>
596    <li>Double click on the <code>AndroidManifest.xml</code> file in the package explorer to open it.
597    </li>
598    <li>Click the <strong>Application</strong> tab at the bottom of the Manifest editor.</li>
599    <li>Click <strong>Add...</strong> in the Application Nodes section.
600      <p>If you see a dialog with radiobuttons at the top, select the top radio button:
601      "Create a new element at the top level, in Application".</p></li>
602    <li>Make sure "(A) Activity" is selected in the selection pane of the dialog, and click <strong>OK</strong>.</li>
603    <li>Click on the new "Activity" node, in the Application Nodes section, then
604    type <code>.NoteEdit</code> into the <em>Name*</em>
605    field to the right. Press Return/Enter.</li>
606    </ol>
607    <p>The Android Manifest editor helps you add more complex entries into the AndroidManifest.xml
608    file, have a look around at some of the other options available (but be careful not to select
609    them otherwise they will be added to your Manifest). This editor should help you understand
610    and alter the AndroidManifest.xml file as you move on to more advanced Android applications.</p>
611
612    <p class="note">If you prefer to edit this file directly, simply open the
613    <code>AndroidManifest.xml</code> file and look at the source (use the
614    <code>AndroidManifest.xml</code> tab in the eclipse editor to see the source code directly).
615    Then edit the file as follows:<br>
616    <code>&lt;activity android:name=".NoteEdit"&gt;&lt;/activity&gt;</code><br><br>
617    This should be placed just below the line that reads:<br>
618    <code>&lt;/activity&gt;</code> for the <code>.Notepadv2</code> activity.</p>
619
620<h2 style="clear:right;">Step 12</h2>
621
622<p>Now Run it!</p>
623<p>You should now be able to add real notes from
624the menu, as well as delete an existing one. Notice that in order to delete, you must
625first use the directional controls on the device to highlight the note.
626Furthermore, selecting a note title from the list should bring up the note
627editor to let you edit it. Press confirm when finished to save the changes
628back to the database.
629
630<h2>Solution and Next Steps</h2>
631
632<p>You can see the solution to this exercise in  <code>Notepadv2Solution</code>
633from the zip file to compare with your own.</p>
634<p>Now try editing a note, and then hitting the back button on the emulator
635instead of the confirm button (the back button is below the menu button). You
636will see an error come up. Clearly our application still has some problems.
637Worse still, if you did make some changes and hit the back button, when you go
638back into the notepad to look at the note you changed, you will find that all
639your changes have been lost. In the next exercise we will fix these
640problems.</p>
641
642<p>
643Once you are ready, move on to <a href="notepad-ex3.html">Tutorial
644Exercise 3</a> where you will fix the problems with the back button and lost
645edits by introducing a proper life cycle into the NoteEdit Activity.</p>
646
647
648