Download XAndroid5Wari

Document related concepts
no text concepts found
Transcript
Android 5: Wari
1
2
Introduction
• This set of overheads is more than just Wari
• It 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
• It is also a lead-in to the code for Wari
3
• Wari illustrates both code logic and a more
complicated layout
• There are two perspectives on what’s going on:
• First of all, it should be apparent that things are
easier because GUI layout work is separate from
the Java code
• On the other hand, in order to deal with this
separation between logic and layout, the
implementation of Wari will differ significantly
from implementations you’ve seen before
4
•
•
•
•
•
•
•
•
5.1
5.2
5.3
5.4
5.5
5.6
5.7
5.8
The OneButtonRecursion app
Unhelpful Error Messages
Logging Output
Wari—General Remarks
layout.xml for Wari
strings.xml for Wari
R.java for Wari
MainActivity.java for Wari
5
5.1 The OneButtonRecursion app
• 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. Look at R.java, the resources as made
available by the system
• 4. MainActivity.java, the code for the app
6
• As you might guess, part of what makes the
app interesting is the fact that it includes
recursion
• This is a preview of the fact that recursion will
be used in the implementation of Wari
7
• The other thing that makes the app
interesting, and relevant to Wari, is that the
contents of the text view are changeable, and
are treated as an integer
• This introduces some syntax, which in turn,
introduces the possibility of errors
• These errors turn out to be runtime errors, so
it behooves us to consider the topic of
debugging in Android
8
activity_main.xml for
OneButtonRecursion
• A screenshot of the layout of the
OneButtonRecursion app in the development
environment is shown on the following
overhead
• It is a simple layout, containing a button and a
text view
9
10
• This app happens to use relative layout
• There is nothing particularly striking about the
syntax for that
• The XML code for the layout is given on the
following overheads for reference
11
•
•
•
•
•
•
•
•
•
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
12
•
<Button
•
android:id="@+id/button1"
•
style="?android:attr/buttonStyleSmall"
•
android:layout_width="wrap_content"
•
android:layout_height="wrap_content"
•
android:layout_alignParentLeft="true"
•
android:layout_alignParentTop="true"
•
android:text="@string/button1Contents"
• android:onClick="sendMessage" />
13
•
•
•
•
•
•
•
•
•
•
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/button1"
android:layout_alignBottom="@+id/button1"
android:layout_toRightOf="@+id/button1"
android:text="@string/textView1Contents" />
</RelativeLayout>
14
• There were some items in the XML that
haven’t come up before
• Where did they come from?
• If you use the graphical tools to create the
basic layout, the system will generate the XML
• You can then edit the XML, if necessary, to
tailor the layout to the specific app you’re
trying to create
15
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
16
•
•
•
•
•
•
•
•
•
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string
<string
<string
<string
<string
name="app_name">One Button Recursion</string>
name="action_settings">Settings</string>
name="hello_world">Hello world!</string>
name="button1Contents">Button1</string>
name="textView1Contents">4</string>
</resources>
17
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
18
•
•
•
•
•
•
•
•
•
•
•
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;
19
MainActivity.java for
OneButtonRecursion
• 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()
20
• 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
21
• 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
22
• The logic is simple, but the code will look
needlessly complex
• 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
23
• 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 mindless recursion
program with only one text view and one
button
24
• Then, in 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
25
An Import and a Declaration and
Initialization for Debugging
• The import of the Log class and the TAG string definition
shown here will be useful for logging and debugging
• They come at the beginning of the MainActivity class, so they
are shown now
• Further explanations will be given later
•
import android.util.Log;
•
public class MainActivity extends Activity {
•
private static final String TAG = "OneButtonRecursion";
•
…
26
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
• The concept of activities is important and will
be pursued further in later sets of overheads
27
•
•
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
{
}
}
28
playNextCup() for OneButtonRecursion
• playNextCup() contains the recursive call
• It also contains the uses of Log and TAG
• These will be explained in a moment
29
•
•
•
•
•
•
•
•
•
•
•
•
•
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
{
}
}
30
5.2 Unhelpful Error Messages
• 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
Eclipse—they’re beyond the scope of this course
• I’m referring to simply figuring out what was
going on
31
• Compiler errors are shown at the bottom of
the screen under the “Problems” tab, and
they’re marked in red there and flagged in
your code
• You will find that Eclipse has a helpful “Quick
Fix” tool that frequently tells you pretty clearly
what’s wrong and how to fix it
• These things are illustrated on the following
overhead
32
33
• I also got two good (bad) examples with
OneButtonRecursion of what can go more
seriously wrong and the quandary you’re left
in
• These were runtime errors, and they
illustrated two features of the development
environment
34
• 1. In Java programming, you may be used to
the fact that even runtime errors show the
line numbers in your code where the errors
occur
• This does not appear to be the case with
Android
• You do see a trace of calls, but it’s up to you to
figure out where that trace intersects your
code and the exact location of the problem
35
• 2. The second aspect accounts for the
heading of this section
• Like with many systems, the error messages
are not necessarily helpful
• As usual, being able to look the error message
up on the Web was very helpful in trying to
figure out what it meant
36
Example 1
• Here is a snippet of code that’s in error:
•
•
•
int handFull = Integer.parseInt(cup.getText().toString());
…
cup.setText(handFull);
• Here is the error message you get:
• No package identifier when
getting value for resource number
HideousHexValue
37
• This is not helpful
• It seems to suggest some deep problem with
the use of resources (like the values in R.java)
or maybe with passing parameters, like the
activity, around
• It doesn’t identify which method call is the
source of the problem
38
• The explanation turns out to be much simpler
• When writing the incorrect code, I heedlessly
assumed that setText() converted whatever
parameter was sent to it to a string by an
internal call to toString()
• This is not so
• There is a version of setText() which accepts
an integer parameter, where the integer is the
id for a resource
39
• 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)
40
• 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 + “”);
41
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
42
• If you write the code as shown and the text
view you’re getting the string from doesn’t
contain an integer
• You will get this runtime error message:
•
FATAL EXCEPTION: main java.lang.IllegalStateException
• It sounds grievous, doesn’t it?
43
• The tracing of calls that’s presented eventually
reaches the parseInt() call, but it’s not
immediately apparent what it is about that
call that’s causing such a serious problem
• The error message obviously doesn’t tell you
something simple, like the parameter passed
to the method isn’t right
44
• This kind of problem is the result of simple
carelessness in coding
• A runtime error can be avoided by careful coding
or by putting the call in a try catch block
• As a garden variety programmer, I made the
mistake
• Because the error message wasn’t helpful, I had
to sort this out with old fashioned debugging, the
topic of the next section
45
5.3 Logging Output
• A screenshot of the current example is shown
on the following overhead
• The playNext() method is shown in the editor
• The LogCat tab has been selected at the
bottom
• This shows the non-graphical output of the
app
46
47
• 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
48
• 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);
49
• 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
50
• 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
• Eclipse has fancier debugging tools, but I’ve
always done it by hand in this way
51
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
52
•
TextView capturedCup = (TextView)
activityIn.findViewById(R.id.textView16);
•
int capturedCount =
Integer.parseInt(capturedCup.getText().toString());
•
capturedCount += seedCount;
•
capturedCup.setText(capturedCount + "");
53
• 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
54
•
•
•
/* Debugging code
/*
Log.i(TAG, "1");
•
TextView capturedCup = (TextView) activityIn.findViewById(R.id.textView16);
•
Log.i(TAG, "2, capturedCup id:
•
CharSequence tempText = capturedCup.getText();
•
Log.i(TAG, "3");
•
String tempString = tempText.toString();
•
Log.i(TAG, "4, tempString contents of capturedCup:
•
int capturedCount = Integer.parseInt(tempString);
•
Log.i(TAG, "5");
•
capturedCount += seedCount;
•
Log.i(TAG, "6");
•
capturedCup.setText("x"); //(capturedCount + "");
•
•
Log.i(TAG, "7");
*/
*/
" + capturedCup);
" + tempString);
55
5.4 Wari—General Remarks
56
Wari in CSCE 202
• Obviously, the point of using Wari as an
example is that it needs no introduction
• For those who didn’t take CSCE 202 from me,
go to the link for that course on my Web page
for full information
• May the tutelary deities of Wari be your guide
57
58
59
• You may recall these characteristics of the
implementation of Wari in CSCE 202
• There was a Cup class
• The board consisted of an array of cups
• Each cup contained a reference to the next
cup, so they were linked together in circular
fashion, the way play progressed around the
board
60
• The cups also had text fields
• In assembling the overall graphical user
interface for the application, the text fields
belonging to the cups were presented in
panels on the screen
• The design was approaching a model-viewcontroller design, but it’s true that
components were still tightly integrated
61
• In Java, with the information given in CSCE
202, it was not so hard to simply create a
“dead” graphical user interface, with all of the
visual components displayed on the screen
but no functionality
• The purpose of this brief review is remind you
of the issues of layout, design, and
functionality as they were introduced when
working with Java swing
62
Wari in Android
• As you have already seen, although based on Java
code, the tools for Android app design are
different
• This is a simple description of the plan for
developing Android apps:
• Using widgets, develop a graphical layout
(activity_main.xml)
• Acquire handles on these widgets through R.java
• Use these widgets in your Java code,
MainActivity.java
63
• The widgets and their layout are separately
defined in their own XML file
• They have a life of their own independent of
the MainActivity.java source file
• In other words, there’s been no indication so
far that an Android version of Wari would
mimic the straight Java implementation
64
• Although it may be possible, there’s been no
consideration of the following:
• Constructing arrays of widgets
• Devising application classes where instance
variables of those classes are widgets
• Trying to link widgets or objects containing them
together
• In fact, you can do swing-like things in an Android
app, but it is not the default approach, and it can
be counterproductive
65
• The goal of the Wari example given in this set
of overheads is to implement roughly the
same functionality as the swing version in Java
• But the intention is not to try and duplicate
the earlier implementation, where the game
logic and the graphical view were integrated
into the same Java code
66
• The goal is to take the default Android approach
and implement the same functionality while
leaving the widgets as independent graphical
items in the interface
• The implementation will still use buttons for play
• This introduces another Android constraint:
• There will be one sendMessage() method for the
app
• It will handle clicks from all of the buttons in the
GUI
67
Implementation Approach
• The fundamental beginning step in Wari is
picking a cup to play
• If the cup contains seeds, you then move to
the next cup
• The description so far implies that in the
Android app, the widgets representing the
cups won’t be linked
68
• If the cups aren’t linked together by
references, how can you implement moving
from one cup to another in this way?
• The cups can be linked together functionally,
by logic in the method that is called when a
button is clicked to play a cup
69
• The method needs to identify the cup that
was clicked
• The method code will contain a sequence of
if/else if statements that encapsulate this
logic, hardcoding the id’s of the cups:
• If you’re on cup x, the next cup is y; else if
you’re on cup y, the next cup is z; and so on,
all the way around the board
70
• You can progress around the board as far as
needed and no further by doing recursion on
the value of handFull that you pick up in the
first cup
• (Note the similarity with simple example given
earlier)
• The stopping condition is easy and natural:
• When the handFull is empty (== 0) you’re
done
71
Coming Attractions
• This unit contains the first assignment, where
you’re expected to implement something
Wari-like as an Android app
• In the following sections, further explanations
will be given of how to do this, some example
code will be shown, but complete code will
not be given or posted
72
• It will be up to you to fill in the missing spaces
and get it to work
• I know it can be done because I did it
• The incomplete example work you’re being
shown consists of selections from the code of
a working app
73
5.5 layout.xml for Wari
• Step 1: Create a layout that presents a Wari-like
interface with the necessary components
• I used buttons for play and text views to hold the
contents of cups
• I decided to use a table layout
• Android has something called a grid layout, but
it’s not exactly the same as a Java grid layout
• The Android table layout is similar to a Java grid
layout
74
• I decided that it would be helpful to use the
graphical tools in Android rather than trying to
master the XML syntax
• This was not trouble-free
75
• More than once I had to start over and create
components in a different order so that the
default names they received would be
consistent with the logic of their use in my
code
• There were 12 buttons and 12 text views in
the layout
• I wanted them numbered 1-12 in the order
they would be played in the game
76
• I also discovered that my machine was
underpowered or something
• Some of the tools caused my system to crash
• The main lesson there was don’t touch those
tools
• I tried to upgrade to a different machine, but
it was impossible to install the Google driver,
so I was stuck with the lesser of two evils
77
• The following overhead shows a screenshot of
my layout in the development environment
• I’m showing you this in order to remind you of
the graphical tools
• My layout consisted entirely of text view and
small buttons
• Notice that among the tools is an option to
choose a layout
• This is where I found the table layout
78
79
• The following overheads show the XML code
that was generated up through the first row of
the table layout
• The full file goes on at length
• This is where you can check to see what
default names your widgets are being given
• They are numbered in creation order
• Your code doesn’t have to be the same, but it
will at least be similar
80
•
•
•
•
•
•
<?xml version="1.0" encoding="utf-8"?>
<!-- This is the activity_main.xml file for Wari. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/androi
d"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
•
•
•
•
•
<TextView
android:id="@+id/textView13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/textView13Contents" />
•
•
•
•
•
<TextView
android:id="@+id/textView14"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/textView14Contents" />
81
•
•
•
•
•
•
•
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
•
•
•
•
•
•
•
<Button
android:id="@+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button1Contents"
android:onClick="sendMessage" />
•
•
•
•
•
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/textView1Contents" />
82
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
<TextView
android:id="@+id/filler1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/filler" />
<TextView
android:id="@+id/textView12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/textView12Contents" />
<Button
android:id="@+id/button12"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button12Contents"
android:onClick="sendMessage" />
83
5.6 strings.xml for Wari
• Creating a strings.xml file for an app isn’t too
difficult
• Largely you can just copy the layout.xml file as
your starting point and then edit it
• It already contains all of the named items that
were created in the layout that are referred to
in strings.xml
• The first step is deleting all of the layout
specific stuff surrounding these names
84
• In strings.xml you give these named items
initial values
• You replace the stuff you removed with the
right syntax for a strings.xml file
• You can also add any other strings necessary
for your app
• A subset of the code for strings.xml for Wari is
shown on the following overhead
85
•
•
<?xml version="1.0" encoding="utf-8"?>
<resources>
•
•
•
•
•
<string
<string
<string
<string
…
•
•
•
<string name="textView1Contents">4</string>
<string name="textView2Contents">4</string>
…
•
<string name="filler">"
•
</resources>
name="app_name">Wari</string>
name="action_settings">Settings</string>
name="button1Contents">P1, C1</string>
name="button2Contents">P1, C2</string>
"</string>
86
• What I’m saying is that you start with something like this:
•
•
•
•
•
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/textView1Contents" />
• And you use it as the starting point to make this, for example:
• <string name="textView1Contents">4</string>
87
5.7 R.java for Wari
• As you recall, R.java is auto-generated
• If your layout and strings files were complete,
R.java will have everything you need in it
• The point is that when writing the code for
MainActivity.java, you refer to R.java
• A subset of R.java is shown on the following
overhead
88
•
•
•
•
•
•
•
•
•
•
…
public final class R {
…
public static final class id {
public static final int
action_settings=0x7f080028;
public static final int button1=0x7f080003;
public static final int button10=0x7f080013;
public static final int button11=0x7f08000d;
public static final int button12=0x7f080007;
public static final int button2=0x7f080009;
89
5.8 MainActivity.java for Wari
• There is nothing special about the onCreate() and
onCreateOptionsMenu() methods for Wari
• They’re just copied as usual
• There’s also nothing unusual about the imports
• Some need to be added so that the code can
work with various classes, but they won’t be
detailed
• The logic of the app is in the sendMessage() and
playNextCup() methods
90
sendMessage() for Wari
• As always, sendMessage() is the method
called on a button click
• This is critically important to this application:
• Each of the 12 buttons in Wari is linked to the
one sendMessage() method
91
• This goes back to a discussion that occurs at
the end of CSCE 202
• You may recall that it’s possible to have one
event and many listeners
• It’s also possible to have many events and one
listener
92
• You may also recall that in the development of
Wari in swing, the possibility of having a
listener full of if statements was mentioned in
passing and rejected as not the ideal solution
• We have now come full circle
• sendMessage() is like a common listener for
clicks on multiple different buttons
93
• sendMessage() determines which button was
clicked
• There is then a series of if statements
• In each if statement, effectively the same logic
is implemented
• The different cases only differ by which
button/cup/next cup are involved
94
• Not only is this method the one listener for all of
the buttons
• This is the part of the app code that creates the
functional connection between the different,
independent widgets in the app
• In other words, sendMessage() functionally
implements the structure of the game board
• The sendMessage() method calls the
playNextCup() method, which implements the
logic of playing the game
95
• The if/else if code in sendMessage() is highly
redundant
• No claim is made that this is the ideal solution
• It is presented as a quick and dirty approach
which is relatively easy to understand in the
context of Android widgets
• The redundancy actually makes it easy to write
• You just copy and paste and change the numbers
identifying the buttons and cups
96
• The first two if cases for the sendMessage()
method are shown on the following overhead
• The full method just continues the pattern
• If you need more knowledge in order to
understand what’s going, you’ll have to figure
it out
• In other words, this is part of what you’ll do
for the assignment
97
•
•
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("0");
playNextCup(this, (TextView) findViewById(R.id.textView2),
handFull);
}
}
else if(clickedButton == findViewById(R.id.button2))
{
TextView cup = (TextView) findViewById(R.id.textView2);
int handFull = Integer.parseInt(cup.getText().toString());
•
•
•
•
•
•
•
•
•
•
•
•
•
if(handFull > 0)
{
cup.setText("0");
playNextCup(this, (TextView) findViewById(R.id.textView3),
handFull);
}
}
…
98
• There is one last thing to mention because it’s
a segue into an important aspect of the
playNextCup() method, which will be the next
topic
• Note the calls to findViewById()
• This has come up before, but it bears
repeating:
• These calls are floating in space
99
• When the app runs, an instance of the
MainActivity class is what’s running on the
Dalvik Virtual Machine
• The calls on the implicit parameter are on this
activity, the MainActivity
• This is relevant to playNextCup() and the
concept is important overall and will be
discussed in greater depth in the future
100
playNextCup() for Wari
• playNextCup() is the method that’s called if a
player clicks a cup that is not empty
• It is a recursive method that jumps to the next
cup in line
• Each successive recursive call jumps to the
succeeding cup on the board
• Seeds continue being dropped in each cup
until handFull is empty
• This is the condition that ends the recursion
101
• playNextCup() is redundant, like
sendMessage()
• Just like in sendMessage(), it’s necessary to
know which cup is being played
• Which is the next cup is determined by which
is the current cup
• Since the cups are found by their id, there has
to be a separate case for each of the 12 cups
on the board
102
• Again, the fact that the code is redundant
actually makes it relatively easy to write
• Figure out one of the cases
• Then copy and paste and change the numbers
identifying the cups
103
• The code for this method does have an
additional characteristic that needs to be
brought out
• It’s already evident in the signature line, which
is shown here:
• public static void
playNextCup(Activity activityIn,
TextView cupIn, int handFullIn)
104
• Not only does the logic of play and recursion require
that the cup and handFull be passed in
• The first parameter passed to the method is an activity
• If you go back to sendMessage(), the calls look like this,
for example:
• playNextCup(this, (TextView)
findViewById(R.id.textView3),
handFull);
• The activity that is passed in is the MainActivity
105
• Passing in this parameter supports calls like these
in the body of the method:
• activityIn.findViewById(R.id.textView1)
• findViewById() is called on the activity
• findViewById() was also called on the activity in
sendMessage(), but it was a call floating in space
• It wasn’t necessary to make the call on “this”
106
• In playNextCup() you will get a compiler error
if you don’t pass in the activity so you can call
findViewById() on it
• This is the message:
• “Cannot make a static reference to the nonstatic findViewById(int) from the type
Activity”
107
• This error message is more helpful than the ones
previously looked at
• playNextCup() is a recursive method which is
declared static
• The error message is telling you that in a static
method there is no “this”, there is no object,
which findViewById() can be called on
• Therefore, in order to make the implementation
work, you have to pass in MainActivity when
making the call to playNextCup()
108
• The first two if cases for the playNextCup()
method are shown on the following overheads
• The full method just continues the pattern
• If you need more knowledge in order to
understand what’s going, you’ll have to figure
it out
• In other words, this is just like sendMessage()
• Doing this is part of what you’ll do for the
assignment
109
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
public static void playNextCup(Activity activityIn, TextView cupIn, int
handFullIn)
{
handFullIn--;
if(cupIn == activityIn.findViewById(R.id.textView1))
{
TextView nextCup = (TextView) activityIn.findViewById(R.id.textView2);
int seedCount = Integer.parseInt(cupIn.getText().toString());
seedCount++;
cupIn.setText(seedCount + "");
if(handFullIn != 0)
{
playNextCup(activityIn, nextCup, handFullIn);
}
else if(seedCount == 2 || seedCount == 3)
{
TextView capturedCup = (TextView)
activityIn.findViewById(R.id.textView14);
int capturedCount =
Integer.parseInt(capturedCup.getText().toString());
capturedCount += seedCount;
capturedCup.setText(capturedCount + "");
}
}
110
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
else if(cupIn == activityIn.findViewById(R.id.textView2))
{
TextView nextCup = (TextView)
activityIn.findViewById(R.id.textView3);
int seedCount =
Integer.parseInt(cupIn.getText().toString());
seedCount++;
cupIn.setText(seedCount + "");
if(handFullIn != 0)
{
playNextCup(activityIn, nextCup, handFullIn);
}
else if(seedCount == 2 || seedCount == 3)
{
TextView capturedCup = (TextView)
activityIn.findViewById(R.id.textView14);
int capturedCount =
Integer.parseInt(capturedCup.getText().toString());
capturedCount += seedCount;
capturedCup.setText(capturedCount + "");
}
}
…
111
Summary and Assignment
•
•
•
•
The summary is simple: Can you do this?
The assignment is equally simple: Do this.
Implement Wari or Togiz Kumalak
You get to choose the number of cups per side
and the initial number of seeds per cup, as
long they are >= 6 and 4, respectively
112
• You will turn this in by demonstrating your app to
me on your tablet or whatever Android device
you’ve decided to develop on
• You can come to my office to do this
• You can do it any time on or before the due date
• I’m begging you, please, don’t push this beyond
the due date
• I make this humble entreaty because it’s for your
own good…
113
The End
114