Download presentation
Presentation is loading. Please wait.
Published byElaine Oliver Modified over 6 years ago
1
Android 7: Assignment 2, Part 1, One Button Recursion and Debugging
3
Introduction This set of overheads begins with a simple app where the sendMessage() method is small, but contains some significant code It is a lead-in to debugging As soon as code gets more complicated you have to be able to debug Android Studio has built-in debugging features, but sometimes the simple ways are the best…
4
7.1 The OneButtonRecursion app
7.2 Unhelpful Error Messages 7.3 Logging Output
5
7.1 The OneButtonRecursion app
6
Screen shots for the one button recursion app are shown on the following overhead
Functionally all that happens when you click the button is counting down to 0 recursively It happens so fast there’s nothing visible on the screen except the result
8
The OneButtonRecursion app will be presented in the order in which it was developed:
1. activity_main.xml, the layout 2. strings.xml, the resources 3. A look at R.java, the resources as made available by the system 4. MainActivity.java, the code for the app
9
As you might guess, part of what makes the app interesting is the fact that it includes recursion
It does something so simple that the recursion, although not necessary, is easy to understand Recursion is covered because it will be used in the implementation of Wari in the assignment The recursion also introduces the possibility of runtime errors
10
This example also has some things in common with the earlier assignments
It includes syntax for converting between strings and numbers, which can also lead to errors if not done correctly These errors are runtime errors, so they lead to the topic of debugging in Android
11
activity_main.xml for OneButtonRecursion
The app uses a RelativeLayout It contains a button and a text view The XML code for the layout is given on the following overheads for reference
12
<RelativeLayout xmlns:android="http://schemas. android
xmlns:tools=" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" >
13
<Button style="?android:attr/buttonStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:onClick="sendMessage" />
14
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
15
There were some items in the XML that haven’t come up before
Where did they come from? I used the graphical tools to drag and drop components into the layout The system generated the corresponding XML If necessary, you can then edit the system generated XML to tailor the layout to the specific app you’re trying to create
16
strings.xml for OneButtonRecursion
The strings.xml file for the app is shown on the following overhead There are no surprises The button and the text view have string resources associated with them
17
<?xml version="1.0" encoding="utf-8"?>
<resources> <string name="app_name">One Button Recursion</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <string name="button1Contents">Button1</string> <string name="textView1Contents">4</string> </resources>
18
R.Java for OneButtonRecursion
As you recall, the R.java file is generated for you It’s important because it’s the place where you can access resources when writing the Java code for MainActivity The relevant parts of R.java are shown on the following overhead
19
public static final class id {
… public static final int button1=0x7f080000; public static final int textView1=0x7f080001; } public static final class string { public static final int button1Contents=0x7f050003; public static final int textView1Contents=0x7f050004;
20
MainActivity.java for OneButtonRecursion, Discussion
The logic of OneButtonRecursion is quite simple The TextView is initially set to a value of 4 When you click the button, you call sendMessage()
21
sendMessage() checks to see what the current value is
If the value is >0, then a call is made to a method named playNextCup() and the value is passed in
22
playNextCup() decrements the value
It updates the text area to this new value If the value has not yet reached 0, it calls itself recursively The end result of this sequence of actions is that the value in the text view goes 4, 3, 2, 1, 0—too fast for the eye to see One click of the button causes the text view to go from 4 to 0, recursively
23
The logic is simple The code is considerably more complex than it would need to be to accomplish this simple task It repeatedly gets a handle on the text view and passes this around—which is needless, considering there is only one text area It also includes if statements to check “which button was clicked” when there is only one button
24
The code is written in this way because it is a preview of what will have to be done to implement Wari It is clumsy here, but it’s easier to first get an idea of what’s involved in a program that does something simple with only one text view and one button
25
In Wari, an app with >1 text view and button, it becomes apparent that it is necessary to repeatedly get references and pass them around and check which button was clicked
26
MainActivity.java for OneButtonRecursion, Code
At the top of the main activity the Log class is imported and the TAG string definition is given These will be useful for logging and debugging
27
import android.util.Log;
public class MainActivity extends Activity { private static final String TAG = "OneButtonRecursion"; …
28
sendMessage() for OneButtonRecursion
The code for sendMessage() is shown on the following overhead Note that the calls to findViewById() and playNextCup() are floating in space They are calls on the MainActivity itself
29
public void sendMessage(View view) {
Button clickedButton = (Button) view; if(clickedButton == findViewById(R.id.button1)) { TextView cup = (TextView) findViewById(R.id.textView1); int handFull = Integer.parseInt(cup.getText().toString()); if(handFull > 0) cup.setText(handFull + ""); playNextCup((TextView) findViewById(R.id.textView1), handFull); } else
30
playNextCup() for OneButtonRecursion
playNextCup() is the recursive method It contains the uses of Log and TAG (because when you’re doing the recursion it’s a likely place to make a mistake…) Using them for debugging will be discussed shortly
31
public static void playNextCup(TextView cupIn, int handFullIn)
{ handFullIn--; cupIn.setText(handFullIn + ""); if(handFullIn != 0) playNextCup(cupIn, handFullIn); Log.i(TAG, "In recursion " + handFullIn); } else
32
7.2 Unhelpful Error Messages
33
When writing the code even for this simple app, I made mistakes (go figure)
It quickly became apparent that I would need to be able to debug in the Android environment I’m not referring now to the debugging tools in Android Studio—they’re beyond the scope of this course I’m referring to simply figuring out what was going on
34
Compiler errors are shown in the bottom window of the development environment
The screen shot on the following overhead illustrates: How a bad line of code is highlighted in the editor And how the error messages are shown at the bottom
36
I also got two good (bad) examples with OneButtonRecursion of what can go more seriously wrong and the quandary you’re left in First of all, notice that if you right click on the mouse with the pointer near the left hand margin of the editor, you have the option of showing line numbers in the source This can be very helpful It’s illustrated on the following overheads
39
As usual, like with many systems, the error messages might not be very helpful
Being able to look the error message up on the Web can very helpful in trying to figure out what it means Do not be afraid to do this I find that stackoverflow.com is the likeliest place to find correct answers (after potentially sorting through things that don’t apply)
40
Example 1 Here is a snippet of code that’s in error:
int handFull = Integer.parseInt(cup.getText().toString()); … cup.setText(handFull); The next overhead shows what happens when you try to run it This is not very helpful
42
This is the line of code that’s the problem
It assumes that handFull gets converted to a String automatically cup.setText(handFull); This is not the case It is a potentially confusing error because there is a version of setText() which accepts an integer parameter, where the integer is the id for a resource
43
The value contained in handFull doesn’t agree with any defined resource id value, so the system has a runtime problem (Imagine the fun you’d have if, by accident, handFull did contain a valid resource id, and you got inexplicable results instead of a runtime error)
44
In any case, once you know what’s wrong, the solution is simple
This is the corrected code: int handFull = Integer.parseInt(cup.getText().toString()); … cup.setText(handFull + “”);
45
Identifying the line of that contains an error can be accomplished by inserting print statements into code This will be illustrated after considering another error
46
Example 2 The same two lines of code contain a call that can also generate another unhelpful runtime error int handFull = Integer.parseInt(cup.getText().toString()); … cup.setText(handFull + “”); Consider the call to parseInt() parseInt() will fail if you apply it to a string that can’t be parsed as an integer
47
If you write the code as shown and the text view you’re getting the string from doesn’t contain an integer You will are likely to get error messages at build time Whether you can sort them out or not, you will definitely get the “Unfortunately, OneButtonRecursion has stopped …OK…” message at run time
48
7.3 Logging Output
49
Remember that the playNext() method contained calls to the static method i in the Log class which causes the code to generate runtime output This is shown again on the following overhead
50
public static void playNextCup(TextView cupIn, int handFullIn) { handFullIn--; cupIn.setText(handFullIn + ""); if(handFullIn != 0) { playNextCup(cupIn, handFullIn); Log.i(TAG, "In recursion " + handFullIn); } else { } }
51
The screen shot on the following overhead shows the logcat screen open at the bottom of the development environment when OneButtonRecursion has been run The highlighted lines are the output of the program, showing the succession of values generated by the recursion and put out by the call to Log.i()
53
In order to do simple debugging, you need to be able to print output strings from your code, like calling System.out.println() in Java code The Android system will write to LogCat The programmer can also send non-graphical output there
54
These are the lines of code in the application related to logging
import android.util.Log; public class MainActivity extends Activity { private static final String TAG = "OneButtonRecursion"; … Log.i(TAG, "In recursion " + handFullIn);
55
In order to write to LogCat you need to import the Log class
Log contains static methods, like “i”, which stands for “information” (as opposed to println() for System.out) These log methods take two strings as parameters, a tag, and the actual output
56
It’s simplest to just define a TAG so that every line from a given app is clearly identified in the LogCat Then at strategic places put calls to Log.i() to see what’s happening Android Studio has fancier debugging tools, but I’ve always done it by hand in this way
57
An Example On the following overhead is a block of code that gave me a runtime error As noted earlier, the runtime error messages are not always as helpful as they might be You’re not told which line of code caused the runtime error I couldn’t tell what exactly was wrong—it was the highlighted parseInt() call
58
TextView capturedCup = (TextView) activityIn. findViewById(R. id
TextView capturedCup = (TextView) activityIn.findViewById(R.id.textView16); int capturedCount = Integer.parseInt(capturedCup.getText().toString()); capturedCount += seedCount; capturedCup.setText(capturedCount + "");
59
The code on the following overhead shows how I picked the block apart and was able to identify exactly which line and which call was causing the problem
60
/* Debugging code */ /* Log.i(TAG, "1"); TextView capturedCup = (TextView) activityIn.findViewById(R.id.textView16); Log.i(TAG, "2, capturedCup id: " + capturedCup); CharSequence tempText = capturedCup.getText(); Log.i(TAG, "3"); String tempString = tempText.toString(); Log.i(TAG, "4, tempString contents of capturedCup: " + tempString); int capturedCount = Integer.parseInt(tempString); Log.i(TAG, "5"); capturedCount += seedCount; Log.i(TAG, "6"); capturedCup.setText("x"); //(capturedCount + ""); Log.i(TAG, "7"); */
61
Summary and Mission The assignment is to get this to work with two changes: 1. The relative positions of the button and the text view have to be different from what’s given in the example 2. You have to use any number except 4 as the starting value shown on the screen and which the recursion works on You will turn this in at the same time as the rest of Assignment 2
62
The End
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.