CIS 350 Software Engineering - Spring 2012

Android Programming Exercise #2

Introduction
In this assignment, you will build a simple Android typing game in which the user is shown a sentence and has to type it in word-for-word. When the user is done, the program indicates how long it took to type the sentence, assuming it was entered correctly. The application also keeps track of the best (lowest) time to type the sentence correctly.

This exercise will focus on:

This document takes you step-by-step through everything that you need to do in order to implement this game.


Before you begin: a word about debugging in Android
When you're debugging your Android app, you'll probably be tempted to use trusty ol' System.out.println; it got you this far, right? But you'll notice immediately that the messages you print don't appear in the Android app, nor in the Eclipse console.

Android uses a logging mechanism called LogCat, in which messages are written to a file, along with the time they were written, any associated tags, etc. Instead of System.out.println(message), use Log.v(tag, message), where tag is some meaningful indicator that you can use if you need to filter the log file.

To see the messages that get written to LogCat, go to Window --> Show View --> Other... --> Android --> LogCat in Eclipse, and you'll see it appear at the bottom of the Eclipse window.

For more info, check out the Debugging section of the Android developers guide.


Step 0. Create a new Android project
Create an Android project in Eclipse. Give the project a meaningful name (something like "TypingGame") and choose a meaningful Java package name (e.g. "edu.upenn.cis350").


Step 1. Arrange the Views in a Layout
We want the main playing screen (where the user types in the sentence that she is shown) to look something like this:

That is, there is a TextView along the top, and EditText taking up the space in the middle, and two Buttons at the bottom. Edit "main.xml" in the res/layout folder in the Eclipse project to modify the UI, then run your application in the emulator to make sure that it looks okay.

The string that the user needs to type as part of the game should not be hardcoded in main.xml; instead, refer to a resource in the strings.xml file.

See slides 29-33 of Tuesday's lecture notes or "XML Layouts" in the developer guide if you need help.


Step 2. Handle button clicks
When the user clicks the "Submit" button, we want to check whether she typed the sentence correctly in the EditText. We will do this by handling the button click and then comparing the Strings.

First, modify main.xml to specify the method that should be called when the "Submit" button is clicked.

Next, implement that method in the Java class that you created (i.e., the one that extends Activity). Be sure that you use the appropriate method signature (i.e., visibility, return type, and parameters).

See slides 36 and 37 of Tuesday's lecture notes or "Input Events" in the developer guide if you need help.

Get the text from the EditText View and compare it to the String that the user was supposed to type. To get the String from the resource file, you can use the command getResources().getString(R.string.name), where name is the name you gave it in strings.xml.

Hint: be careful how you compare Strings in Java!

Now display a Toast indicating whether the user typed the sentence correctly. For simplicity, you can hard-code the messages that are displayed by the Toast directly into your Java class. See "Toast Notifications" in the developer guide.

Handling the "Quit" button is easy. Modify main.xml to specify the method that should be called when the "Quit" button is clicked, and implement that method in the Java class. In that method, simply call finish(); to exit the application.

Run your application in the emulator again and test that the button clicks are handled correctly. Check that you get the right message when you correctly enter the sentence, and when you do it incorrectly. Also check that the user can quit the application.


Step 3. Add "Are you ready?" Dialog
Now we're going to start adding functionality to measure how long it takes to type the sentence. We need some way for the user to indicate that she is ready (as opposed to just starting the clock as soon as the application starts), so we will show a Dialog asking "Are you ready?", like this:

Dialogs are covered in the "Dialogs" section of the developer guide, but the basics are described here:

In your Java class that extends Activity, create a field (member variable) like this: private static final int READY_DIALOG = 1; This will be the ID that we will use to show the Dialog.

Next, in the onCreate method, add the command showDialog(READY_DIALOG); at the end. This will attempt to show the Dialog when the Activity starts.

