Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
69
Dr. Penniel P. Wu
Lecture #3 Java Basics – A Simple “Hit the Zombies” Game
Introduction The previous lecture provided a guided tour to explore the basics of “Android Studio” and
how to use it to create a project to build an Android game application. In this lecture,
students will explore how Java programming skills apply to the making of Android games.
In an Android Studio project, both the “activity_main.xml” and “MainActivity.java” files
are the two core files for developers to work on. In the nutshell, the “activity_main.xml” file
is used to define the appearance of all user interfaces (UIs), while the “MainActivity.java”
file contains Java code to drive the application and control the behaviors of the application.
The following figure illustrates the relationship.
The intersection of XML and Java parts of the project indicates that programmers can write
Java code to dynamically change appearances of the application. The following demonstrates
how to use Java code to change the background color of a Button control with its identifier
being “button1”.
button1.setBackgroundColor(Color.White);
In this lecture, students will work on five learning activities to develop a game named “Hit
the Zombies”.
Java Basics for
Android
As a specialized kind of Java application, an Android Java application can be described as a
collection of objects defined by a Java “class” in order to invoke methods and implement
properties. The term “class” is an official term used by the “object-oriented programming” to
describe a logical container defined by the programmers for member definitions. The term
“members” of a given class are typically made up of “methods” and “properties”. The
following are the basic terms students should be familiar with in order to understand how
Java coding applies to Android programming.
Object – Objects are identifiable items, such as a book, a button, a sprite, or a sound.
An object has states (or appearance) and behaviors. For example, a game sprite has
states including color, name, file size as well as behaviors like moving around the
screen, changing its size, and fighting against an enemy. An object is also described as
an “instance” of a class. The action of creating an instance is known as “instantiation”.
Class – A class is a logical container for defining methods and properties. A class can
also be defined as a template (or a blue print) that describes the behaviors and states for
objects of its type to use.
Android Project
XML Java
class
properties
methods
object 1
object 2
object n
70
Dr. Penniel P. Wu
Methods - A method is basically a code block that defines of a specific behavior. A
class can contain many methods. For example, how an “UFO” object can “fly” from the
ground to the sky is typically defined in a method.
Properties (class variables) – A property of a class is a variable that indicates one
specific state of an object. For example, a variable named “bgcolor” is used to indicate
the background color of an object.
Package. A Java package is a group of similar types of classes, interfaces and sub-
packages. An Android project may consist of two or more individual classes. A
“package” thus packs these individual classes as a single “unit”. In a package, all classes
are “peers” to one another. A significant benefit of “package” is for members of these
classes to easily access members of other “peer” classes. Programmers also typically use
packages to organize classes belonging to the same category or providing similar
functionality. In an Android Java program, a package can also provide a unique
namespace for the data types it contains.
If a package becomes a library, programmers can use the “import” directive to include
classes and/or interfaces contained in that package by “qualifying” their names. In terms of
programming, a library is a collection of pre-built resources for quickly developing new
software. The terms, “qualify a class”, means to specify the full hierarchy (or file structure).
In Android, a class has a hierarchy that starts with a “namespace” name, followed by a
period (.), a “package” name, another period (.), and then the class name. The following
demonstrates how to properly “import” a class (the “TextView” class) using its “qualified
name”, which also depicts the file structure. The structure is: “TextView” is under “widget”,
and “widget” is a child of “android”.
import android.widget.TextView;
An Android project often requires programmers to “import” several resources. For example,
every project must make a reference to the android.app.Activity class to create a default
window. Therefore, the following importing is required.
import android.app.Activity;
Every Android application must have at least one class of the “android.app.Activity” type;
therefore, the Android Studio automatically declares a “MainActivity” class in every
Android project, as shown below. This “MainActivity” class extends the
“android.app.Activity” class, so it is a derived (or subclass) of the “android.app.Activity”
class. In Java, extends is the keyword used to inherit members of a base (or superclass) class.
public class MainActivity extends Activity { }
By the way, Google now encourages to replace the android.app.Activity class with the
“android.support.v7.app.AppCompatActivity” class. According to Google, the new
“AppCompactActivity” is fully compatible to the “android.app.Activity” class with
additional supports on UIs like ActionBar.
import android.support.v7.app.AppCompatActivity;
Throughout this semester, most Android coding project will start with the modification of
the following “MainActivity” class to handle the default activity. Coding an “activity” is the
writing of a Java code that supports a screen or UI. The “MainActivity” class in every
Android application is the entry point of the application. The term “entry point” implies that
it is what the Java virtual machine is looking for to read and start the application when the
application is launched.
public class MainActivity extends AppCompatActivity { }
71
Dr. Penniel P. Wu
In terms of Android, an “activity” is anything a user can interact with the application. The
android.app.Activity class is the base class (or superclass) provided by the Android API as
toolkit to for Android programmers to create a container (known as a “window”) to host all
other user interfaces (UIs), such as Button and TextView controls. In the following figure,
the “MainActivity” creates the default “activity” which has one TextView and one Button
control in it to interact with the user.
This default “activity” is the foundation for building the default user interface (UI), known
as a “View” which is created by the setContentView(View) method. A View is a
rectangular area on the screen that is responsible for drawing and event handling. Every
Android project automatically contains a default View defined in the “activity_main.xml”, as
demonstrated below.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
A properly written Java code can be used to create custom-made View. The following is a
sample Android Java code that create a TextView control as the View. Inside the
“onCreate()” method, the instructor purposely ignores the default View by “commenting
out” the “setContentView(R.layout.activity_main);” statement. In Java, the term
“comment out a line of statement” means to put two slashes (//) at the beginning of a line of
statement to force the compiler to ignore that particular line. The instructor, then, manually
defines a “TextView” (which is a kind of “View”) as the replacement of the default View. A
TextView is also a kind of user interface provided by Android to display text (or message) to
the user and optionally allows users to edit its caption.
package my.labn_m;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
int size; // property
private int reSize() { //method
size = 6;
return size;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textView1 = new TextView(this); // an instance
textView1.setText(reSize()+""); // define content
setContentView(textView1); // define what to display
}
}
MainActivity
textView 1
button1
72
Dr. Penniel P. Wu
By properly “importing” the class, as showing the following statement, the currently
Android project will actually “import” source code from “android.widget.TextView” which
was provided by Android API; therefore, programmers no longer have to write code to
define what a “TextView” is. It is necessary to note that the “qualified name” clearly
instructs the compiler where to obtain the source code from the library.
import android.widget.TextView;
The above statement, on the other hand, also officially introduce the “TextView” class to the
current Android project; therefore, programmers can start to create an instance of the
“TextView” class without the need to define what “TextView” class is. The following
statement illustrates the instantiation, in which “textView1” is the identifier of the object.
The “textView1” object is also an instance of the “TextView” class.
TextView textView1 = new TextView(this);
In terms of Object-Oriented programming, an instance is created by a constructor of the
class. A constructor in Java is a block of code that is designed to be called for execution only
when an instance of a class needs to be created. A constructor shares the identifier with the
class, the only difference is that the constructor name is followed by a pair of parentheses
while the class name is not. The new keyword is a Java operator that creates the object.
During the instantiation, the new operator is followed by a call to a constructor, which
creates the object “textView1”.
Class Name Object Name Assignment keyword Constructor TextView textView1 = new TextView(this)
Another purpose of the above sample code is to demonstrate how to create a property and a
method as members of the “MainActivity” class. As shown below, it creates an integer
variable named size as a property and an integer method named reSize().
int size; // property
private int reSize() { //method
size = 6;
return size;
}
By the way, private is a Java keyword which declares a member’s access as private. That is,
the member is only visible and accessible within the class, not from any other class
(including subclasses). In Java, the visibility of private members can extend to nested
classes. In the following figure, “class 3” is a nested class to “class 1” while “class 2” is a
“peer” to “class 1”. Only “class 1” and “class 3” can access the “resize()” method of “class
1”.
The “reSize()” method is declared as a method of int type, which indicates that it must “give
back” an integer to whatever part of the Java code (the calling party) that calls it for
package 1
class 1
- private int reSize()
Class 2
Class 3
73
Dr. Penniel P. Wu
execution. The return keyword is used to “give back” from a method when its execution is
complete. When a return statement is reached in a method, the program passes a value to the
code that invoked it. When declaring the type of a method, programmers must decide
whether the method should “give back” a value. If the choice is not to return a value, the data
type must be “void”. The following is a sample “void” method. It does not “give back” any
value to its calling party.
void showResult()
{
textView1.setText("Winning!");
}
The purpose of the following line is to call the reSize() method to receive the value of the
size variable passed by the return keyword.
textView1.setText(reSize()+"");
Since textView1 is the object that will display the text on the screen, it should be associated
with the setText() which is a method provided by Android API to set the text (or caption) for
the TextView to display. The text is a specified string. Interestingly, according to the
Android API, the setText() method only accepts a String value as parameter.
setText(string)
There is a “data type conflict” between the reSize() method and the setText() method. The
reSize() method returns only int type of data, while the setText() method accepts only String
type of value as parameter. In Java, any data type, when combined with a pair of double
quotes ("") becomes a String type, as shown below. The plus sign (+), in this case, is the
“concatenation” operator, not the arithmetic “addition” operator. The term “concatenation”
literally means to merge two or more pieces of data together to form a new single String
data. A pair of double quotes without any character in them indicates a “blank” character.
Students will exercise this coding technique throughout the entire course.
reSize() + ""
One simple way to distinguish what roles the plus sign (+) plays in a statement is to check
the data type of its two operands. If both operands are numeric values, the plus sign (+) is the
addition operator; otherwise, it is used as the “concatenation” operator.
(3.5 + 4.1242) // addition
(3.5 + "4.1242") // concatenation
This section discussed the “MainActivity” class and how to use it to create class members,
such as properties and methods to be used by other code segments. In the next several
sections, students will review Java programming basics.
Data Types and
Variable
Declaration
A data type of a value in a programming language is an attribute that tells the computer
what kind of data that value can be. For instance, number of persons in a group must be
integers only because a person cannot be split in pieces (or avatars) to join different groups.
Before a piece of data can be recognized and processed by a computer, the data must be
“officially” introduced to the computer by a program. The process of introduction a data to
the computer is known as “declaration”. The following depicts the syntax for declaring a
variable.
DataType VariableName;
In programming, it is necessary to specify that “number of persons” can only be integers, as
shown below. The keyword int indicates that it is a piece of data of int type (integer), while
74
Dr. Penniel P. Wu
“numberOfPersons” is the identifier the instructor chose to describe the variable. The term
“variable” refers to an area of physical memory that will be allocated by the operating
system to hold the data. The “identifier” of the variable is the name that represent the
allocated memory area for the sake of identification.
int numberOfPersons;
The price of a product, as those in a U.S. retail store, are not always whole numbers, such as
12.95. They have fractional parts. It is necessary to declare such data as float or double
because they support fractional values. Technically speaking, the word “double” means
twice the memory size of the float type. Currently, Java float type is a single-precision 32-bit
floating-point type, while double is a double-precision 64-bit floating-point type.
float price;
Answers to a question like “Are you a human?” can only be either Yes or No (True or
False), but not both. It is better to declare such kind of data as boolean, which is a data type
that allows only two possible values: True or False. Some programming languages choose to
use 1 and 0 to represent True and False.
boolean answer;
Most programming languages supports primary data types including integer, floating point
unit number, character, string, and pointer. The Android API supports most of the standard
Java primitive data types. The following table lists the most commonly used data types.
Table: Android (Java) Primitive Data Types
Type Contains Default Size Range int Signed integer 0 32 bits -2147483648 to 2147483647 float floating point 0.0 32 bits ±1.4E-45 to ±3.4028235E+38
double floating point 0.0 64 bits ±4.9E-324 to
±1.7976931348623157E+308
String Combination of
characters NULL - -
char Unicode
character \u0000 16 bits \u0000 to \uFFFF
byte Signed integer 0 8 bits -128 to 127 boolean true or false false 1 bit NA
It is necessary to note that the Java String type is a special type of data designed to hold a
combination of characters; however, the Java String type is a class and not a primitive data
type.
After declaring a variable, programmer can assign a value to the variable using the
assignment operator (=). The following depicts the syntax. The equal sign (=), in this case,
does not check if both side of party are equivalent to each other. Instead, it simply tells the
computer “value is the value of variableName”.
variableName = value;
Programmers can choose to declare a variable in one statement, and then assign a value to it
in another statement. In the following example, declaration and value assignment are two
individual statements. Throughout this course, the instructor will demonstrate this technique
to declare “global” variables. In computer programming, a global variable is the one that is
meant to be accessible by any part of the program without restriction. A detailed discussion
is available in the “Scope and Access Control” section.
75
Dr. Penniel P. Wu
String gameTitle;
..........
gameTitle = "Zombie 3";
Often, programmers will choose to declare and assign an initial value in one single
statement, as shown below.
String gameTitle = "Zombie 3";
The following statement declares and creates a variable named “increment” of float type, and
then assign 0.05f as initial value. In Java, value of float type must end with a “f” or “F”
suffix.
float increment = 0.05f;
The following is another example that declares and creates a variable of int type with an
initial value of 26.
int imgWidth = 26;
The following is a simple program that demonstrates how to declare integer variables and
assign their initial values. It is necessary to note that the setText(parameter) function only
accept String values as its parameter. A parameter is a value in a method (or function) that
is passed to the method for further processing. Both x and y are declared as variables of int
type. Their values, after the addition operation (x+y), still produce a value of int.
Programmers needs to convert the int type to String type in order for the setText() method to
accept the value. In Java, anything that combines with an empty character ("") automatically
becomes a String literal. A literal in Java is a value with specified data type.
Package my.labn_m; // n and m are numbers
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
int x = 5; // declare and assign initial value
int y = 7;
tv.setText((x+y) + ""); // convert an integer to string setContentView(tv);
}
}
In the above code, (x+y) is an expression that describe how to operate on two values to
produce a new one. The plus sign (+), in this case, is the addition operator. In programming,
an expression is a well-constructed code unit consisting of variables, operators, and/or
method invocations, and must be constructed according to the syntax of the language, in
order to produce a single value.
Operators Throughout this course, students will frequently use four categories of “operators”:
arithmetic, increment/decrement, relational (comparison), and logical operators.
76
Dr. Penniel P. Wu
An arithmetic operator is a built-in program that takes two operands and performs a
calculation on them, particularly in addition, subtraction, multiplication, division, and
modulus calculation.
Table: Java Arithmetic Operators
Operator Symbol Example Result
Addition + 5 + 3 8
Subtraction - 5 - 3 2
Multiplication * 5 * 3 15
Division / 5/3 1
Modulus % 5%3 2
It is necessary to note that the expression, (5/3), actually produces 1 as result in Java. This
is because Java operates data based on the data type. Both 5 and 3 are int type (which
indicates they must be integer), so the result of operation must return a value of the same
data type. In programming, integer division produces an integer rather than rational result; it
truncates to the decimal representation of the rational result. The expression, (5.0/3.0),
will produce the expected rational result because both 5.0 and 3.0 are floating-point type of
data.
In programming, the percentage sign (%) has a different definition. It represents the
“modulus” operator. The modulus operator (%) is also known as remainder operator
because it returns the remainder of two numbers as the result of an integer division. For
instance, 10 % 3 is 1 because 10 divided by 3 leaves a remainder of 1.
Programmers often take advantages of the modulus operator to simplify a complicated
situation. The following is an example that can form a good programming logic to determine
if a given year is a leap year.
If year % 4 = 0, then it's a leap year
if a year % 100 and if year % 400 = 0, then it's a leap year
if a year % 100 and if year % 400 != 0, then it's not a leap year
else, it's not a leap year
The following is a sample pseudocode written based on the above logic.
if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)
y is a leap year
else
y is not a leap year
The above pseudocode uses one of the rational operator, the “equal to” operator (==).
Relational operators are operators that test or evaluate relation between two operands to
return a Boolean result: True or False. They are often used in Java expressions to make basic
decisions.
Table: Relational Operators
Operators Description Example Results == Equal to 3 == 3 true
!= Not equal to 3 != 5 true
> Greater than 3 > 5 false
>= Greater than or equal to 3 >= 5 false
< Less than 3 < 5 true
<= Less than or equal to 3 <= 5 true
77
Dr. Penniel P. Wu
It is necessary to distinguish the “equal to” operator (==) with the “assignment” operator (=).
In programming, it takes two consecutive equal signs (==) to denote the “equal to” operator.
The assignment operator is the one that has only one equal sign (=).
Increment (++) and decrement (—) operators in Java programming are designed to add 1
to, or subtract 1 from its operand. They are used as a shortcut to modify the value stored in a
variable and access that value.
Table: Increment and Decrement Operators
Operator Example Equivalence Description ++ x++ x = x + 1 Adds 1 to the current value of x. -- x-- x = x - 1 Subtract 1 from the current value
of x. += x += 3 x = x + 3 Adds 3 to the current value of x. -= x -= 3 x = x - 3 Subtract 3 from the current value
of x. *= x *= 3 x = x * 3 Multiply 3 with the current value
of x.
The addition assignment operator (+=) adds the value of an expression to the value of a
variable and assigns the result to the variable. The subtraction assignment operator (-=)
subtracts the value of an expression from the value of a variable and assigns the result to the
variable. The multiplication assignment operator (*=) multiplies the value of a variable by
the value of an expression and assigns the result to the variable.
In the following example, the “multiply assign” operator (*=) combines multiplication with
assignment operations, and force its left operand to multiply itself with 1.1.
imageView1.getLayoutParams().width *= 1.1;
imageView1.getLayoutParams().height *= 1.1;
Logical operators are typically used with Boolean (logical) values to produce one Boolean
value as result.
Operator Description Example && AND x < 40 && y > 90
|| OR x < 0 || x > width
! NOT !x > 0
The logical AND operator (&&) performs a logical conjunction on two expressions. The
operation returns true only if both operands are true; otherwise, it returns false. The logical
OR operator (||) performs a logical disjunction on two expressions. If either or both
expressions evaluate to True, result is True. The logical NOT operator (!) performs logical
negation on an expression.
In the following example, the getLayoutParams() method will get the value of the “width”
property from “imageView1” and assigns that value to a variable “imgWidth” of int type.
Then, the OR (||) operator will evaluate a hybrid expression which consists of two individual
expressions: imgWidth >= (w * 0.9) and imgWidth < 26.
int imgWidth = imageView1.getLayoutParams().width;
......
(imgWidth >= (w * 0.9) || imgWidth < 26)
78
Dr. Penniel P. Wu
In the following example, x is 5, so (x<=4) is False. However, the NOT (!) operator is used
to check if the expression is “Not” False. Since the entire expression, !(x <=4), is actually
not False, the result is True.
int x = 5;
.......
!(x <= 4)
Array Game programming frequently use arrays to manipulate game data. An array is a collection
of items that all have something in common. The commonality is what you need to use to
group them in an array. By using an array variable, which store more than one possible value
as element to a variable, you can avoid creating many variables for similar type of data. Each
possible value of an array is known as an element. The sequence of an element is indicated
by an index. The following illustrates the syntax:
DateType[] arrayName;
arrayName = new DataType[size]
where,
dataType is a keyword that actually represents a data type, such as int, float, or String;
arrayName is the identifier given to the array;
size is the total number of elements allowed; and
new is the Java keyword that actually creates the array.
The following declares an array of float type with an identifier (or name) “body_weight”.
float[] body_weight;
Declaration alone cannot create the array; the following uses the “new” keyword to actually
create the array. It also specifies that the array can only host 5 elements.
body_weight = new float[5];
The term “size” (or “length”) refers to the total allowed number of elements of an array. If
an array is said to have a “size” of 5, then it can only host 5 elements. The value of index
typically starts at 0, not 1.
Throughout this course, students will frequent declare, create, and populate arrays. For
example, the following declares an array named x that will be used to store three zombies’ x-
coordinates in a game.
int[] x;
After declaration, the following uses the “new” keyword to create the array that can host no
more than 3 elements.
x = new int[3];
To “populate” and array means to actually create elements of the array. The “new” keyword
can build an abstract “container” for the array to host elements, but it does not create the
elements. Programmer must use the following syntax to populate elements.
arrayName[index] = value;
The index of element are integers starting at 0 and ending at size-1. In the case of x array, the
first element is x[0], the second is x[1], and the third is x[2]. The following illustrates how to
populate these three elements.
79
Dr. Penniel P. Wu
Sprite Index x-coordinate Populating elements
Zombie1 0 10 x[0] = 10;
Zombie2 1 25 x[1] = 25;
Zombie3 2 40 x[2] = 40;
The following is the syntax for retrieving value from a populated element.
arrayName[index]
The following is an example that attempts to retrieve the value of x[0]. Parameter of the
setText() method must be a String type, therefore, the instructor concatenate x[0] with a
blank character.
textView1.setText(x[0] + "");
A complete sample code is:
package my.labn_m; // m and n are
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textView1 = new TextView(this);
int[] x = new int[3];
x[0] = 10;
x[1] = 25;
x[2] = 45;
textView1.setText(x[1]+"");
setContentView(tv);
}
}
If the size of an array is small, you can declare an array and its containing elements in a
single line. This is a “short-hand” way to create an array. For example,
double[] d = {3.1, 2.6, 7.5};
The following is the short-hand way to create a String array.
String[] arrayOfString = {"A", "B", "C", "D"};
You can create a jagged array in Android. For example,
int[][] x = { { 3, 4, 5 }, { 77, 50 }};
A jagged array is an array whose elements are arrays. The elements of a jagged array can be
of different dimensions and sizes. A jagged array is sometimes called an "array of arrays."
The following examples show how to declare, initialize, and access jagged arrays.
If you need to handle both x- and y-coordinates of three zombie sprites, you can declare a
jagged array. For example, (10, 5), (25, 15), and (40, 35).
int[][] zombie = new int[3][2];
80
Dr. Penniel P. Wu
zombie[0][0] = 10;
zombie[0][1] = 5;
zombie[1][0] = 25;
zombie[1][1] = 15;
zombie[2][0] = 40;
zombie[2][1] = 35;
Or, simply
int[][] zombie = {{10, 5}, {25, 15}, {40, 35}};
The if Statements A decision structure is a fundamental control structure in game logics. The if..else statement
is the most fundamental decision structure. The following illustrates the syntax, which
includes optional “else if” segments. All the “else if” segments are on-demand segments,
they are added only when they are deemed necessary.
if (condition) {
// execute only when condition is true
}
else if (condition2) {
// execute only when condition2 is true
}
............
else if (conditionn) {
// execute only when conditionn is true
}
else {
// execute when all conditions are false
}
To build an if structure, the “if” part is absolutely needed, in which the condition must be a
Boolean expression that only produces one of the two possible values: True or False. In the
following example, the expression, imgWidth < 26, is either True or False. Interestingly,
the “else” can be omitted unless it is needed to make the decision-making process more
complete.
if (imgWidth < 26)
{
imageView1.getLayoutParams().width = 26;
imageView1.getLayoutParams().height = 31;
}
The following is a complete code that illustrates how to use the if..else statement. The
condition is defined by an expression, (3>5). When (3>5) is evaluated to be True, the
message to display in a ”TextView” is “Correct!”; otherwise, it displays “Incorrect!”.
package my.lab0_1; // m and n are
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
String msg=""; // blank
if (3>5) { msg = "Correct!"; }
81
Dr. Penniel P. Wu
else { msg = "Incorrect!"; }
tv.setText(msg);
setContentView(tv);
}
}
The following is an example that use if..else if..else statement with String as a switch
statement in Java example source code. If also demonstrates how to call a function (or
method) that returns a value to its calling party (e.g.). Notice that the equals() method of
java.lang.Object acts the same as the == operator; that is, it tests for object identity rather
than object equality. The implicit contract of the equals() method, however, is that it tests for
equality rather than identity.
package my.labm_n; // m and n are numbers
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText(getLevel("A")); // call getLevel() function
setContentView(tv);
}
private String[] arrayOfString = {"A", "B", "C", "D"};
public String getLevel(String level)
{
String str = "You entered " + level + "\n";
if (arrayOfString[0].equals(level)) str += "Level A";
else if (arrayOfString[1].equals(level)) str += "Level B";
else if (arrayOfString[2].equals(level)) str += "Level C";
else if (arrayOfString[3].equals(level)) str += "Level D";
else str += “Invalid request!!!”;
return str;
}
}
The above code uses a layered if statement. It also depicts that the pair of { and } is optional
in Java coding. However, throughout this course, the instructor prefers using curly bracket to
enclose code segments.
if (condition1) { }
else if (condition2) {}
else if (condition3) {}
........
else {}
Conditions in an if structure can be hybrid expressions. The following is a sample, excerpted
from Learning Activity #2, that uses a hybrid expression. The “imgWidth” variable holds the
value of the “layout_width” property of a given ImageView. The hybrid expression consists
of two expressions: imgWidth >= (w * 0.9) and imgWidth < 26. These two
82
Dr. Penniel P. Wu
expressions are operands of an OR (||) operator. By the way, the variable “w” in the
following code holds the width of the device screen.
if (imgWidth >= (w * 0.9) || imgWidth < 26) {
...............
}
The switch..case
Statement
The switch..case statement is another decision structure. The switch Statement allows for
any number of possible execution paths. An if..then..else statement can be used to make
decisions based on ranges of values or conditions, whereas a switch statement can make
decisions based only on a single integer or enumerated value. The syntax is:
switch(position)
{
case 0: statement; break;
case 1: statement; break;
case 2: statement; break;
........
case n: statement; break;
default:
}
The position of a switch can be int, short, char, and other primitive data types. The break
statement after each case terminates the enclosing switch statement. The break statements
are necessary because without them, case statements fall through; that is, a situation known
as “case hopping” which means the control will flow sequentially through subsequent case
statements without an explicit break.
The optional default section is used to handle “un-defined” cases, which occurs when a
value given to position that cannot be matched with all the defined cases. In this above,
example, -1 is an “un-defined” case. By the way, the “default” case is always placed as the
last case; therefore, whether or not to have a “break” statement to terminate its section is also
optional.
The following is a sample code, excerpted from Learning Activity #4, to randomly select an
image file in the “drawable” subdirectory of “R” for the “imageView1” to load.
Random rnd = new Random();
int n = rnd.nextInt(6);
...............
int rid = 0;
switch (n)
{
case 0: rid = R.drawable.zombie1; break;
case 1: rid = R.drawable.zombie2; break;
case 2: rid = R.drawable.zombie3; break;
case 3: rid = R.drawable.zombie4; break;
case 4: rid = R.drawable.zombie5; break;
case 5: rid = R.drawable.zombie6; break;
}
.................
imageView1.setImageResource(rid);
The following is an example that shows how a switch..case statement are used to determine
key events. When the left arrow key () is pressed, the Boolean variable “handled” is set to
be true. When the right arrow key () is pressed, “handled” is set to be false. When any
other key is pressed, “handled” is also set to false.
83
Dr. Penniel P. Wu
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
super.onKeyDown(keyCode, event);
boolean handled = true;
// handle key presses
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT:
handled = true; break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
handled = false; break;
default:
handled = false; break;
}
return handled
}
By the way, in Java, @Override is used to mark methods that override a method declaration
in a superclass. Compilers produce an error if a method annotated with @Override does not
actually override a method in a superclass.
Repetition
structure
The for statement provides a compact way to iterate over a range of values. Programmers
often refer to it as the “for loop” because of the way in which it repeatedly loops until a
particular condition is satisfied. The general form of the for statement can be expressed as
follows:
for (initialization; termination; increment) {
statement(s)
}
When using this version of the for statement, keep in mind that:
The initialization expression initializes the loop; it will only execute once at the moment
when the looping begins.
When the termination expression evaluates to False, the iteration (looping) terminates.
The increment expression is invoked after each iteration. When the increment is based
on a negative value, it is known as decrement.
The following is a sample for loop. The variable i serves as a “counter” of iterations. The
initial value of i is set to be 0. The termination expression is (i<9), which means the value of
i must be less than 9. It is necessary to note that i is a variable of int type whose initial value
is 0. Both the initiation and termination expressions collaboratively specify that the value of
i can only be 0, 1, 2, …, and 8 with an increment of 1.
for (int i=0; i<9; i++) { }
The following is another example of for loop. Its initial value of counter variable i is 5,
terminal value is 50 because of the expression (i<=50), and its increment is 5. This for loop
progresses in a “skip counting” mode from 5, 10, 15, to 45, 50.
for (int i=5; i<=50; i+=5) { }
The following demonstrates the use of decrement, and the decrement is -1.
for (int i=12; i>3; i--) { }
The following is the sample code that demonstrates how a for loop works.
84
Dr. Penniel P. Wu
package my.lab0_1; // m and n are
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
int[][] zombie = new int[3][2];
zombie[0][0] = 10;
zombie[0][1] = 5;
zombie[1][0] = 25;
zombie[1][1] = 15;
zombie[2][0] = 40;
zombie[2][1] = 35;
String str = "";
for (int i=0; i<3; i++)
{
str += zombie[i][0];
}
tv.setText(str);
setContentView(tv);
}
}
The while statement continually executes a block of statements while the termination
expression is True. Its syntax can be expressed as:
initiation
while (termination) {
statement(s)
increment
}
The while statement evaluates expression, which must return a boolean value. If the
expression evaluates to true, the while statement executes the statement(s) in the while
block. The while statement continues testing the expression and executing its block until the
expression evaluates to false. The following is a simple example, the counter variable i is set
to start at 3, the termination expression (i<15) sets the last possible value to be 14, and the
increment is 1. Consequently, the value of i can only be 3, 4, 5, …, and 14.
int i=3;
while (i<15) {
// statements
i++;
}
The following is another example. Its first possible value is 0, the last possible value is 20
because (i<25), and the increment is 5. All the possible values of i are 0, 5, 10, 15, and 20.
int i=0;
85
Dr. Penniel P. Wu
while (i<25) {
// statements
i+=5;
}
The following demonstrates how a while loop handles decrement.
int i=9;
while (i>=0) {
// statements
i--;
}
The following is the sample code that demonstrates how a while loop works.
package my.labn_m; // m and n are
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
int[][] zombie = {{10, 5}, {25, 15}, {40, 35}};
String str = "";
int i=0;
while (i<3)
{
str += zombie[i][0];
i++;
}
tv.setText(str);
setContentView(tv);
}
}
Pre-built Methods With Android Studio, application developers create new projects and modify the
“MainActivity.java” files with custom-made Java code. These Java code usually utilize “pre-
built methods” provided by the Android SDk. The term “built-in” mean they are methods
created by the programming team of the Android SDK for all other application developer to
use. In the following sample statement, setText() is a method provided by the Android SDK.
textView1.setText("Zombie 3");
The “findViewById()” method is another frequently used pre-built method, which is
provided by the Android SDK.
ImageView imageView1 = (ImageView)
findViewById(R.id.imageView1);
The Android SDK contains many classes with each provide different sets of methods. A
class is defined by a set of declaration statements and members, including properties,
86
Dr. Penniel P. Wu
methods, and constructor. Class properties in Java are typically variables. The term method
is adapted by the object-oriented programming to describe a block of well-arranged
statements to perform a special task. Constructors are special kind of methods that only
create instances of the class. Throughout this course, students will use many pre-built
methods to retrieve resources.
The following example use the getLayoutParams() method to access properties of the
LayoutParams object associated with a specified ImageView. The
android.view.ViewGroup.LayoutParams class provides members to specify layout of a
View. Both “width” and “height” are two parameters that specify how wide and how tall the
view has to be.
imageView1.getLayoutParams().width *= 1.1;
imageView1.getLayoutParams().height *= 1.1;
The “multiply assign” operator (*=) combines multiplication with assignment operations,
and force its left operand to multiply itself with right operand. In the above example, both
“width” and “height” parameters of the “imageView1” are forced to enlarge by 1.1 fold. The
above code can create a “Zoom In” visual effect of an image, while the following can create
a “Zoom Out” visual effect. Learning Activity #1 will demonstration of such technique.
imageView1.getLayoutParams().width *= 0.9;
imageView1.getLayoutParams().height *= 0.9;
According to Android SDK, the requestLayout() method must be called to re-initiate (or
refresh) a layout, as shown below. This method is typically called by a view on itself when it
believes that is can no longer fit within its current bounds.
imageView1.requestLayout();
The following demonstrates how to set the Activity title by getting a string from the
Resources object. It also demonstrates how to get an instance of Resources with
Context.getResources() method. The getWindow() method retrieves the current Window
for the activity (such as the “MainActivity”). The getText() method retrieves the caption (or
value of the “text” property) of a resource.
getWindow().setTitle(getResources().getText(R.string.main_title));
The following programmatically assigns an image from a drawable resource as background
to the current screen. getWindow().setBackgroundDrawableResource(R.drawable.bg);
In order to detect and respond to user activities (such as the “onClick” event), Androids SDK
provide many “listener” methods that can detect the occurrence of an event. In terms of
programming, an “event” is an action perform by a user, such as pressing a key, clicking a
button, touch an object on the screen. In terms of Java programming, a “listener” is a
mechanism (typically a method) provided by the Java language as a class (or interface) to
detect whether or not a demanded event occurs. The following demonstrates how to create a
View.OnClickListener object and assign it to the button by calling
setOnClickListener(View.OnClickListener) in order to declare the event handler
programmatically.
Button button1 = (Button) findViewById(R.id.button_send);
Button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Do something in response to button click
87
Dr. Penniel P. Wu
}
});
When a player clicks the “button1” control, the “setOnClickListener()” method will detect
the event and immediately call the “onClick()” method to respond to the event.
Programmers must override the “onClick()” method by adding Java code to specify the
response actions.
A later lecture will discuss about the concept of Java “listener” in details.
User-defined
functions
The “MainActivity.java” file in essence is a Java class that is specially tailored to fit in the
Android environment. Therefore, programmers can make add named blocks of statements to
the “MainActivity” class as custom-made members. Interestingly, when the programmer has
to organize a set of statement in a named block, the entire block is known as a “user-defined
function”. However, it is probably appropriate to say that a “user-defined function” is a
custom-made “method” of a Java class. Both “method” and “user-defined functions” must be
called for execution. They are not executed automatically.
A named block, in Java, must stick to the following syntax. The block of statements must be
enclosed by { and }.
dataType functionName() { statements }
where,
dataType can be any of the recognized data type such as int, float, char, and String as
well as the “void” type;
functionName is a unique identified given by the programmer as the name of the code
block; and
statements are lines of Java code that can perform a task.
The following is a function named “getImage()” that will send a value of int to its calling
party. In Java, the “return” keyword is used to return a value.
int getImage(int n)
{
int rid = 0;
.........
return rid;
}
It is necessary to note the “void” type. In Java, a function of “void” type is one that does not
return anything to its calling party. The following is a sample “void” function, excerpted
from Learning Activity #2. The “reSizeImage()” function simply perform the designated
task, but it does not return anything to its calling party.
reSizeImage(-0.1f); // call the function and pass a value
................
................
void reSizeImage(float increment) { // function
imageView1.getLayoutParams().height *= (1 + increment);
imageView1.getLayoutParams().width *= (1 + increment);
imageView1.requestLayout();
}
The content of the “reSizeImage()” function (as demonstrated in Learning Activity #2) is
also part of the content of “button1” and “button2” (Learning Activity #2) as shown below.
Apparently, organizing repeating code as an individual function is an efficient way to make
Java code “reusable”.
88
Dr. Penniel P. Wu
// Zoom in
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
increment = 0.1f;
imageView1.getLayoutParams().height *= (1 + increment);
imageView1.getLayoutParams().width *= (1 + increment);
imageView1.requestLayout();
}
});
// Zoom out
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
increment = -0.1f;
imageView1.getLayoutParams().height *= (1 + increment);
imageView1.getLayoutParams().width *= (1 + increment);
imageView1.requestLayout();
}
});
For API 17 and higher, programmer can call the Display.getRealSize() method to obtain the
real size of the display. Interestingly, the actual size may be smaller than the physical size of
the screen when the window manager is emulating a smaller display. The two variables of int
type, w and h, are used to temporarily how the value of screen dimension.
import android.view.Display;
.........
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getRealSize(size);
int w = size.x;
int h = size.y;
The instructor organizes the above code as a “void” type of “user-defined function” name
“showDisplaySize()”. Therefore, whenever the application needs to re-obtain the screen
dimension (after a rotation from Portrait to Landscape orientation), the values of w and h can
be updated by calling the “showDisplaySize()” function. Learning Activity #2 demonstrates
how the “showDisplaySize()” function works.
int w, h;
...........
void showDisplaySize()
{
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getRealSize(size);
w = size.x;
h = size.y;
}
Prior to the API Level 17, programmers will have to use the following code snippet to obtain
the actual screen width and height from an activity (such as the "MainActivity").
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
89
Dr. Penniel P. Wu
display.getSize(size);
int w = size.x;
int h = size.y;
Scope and Access
Control
In programming, scope of a variable or a method defines the accessibility of them. In other
words, scope restricts where a variable or a method is accessible.
public class MainActivity extends AppCompatActivity {
int cnt = 0; // a member of MainActivity class
protected void onCreate(Bundle savedInstanceState) {
int noOfImages = 0; // a member of onCreate
..............
noOfImages = cnt; // access cnt
}
void countZombies()
{
cnt = query("android.view.ImageView").count;
}
}
The use of android.os.Handler class to manipulate a Java “Runnable” object is a good
example of scope. The following code, excerpted from Learning Activity #3, declares and
instantiate a Handler object outside the “Runnable” object. Therefore, the “run()” method
(which resides inside the Runnable object) can access the Handler object. A Java “Runnable”
represent a task in Java which is executed by Thread. A Thread in Java is an independent
flow of execution in a program that perform a specific task. Since a "thread" is independent,
it can be started, paused, and stopped by the program it resides any time.
Handler handler1 = new Handler();
..........
Runnable runnable = new Runnable() {
@Override
public void run() {
.........
handler1.postDelayed(this, 1000);
}
};
handler1.postDelayed(runnable, 1000);
A later lecture will discuss in details about the how to use “Thread” in Java. In this lecture,
the above code is used to create a “timer” that sets a delay of 1000 milliseconds (which is 1
second) before the next execution. The above code, once launched, will also repeat the same
task every 1 second. The instructor uses the above code to resize an image every second to
create a visual effect that the image is moving towards the player. Learning Activity #3 will
demonstrate how such visual effect works.
References https://developer.android.com/guide/topics/resources/accessing-resources.html
http://www.programcreek.com/java-api-
examples/index.php?class=android.widget.ImageView&method=getLayoutParams
Review Question 1. Given the following statement, which is NOT correct?
public class MainActivity extends AppCompatActivity { }
A. "MainActivity" is a Java class that inherits "AppCompatActivity".
90
Dr. Penniel P. Wu
B. "AppCompatActivity" is a superclass.
C. "MainActivity" class can use members of the "AppCompatActivity" class.
D. The "AppCompatActivity" class can use members of the "MainActivity" class.
2. In which of the following, the word "size" is possibly the identifier of a method of a Java
class?
A. int size;
B. int size() { }
C. size = 100;
D. return size;
3. Assuming "textView1" is a variable of the "TextView" type in Android Studio, which can
display the correct result of an arithemetic expression (5 - 2) using the setText() method?
A. textView1.setText(5 - 2);
B. textView1.setText(5 - 2 + "");
C. textView1.setText((5 - 2) + "");
D. textView1.setText("(5 - 2)");
4. What is the result of x after the following statements?
int x = 5;
x--;
A. 6
B. 5
C. 4
D. 3
C
5. Given the following statement, which is the third element of "zombie" array?
String[] zombie = new String[5];
A. zombie[1]
B. zombie[2]
C. zombie[3]
D. zombie[4]
6. Which is not the correct way to declare a variable in Android Java programming?
A. String size = "12";
B. int size; size = 12;
C. int size = "12";
D. String size; size = "12";
7. Given the following code, Android emulate should display __.
if (3>5) { msg = "Correct!"; }
else { msg = "Incorrect!"; }
A. Correct!
B. Incorrect!
C. Correct!Incorrect!
D. Incorrect!Correct!
8. Given the following code, Android emulate should display __.
91
Dr. Penniel P. Wu
if (3>5 || 3<5) { msg = "Correct!"; }
else { msg = "Incorrect!"; }
A. Correct!
B. Incorrect!
C. Correct!Incorrect!
D. Incorrect!Correct!
9. Given the following code segment, in which condition will the "zombie4.png" file in the
"res/drawable" folder be loaded?
switch (n)
{
case 0: rid = R.drawable.zombie1; break;
case 1: rid = R.drawable.zombie2; break;
case 2: rid = R.drawable.zombie3; break;
case 3: rid = R.drawable.zombie4; break;
case 4: rid = R.drawable.zombie5; break;
case 5: rid = R.drawable.zombie6; break;
}
A. n = 2;
B. n = 3;
C. n = 4;
D. n = 5;
10. Given the followng code, zombie[1][0] is __.
int[][] zombie = {{10, 5}, {25, 15}, {40, 35}};
A. 10
B. 5
C. 25
D. 15
92
Dr. Penniel P. Wu
Lab #3 Java Basics – Hitting Zombie Game
Preparation #1: Download lab file
1. Create a temporary, “C:\temp”, if it does not exist.
2. Download the zombie.zip file to the C:\temp directory, and then extract all its content to the C:\temp directory.
Learning Activity #1: Data type and basic operators
1. Launch the Android Studio (as you did in the previous labs).
2. In the tool bar, click “File”, and then “New Project…”
3. In the “Create New Project” window, enter the followings. Then, click Next.
Application name: Lab3_1
Company Domain: Misato
Project location: X:\AndroidStudioProjects\Lab3_1
(where X is the drive name)
4. Click Next on the “Target Android Devices” window.
5. Select “Empty Activity” on the “Add an Activity to Mobile” window, and then click Next.
6. Click Finish on the “Customize the Activity” window.
7. Use Windows Explorer to copy only the “zombie.png” file to the
“X:\AndroidStudioProjects\Lab3_1\app\src\main\res\drawable” directory (“X” is the drive
name).
8. Click the “app” folder to expand it. Click the “java” sub-folder to expand it. Click the project name to expand it.
Finally, double click the “MainActivity” file to open it in the editor mode.
93
Dr. Penniel P. Wu
9. In the project panel, click the “activity_main.xml” tab once. Click the “Design” tab at the bottom of
“Component Tree” to display the “design view”.
10. In the “Palette”, drag down the veil.
to
11. On the “design view”, right-click the “TextView” that displays “Hello World!”, select “Delete” from the menu
as shown below to remove it.
12. On the “Palette”, click the “Layouts” category, and then drag one “LinearLayout (vertical)” to the “Component
Tree” and place it under the “ConstraintLayout”. Make sure the “LinearLayout (vertical)” is a child of
“ConstraintLayout”, as shown below.
design view
Palette
Component Tree
Desgin tab
activity_main.xml tab
94
Dr. Penniel P. Wu
13. Drag two “LinearLayout (horizontal)” to the “Component Tree” and place them under the “LinearLayout
(vertical)”, as shown below.
14. From the “Palette”, drag two “Button” controls to the “Component Tree” and place them under the first
“LinearLayout (horizontal)”, as shown below. Change their “ID” properties to “button1” and “button2”. Change
their “text” properties to “Zoom In” and “Zoom Out”.
15. On the “Palette”, click the “Images” category. Drag in an “ImageView” control to to the “Component Tree” and
place it under the second “LinearLayout (horizontal)”. The “Resources” window will pop up.
16. In the “Resources” window, select the “zombie” image and click OK.
17. Change the “ID” property of the “ImageView” control to “imageView1”. It is necessary to remember that
values of “ID” (which is short for “identifier”) is case-sensitive.
18. Click the “activity_main.xml” tab once, and then click the “Text” tab at the bottom of the editor window to
change to the editing view.
95
Dr. Penniel P. Wu
19. In the “activity_main.xml” file, manually set the “layout_height” of the first “LinearLayout (horizontal)” to
60dp.
........
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Zoom In" />
........
20. In the “activity_main.xml” file, manually change the “layout_width” property to 26dp and “layout_height” to
32dp. Make sure the “activity_main.xml” file reflects the changes.
<ImageView
android:id="@+id/imageView1"
android:layout_width="26dp"
android:layout_height="32dp"
android:layout_weight="1"
app:srcCompat="@drawable/zombie" />
21. The layout should look similar to the following.
22. In the “MainActivity.java” file, change the Java code to the following.
package misato.lab3_1;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Button;
96
Dr. Penniel P. Wu
public class MainActivity extends AppCompatActivity {
ImageView imageView1; // declare a variable of ImageView type
float increment = 0.1f; // declare and create a float type of variable
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView1 = (ImageView) findViewById(R.id.imageView1); //instantiation
// Zoom in
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
increment = 0.1f;
imageView1.getLayoutParams().height *= (1 + increment);
imageView1.getLayoutParams().width *= (1 + increment);
imageView1.requestLayout();
}
});
// Zoom out
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
increment = -0.1f;
imageView1.getLayoutParams().height *= (1 + increment);
imageView1.getLayoutParams().width *= (1 + increment);
imageView1.requestLayout();
}
});
}
}
23. In the tool bar, click the Run () button to test the application. Click “Zoom In” and “Zoom Out” buttons. A
sample output looks:
24. Capture a screen shot(s) similar to the above, and paste it/them to the lab3.doc (or .docx) document.
25. Copy the “app-debug.apk.” file to a temporary directory and rename it to “lab3_1.apk”.
Learning Activity #2: function
1. Create a new Android Stuio project with an “Empty Activity” named “lab3_2” with the following
specifications:
Application name: Lab3_2
97
Dr. Penniel P. Wu
Company Domain: Misato
Project location: X:\AndroidStudioProjects\Lab3_2 (where X is the drive name)
2. Use Windows Explorer to copy only the “zombie.png” file to the
“X:\AndroidStudioProjects\Lab3_2\app\src\main\res\drawable” directory (“X” is the drive
name).
3. Repeat all steps of Learning Activity #1, except the Java code in the “MainActivity.java” file. Change the Java
code in the “MainActivity.java” file to the following.
package misato.lab3_2;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
ImageView imageView1;
float increment = 0.1f;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView1 = (ImageView) findViewById(R.id.imageView1);
// Zoom in
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
reSizeImage(0.1f);
}
});
// Zoom out
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
reSizeImage(-0.1f);
}
});
}
void reSizeImage(float increment) {
imageView1.getLayoutParams().height *= (1 + increment);
imageView1.getLayoutParams().width *= (1 + increment);
imageView1.requestLayout();
}
}
4. In the tool bar, click the Run () button to test the application. Click “Zoom In” and “Zoom Out” buttons A
sample output looks:
98
Dr. Penniel P. Wu
5. Capture a screen shot(s) similar to the above, and paste it/them to the lab3.doc (or .docx) document.
6. Copy the “app-debug.apk.” file to a temporary directory and rename it to “lab3_2.apk”.
Learning Activity #3: if..else structure and automatically refreshing
1. Create a new Android Stuio project with an “Empty Activity” named “lab3_3” with the following
specifications:
Application name: Lab3_3
Company Domain: Misato
Project location: X:\AndroidStudioProjects\Lab3_3 (where X is the drive name)
2. Use Windows Explorer to copy only the “zombie.png” file to the
“X:\AndroidStudioProjects\Lab3_3\app\src\main\res\drawable” directory (“X” is the drive
name).
3. Repeat all steps of Learning Activity #2, except the Java code in the “MainActivity.java” file. Change the Java
code in the “MainActivity.java” file to the following.
4. In the “MainActivity.java” file, change the Java code to the following.
package misato.lab3_3;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.os.Handler;
import android.view.Display;
import android.graphics.Point;
public class MainActivity extends AppCompatActivity {
ImageView imageView1;
float increment = 0.05f;
int w = 0;
int imgWidth = 26;
Handler handler1 = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView1 = (ImageView) findViewById(R.id.imageView1);
imageView1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
reSet();
}
99
Dr. Penniel P. Wu
});
showDisplaySize(); // get the width of the screen
Runnable runnable = new Runnable() {
@Override
public void run() {
imgWidth = imageView1.getLayoutParams().width;
if (imgWidth >= (w * 0.9) || imgWidth < 26) {
increment = increment * -1;
}
if (imgWidth < 26)
{
reSet();
}
reSizeImage(increment);
handler1.postDelayed(this, 100);
}
};
handler1.postDelayed(runnable, 100);
}
void showDisplaySize()
{
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
w = size.x;
}
void reSizeImage(float increment) {
imageView1.getLayoutParams().height *= (1 + increment);
imageView1.getLayoutParams().width *= (1 + increment);
imageView1.requestLayout();
}
void reSet()
{
imageView1.getLayoutParams().width = 26;
imageView1.getLayoutParams().height = 31;
}
}
5. In the tool bar, click the Run () button to test the application. The image enlarges and then shrinks
automatically. A sample output looks:
100
Dr. Penniel P. Wu
6. Capture a screen shot(s) similar to the above, and paste it/them to the lab3.doc (or .docx) document.
7. Copy the “app-debug.apk.” file to a temporary directory and rename it to “lab3_3.apk”.
Learning Activity #4:
1. Create a new Android Stuio project with an “Empty Activity” named “lab3_4” with the following
specifications:
Application name: Lab3_4
Company Domain: Misato
Project location: X:\AndroidStudioProjects\Lab3_4 (where X is the drive name)
2. Use Windows Explorer to copy “zombie1.png”, “zombie2.png”, “zombie3.png”, “zombie4.png”,
“zombie5.png”, and “zombie6.png” files to the
“X:\AndroidStudioProjects\Lab3_4\app\src\main\res\drawable” directory (where X is the drive
name).
3. On the “design view”, right-click the “TextView” that displays “Hello World!”, select “Delete” from the menu
as shown below to remove it.
4. On the “Palette”, click the “Layouts” category, and then drag one “LinearLayout (vertical)” to the “Component
Tree” and place it under the “ConstraintLayout”. Make sure the “LinearLayout (vertical)” is a child of
“ConstraintLayout”.
5. Drag two “LinearLayout (horizontal)” to the “Component Tree” and place them under the “LinearLayout
(vertical)”.
6. From the “Palette”, drag on “TextView” control to the “Component Tree” and place it under the first
“LinearLayout (horizontal)”. Change the “ID” property of the TextView to “textView1”. Change its “text”
property to “Hit Number: “.
7. On the “Palette”, click the “Images” category. Drag in an “ImageView” control to to the “Component Tree” and
place it under the second “LinearLayout (horizontal)”. The “Resources” window will pop up.
8. In the “Resources” window, select the “zombie1” image and click OK.
9. Change the “ID” property of the “ImageView” control to “imageView1”. It is necessary to remember that
values of “ID”.
10. In the “MainActivity.java” file, change the Java code to the following.
101
Dr. Penniel P. Wu
package misato.lab3_4;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.os.Handler;
import android.view.Display;
import android.graphics.Point;
import android.widget.TextView;;
public class MainActivity extends AppCompatActivity {
TextView textView1;
ImageView imageView1;
float increment = 0.05f;
int w = 0;
int imgWidth = 26;
int n = 0;
int hit = 0;
Handler handler1 = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView1 = (TextView) findViewById(R.id.textView1);
imageView1 = (ImageView) findViewById(R.id.imageView1);
imageView1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
hit++; // increment
textView1.setText("Hit Number: " + hit);
reSet();
}
});
imageView1.setImageResource(getImage(n));
showDisplaySize(); // get the width of the screen
Runnable runnable = new Runnable() {
@Override
public void run() {
imgWidth = imageView1.getLayoutParams().width;
if (imgWidth >= (w * 0.9))
{
reSet();
}
reSizeImage(increment);
handler1.postDelayed(this, 10);
}
};
102
Dr. Penniel P. Wu
handler1.postDelayed(runnable, 10);
}
void showDisplaySize()
{
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
w = size.x;
}
void reSizeImage(float increment) {
imageView1.getLayoutParams().height *= (1 + increment);
imageView1.getLayoutParams().width *= (1 + increment);
imageView1.requestLayout();
}
int getImage(int n)
{
int rid = 0;
switch (n)
{
case 0: rid = R.drawable.zombie1; break;
case 1: rid = R.drawable.zombie2; break;
case 2: rid = R.drawable.zombie3; break;
case 3: rid = R.drawable.zombie4; break;
case 4: rid = R.drawable.zombie5; break;
case 5: rid = R.drawable.zombie6; break;
}
return rid;
}
void reSet()
{
imageView1.getLayoutParams().width = 26;
imageView1.getLayoutParams().height = 31;
n = n + 1;
imageView1.setImageResource(getImage(n%6));
}
}
11. In the tool bar, click the Run () button to test the application. Zombies will take turn to approach the player.
The player needs to tap on the enlarging image to earn credits. A sample output looks:
12. Capture a screen shot(s) similar to the above, and paste it/them to the lab3.doc (or .docx) document.
103
Dr. Penniel P. Wu
13. Copy the “app-debug.apk.” file to a temporary directory and rename it to “lab3_4.apk”.
Learning Activity #5: for loop and array
1. Create a new Android Stuio project with an “Empty Activity” named “lab3_5” with the following
specifications:
Application name: Lab3_5
Company Domain: Misato
Project location: X:\AndroidStudioProjects\Lab3_5 (where X is the drive name)
2. Use Windows Explorer to copy “nozombie.png”, “zombie1.png”, “zombie2.png”, “zombie3.png”,
“zombie4.png”, “zombie5.png”, and “zombie6.png” files to the
“X:\AndroidStudioProjects\Lab3_5\app\src\main\res\drawable” directory (“X” is the drive
name).
3. Remove the existing “Hello World!” TextView.
4. From the “Palette”, drag a “TableLayout” to the “Component Tree” and place it under the “ConstraintLayout”
as a child. The “TableLayout” contains four “TableRow”.
5. In the “Component Tree”, click first “TableRow” and change its “ID” property to “row1” , as shown below.
Click the second “TableRow” and change its “ID” property to “row2”. Change the rest to “row3” and “row4”.
6. From the “Palette”, drag one “TextView” control to the “Component Tree” and place it under “row1
(TableRow)” as a child to “row1”. Change the “ID” propert to “textView1”.
7. Click the “row2 (TableRow)” to select it. Add three “ImageView” controls to the “row2 (TableRow)”, as shown
below. Set their default images to “zombie1”, “zombie2”, and “zombie3”. Set their “ID” properties to
“imageView1”, “imageView2”, and “imageView3”.
104
Dr. Penniel P. Wu
8. The layout on the “design view” should now look similar to the following.
9. Click the “row3 (TableRow)” to select it. Add three “ImageView” controls to the “row3 (TableRow)”, as shown
below. Set their default images to “zombie4”, “zombie5”, and “zombie6”. Set their “ID” properties to
“imageView4”, “imageView5”, and “imageView6”.
10. Make sure to “design view” look similar to the following.
11. In the “activity_main.xml” file, add the following “layout_marginBottom” attribute to the “textView1”.
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:layout_marginBottom="25px" />
12. In the “MainActivity.java” file, change the Java code to the following.
package misato.lab3_5;
105
Dr. Penniel P. Wu
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.ImageView;
import android.os.Handler;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
TextView textView1;
// declare and create array of ImageView type
ImageView[] img = new ImageView[6];
int imgVId; // temp id for ImageViews
int hit, miss;
int selected_img = 0;
Random rnd = new Random();
Handler handler1 = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView1 = (TextView) findViewById(R.id.textView1);
//populate array elements
img[0] = (ImageView) findViewById(R.id.imageView1);
img[1] = (ImageView) findViewById(R.id.imageView2);
img[2] = (ImageView) findViewById(R.id.imageView3);
img[3] = (ImageView) findViewById(R.id.imageView4);
img[4] = (ImageView) findViewById(R.id.imageView5);
img[5] = (ImageView) findViewById(R.id.imageView6);
for (int i=0; i<img.length; i++)
{
img[i].setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
switch (view.getId())
{
case R.id.imageView1: imgVId = 0; break;
case R.id.imageView2: imgVId = 1; break;
case R.id.imageView3: imgVId = 2; break;
case R.id.imageView4: imgVId = 3; break;
case R.id.imageView5: imgVId = 4; break;
case R.id.imageView6: imgVId = 5; break;
}
checkResult(imgVId);
}
});
}
Runnable runnable = new Runnable() {
@Override
public void run() {
reSet();
handler1.postDelayed(this, 1000);
106
Dr. Penniel P. Wu
}
};
handler1.postDelayed(runnable, 1000);
}
int getImage(int n)
{
int rid = 0;
switch (n)
{
case 0: rid = R.drawable.zombie1; break;
case 1: rid = R.drawable.zombie2; break;
case 2: rid = R.drawable.zombie3; break;
case 3: rid = R.drawable.zombie4; break;
case 4: rid = R.drawable.zombie5; break;
case 5: rid = R.drawable.zombie6; break;
}
return rid;
}
void reSet()
{
for (int i=0; i<img.length; i++) {
img[i].setImageResource(R.drawable.nozombie);
}
selected_img = rnd.nextInt(6);
img[selected_img].setImageResource(getImage(selected_img));
}
void checkResult(int vid)
{
if (vid == selected_img) { hit++; }
else { miss++; }
textView1.setText("Hit: " + hit + " Miss: " + miss);
reSet();
}
}
13. In the tool bar, click the Run () button to test the application. One of the 6 zombies will randomly jump out.
Tap on the zombie to earn credits. A sample output looks:
14. Capture a screen shot(s) similar to the above, and paste it/them to the lab3.doc (or .docx) document.
15. Copy the “app-debug.apk.” file to a temporary directory and rename it to “lab3_5.apk”.
Submittal
1. Compress ONLY the following files to a .zip file named lab3.zip.
lab3_1.apk
107
Dr. Penniel P. Wu
lab3_2.apk
lab3_3.apk
lab3_4.apk
lab3_5.apk
Lab3.doc (or lab3.docx)
2. Submit only the .zip file as response to Question 11.
Programming Exercise #03
1. Create a new Android project named “ex03”.
2. Use the Learning Activity #5 as a guideline to create an Android application that will have the following
layout in the design view.padding, as shown below.
3. When being played, one of the 9 zombie will randomly jump out. The play must hit the zombie to earn credit.
4. Capture a screen shot similar to the above figure and then paste it to a Word document named “ex03.doc”
(or .docx).
5. Compress the executable (ex03.apk) and the Word document (ex03.doc or .docx) to a .zip file named
“ex03.zip”.
6. Upload ONLY the .zip file.