To really make use of this module, it is best to download and import the project first. This gives you the ability to navigate in Android Studio and potentially making modifications to the sample program.
To do this, first download FirstShellApp.zip. This is a zip file that contains all the files of the project.
When you are ready to explore the project, unzip the content of this file. This zip file creates its own folder. Remember where you unzip the content.
In Android Studio, click “Open an existing Android Studio project”. This opens a dialog box titled “Open File or Project”. Navigate to the folder created by unzipping the zip file. Have the folder selected, then click OK.
This should open the project.
Now that we have a project open, let’s explore the files. At the top level, an Android project has three types of files under “app”.
The “manifests” files contain meta data of the app itself. It is of great importance when app is to be published. But for now, we are going to skip them.
The “java” files are the source files. These are important files as they contain the Java code that dictate how an app behaves. Specifically, we are going to explore the code in com.example.tauyeung.firstshellapp.
The “res” files are resource files. These files contain data that specifies the static look of the app. We are going to explore activity_main.xml in “layout” in this module.
You can explore this file using the path “FirstShellApp, app, src, main, res, layout, activity_main.xml”. When this file is opened, Android Studio displays a WYSIWYG layout editor. The left pane includes the Palette (components that you can drag into the editing area) and the Component Tree (which component contains which other components).
The middle pane is the main editing area. When a component is clicked, the static properties are displayed in the rightmost pane, the Properties pane. This should look familiar to those who use AppInventor.
The layout of an activity is useful for most apps where labels, buttons, textboxes and other user interface elements are static. The use of a WYSIWYG tool means editing the looks of an activity is simple and intuitive.
For example, if you click on the button, it shows that the ID is “button”, and the text is “Click me!”. Likewise, if you click the label, it shows that the ID is “helloLabel” and the text is “Hello World!”
When an Android app is run, the layout specification of an activity instructs Android (the OS) how to create the elements (like buttons, labels and etc.) Each element is represented by a Java object that is automatically created.
But what if you want to specify what to do with interactive elements like a button? There are several ways.
The easier way is to use the on... properties of interactive elements in the layout. For example, the button in this example has a property of onClick where the value is clickHandler.
clickHandler specifies the name of a method of the activity object that represents this activity (screen). Android Studio does not check (in the layout editor) whether there really is a method called clickHandler. In fact, if no such method is defined, the project still compiles and run until the button is clicked. When the button is clicked, a run-time error is reported stating that the expected method clickHandler is not available.
This means that as a developer, you have to make sure all the interactive elements be tested to make sure there are no missing handlers!
Now let us proceed to “FirstShellApp, app, src, main, java, com, example, tauyeung, firstshellapp, MainActivity”.
Let’s take a close look at this source file.
This line declares that the definition contained in this file is a part of the package “com.example.tauyeung.firstshellapp”.
This line imports the definition of a class AppCompatActivity that enables the use of action bars.
Bundle is a class that handles the serialization of objects so that objects can be turned into strings (for storing or transmission) and then back to objects.
View is a important base class for just about everything that has a visible representation in Android.
TextView is a subclass of View that can display and optionally edit text (string) values.
All the lines beginning with import are necessary only because the imported class is mentioned somewhere within the code. Android Studio does a good job guessing which class to import in editing mode. This is a great feature so that a developer does not need to break concentration to explore the class hierarchy to find out the package containing the needed class definition.
Next, we have a single public class defintion in the following form:
This defines a new class that is based on AppCompatActivity. The main screen (activity) of this simple app is represented by an object of this class. An object of class MainActivity can do everything that an object of class ApopCompatActivity can, and it is do more!
Now we take a look inside the class definition, starting with the overriding deinition of onCreate:
@Override is optional, but it tells the compiler to check whether onCreate is already a member of the class AppCompatActivity. This is good programming practice because a mispelled method name can easily cause problems otherwise.
In this method, the first line makes use of the onCreate method of the super class. This preserves the behavior of this method from the super class.
The second call is unique to this subclass because the layout is specific to this particular activity of this particular app. Essentially, this method definition is saying the following:
“When onCreate is called, do whatever it is supposed to do as defined in the superclass. On top of that, also make use of the layout that is specific to this activity. This includes using the layout definition to create all the necessary components (labels, buttons, etc.) and place them correctly on the screen.”
The next method is not an extension to a method in the superclass. It is a method that handle the event of the button being clicked. The association of this method to the click event is specified in the properties of the button seen earlier.
Let us take a look at this method (it is called when the button is clicked):
The parameter x is a reference to the object that receives the click even. In this case, x is the button on the screen. This is handy if the same handler is shared among multiple screen elements.
label is a local variable of the class TextView. The magic is the call to findViewById.
findViewById is a method inherited along the inheritance stack of AppCompatActivity. Now let us take a close look at the parameter to this call. R.id.helloLabel refers to R, the resource class that is specific to this activity. id is a nested class of R, it includes the definition of integer constants. helloLabel is the ID of the label (TextView) in the screen. In the defintion of R.id, helloLabel is defined as an integer constant.
This call allows an activity locate specific components using the symbolic ID. It returns a reference to a View object, not a TextView object. The run-time cast to TextView is put here because we know this ID corresponds to a TextView object.
If the run-time down-cast is incorrect, a run-time error is generated when this line of code executes.
Once we retrieve the reference to the label (TextView object), we can then use its own method to change the text value.
With Android Studio, this is much simpler than earlier IDEs (integrated development environments). As long as the whole project is self-contained in one folder, Android Studio can open the project.
A class is a template used to create objects. You can look at a class as a cookie cutter, whereas objects are the cookies cut by this cookie cutter. Note how all the cookies cut by the same cookie cutter have the same shape. However, each cookie is independent from others, and each cookie has it own state.
In many ways, you can also see a class as a basic type like int in C/C++ (and Java, of course!). The main difference is that an int variable has predefined operators that apply to it, but an object of a class can only do what the class defines.
In our example, there are no objects! This is because the class MainActivity is used by Android to automatically create the object used to present the activity (screen) when the app starts.
A method is a subroutine defined in a class definition. In our example, onCreate and checkHandler are both methods of the class MainActivity
A method is like a “normal” subroutine, but it also differs in some subtle ways.
First, the visibility of a method is subject to scope control. We will explore this topic in some other modules. The bottomline, however, is that a method may or not may not be visible to methods of another class. One thing is guaranteed, however. All methods defined in one class are visible to all other methods defined in the same class.
This is a key object-oriented programming (OOP) concept that is present in all OOP programming languages. This concept, indeed, is what makes OOP so attractive.
When a class inherits from another class (using the keyword extends), then all methods (and other definitions) of the class that it inherits from become a part of the new class.
In our example, the class MainActivity inherits all the methods from the class AppCompatActivity. The inheriting class is called a “subclass” of the inheritted class. You can also call the inheritted class a “superclass” of the inheriting class.
Using this terminology, MainActivity is the subclass, and AppCompatActivity is the superclass.
Inheritance allows class hierarchies to be defined. As necessary, subclasses extend a superclass in various ways. The best part, however, is that common attributes only need to be defined once.
The Android API (application program interface) has a huge class hierarchy. We will explore many more classes in future modules.
Just about any interactive program makes use of the event driven model. What this means is that the program is in a loop as follows:
Even in this rather simple program, there are two event handlers, not just one!
The obvious one is clickHandler. This method is linked to the onClick event of the button via the button property (visible in the layout editor).
The no-so-obvious one is onCreate. This is an event handler corresponding to the onCreate event. In other words, when an activity (screen) is created (by the Android OS), an event is raised. This makes it easy to attach code to run when an activity is first created.
In our example, the code corresponding to onCreate is automatically generated, and the main purpose is to set the content of the activity according to the activity_main layout specified as a resource.
Because an app is event-driven, what about action games where the screen is constantly getting updated? This is an interesting question, but the answer is somewhat complex. An ordinary Android app has one thread associated with it running the event handling loop mentioned earlier. However, an Android app can have multiple threads. To further complicate things, only one thread is dedicated to handle screen updates, so everything has to funnel to this one thread to actually perform screen updates. Android gaming will be explored in more details in another module.
Note that the layout of an activity is not the only way to specify and create user interface elements. A button can be created dynamically and be displayed using just Java code. However, this approach should be used only as the last resort because the design tool in Android Studio cannot be leveraged this way.
As a beginner, the most daunting part of Android programming is to get familiar with the class hierarchy. There is no quick way around this except to use the class hierarchy web pages a lot. It does not make much sense to try to read all the class definitions in a linear fashion because few people have the memory to actually remmeber the details. It makes far more sense to first have a goal (something to implement) in mind, then look up and learn the necessary information and knowledge to get it done.