Last, you need to write the method that will actually construct the Dialog object and display it. This can be a bit tricky, so here's the code that you need:

   protected Dialog onCreateDialog(int id) {
    	if (id == READY_DIALOG) {
	    	AlertDialog.Builder builder = new AlertDialog.Builder(this);
                // this is the message to display
	    	builder.setMessage(R.string.ready); 
                // this is the button to display
	    	builder.setPositiveButton(R.string.yes,
	    		new DialogInterface.OnClickListener() {
                           // this is the method to call when the button is clicked 
	    	           public void onClick(DialogInterface dialog, int id) {
                                   // this will hide the dialog
	    	        	   dialog.cancel();
	    	           }
	    	         });
    		return builder.create();
    	}
    	else return null;
    }
}

Note that you will have to add the "ready" and "yes" resources to strings.xml.

Run your application and make sure that the "Are you ready?" Dialog appears when the application first starts, and that the Dialog disappears when you click the "Yes" button.


Step 4. Time how long it takes
Now we can time how long it takes for the user to type the sentence. We will do this by capturing the current time when the user clicks "Yes" in the "Are you ready?" Dialog, capturing the current time when the user clicks the "Submit" button, and calculating the difference.

To get the current time, use the System.currentTimeMillis(); method. This returns a long indicating the number of milliseconds since January 1, 1970 (seriously). If you capture the start and end times, you can just subtract to find out how many milliseconds have elapsed.

Modify the Toast that is shown when the user correctly types the sentence so that the elapsed time is displayed in seconds (not milliseconds), to one decimal place. You'll have to do a bit of math here! It should look something like this:


Step 5. Add "Try again" Dialog
At this point, the application only figures out how long it takes to type the sentence the first time. If you try it again, the time elapsed is measured since the user exited the "Are you ready?" Dialog. So let's change it so that, instead of showing a Toast to the user after she clicks submit, we show a Dialog with a button on it, and allow her to reset the clock.

In your Java class, create two new fields (member variables) like this: private static final int CORRECT_DIALOG = 2; and private static final int INCORRECT_DIALOG = 3; These will be the IDs that we will use to show the "you got it right" and "you got it wrong" Dialogs, respectively.

Modify the method that handles the "Submit" button click as follows: If the user correctly entered the sentence, rather than showing the Toast, call removeDialog(CORRECT_DIALOG); and then call showDialog(CORRECT_DIALOG); Be sure to call both methods, otherwise you will get some unexpected behavior.

Also modify the button handler method such that, if the user typed the sentence incorrectly, you call removeDialog(INCORRECT_DIALOG); and then call showDialog(INCORRECT_DIALOG); Again, be sure to call both methods.

Now you need to change onCreateDialog. Start with the code that is there and modify it by adding two new conditions to the "if" statement that is inspecting the value of the id parameter. If id is equal to CORRECT_DIALOG, then you want to use the AlertDialog.Builder class to create a Dialog that indicates that the user typed the sentence correctly, and displays the time it took in seconds; on the other hand, if id is equal to INCORRECT_DIALOG, then you want to use the AlertDialog.Builder class to create a Dialog that indicates that the user typed the sentence incorrectly.

In either case, when the user clicks the "OK" button in the Dialog, you should clear the text in the EditText, reset the timer, and let the user keep playing the game.

Here's a screen shot of how it should appear when the user correctly enters the sentence:

Run your application again. At this point, it should:


Step 6. Keep track of best (lowest) time
The last feature you'll add is the ability for the application to keep track of the best time (i.e., the lowest time elapsed).

Add a variable to the Java class to track the best time recorded so far. If the user correctly types the sentence, compare the elapsed time to the best time. If the user beat the best time, indicate that in the Dialog that is displayed, and update the best time; if the user didn't beat the best time, just show what the best time so far is.

Note that you should not display the "top score" message if this is the first time the user has entered the particular sentence. Also, you don't need to record top scores across program executions, only for the current invocation of the program.


Extra features
If you'd like, you can add extra sentences to your application so that the game has a little more variety. Create an array of string resources representing different sentences that may be shown to the user. Randomly show different sentences each time the user plays the game, and keep track of the top score for each one.

If you still want to add more features, try this one: When the user clicks the "Quit" button, display a Dialog asking "Do you really want to quit?" that has a "Yes" option (causing the application to finish) and a "No" option (causing no action).