MEIC/MERC 2015/2016
Mobile and Ubiquitous Computing
Lab Guide 1
Introduction to Android
Objectives:
- Introduction to Android application development.
- Familiarization with Android development tools: Android Studio and Gradle.
Material:
Exercise I – Hello World
Implement a Hello World application which renders the two activities shown in Figure 1. The left-hand side activity is shown when the app is started, and displays a textbox and a "Send" button. When the user types a string in the textbox and presses the button, the right-hand side activity is created, echoing the input string back to the user.
1. Create an Android project
The first step to implement the app is to create an Android project:
- Open the Android Studio and select "Start a new Android Studio project". In the panel "Configure your new project", assign names to your app (
Hello Word
) and to the company domain (cmov.tecnico.ulisboa.pt
). Accept the suggested project location. - Under "Select the form factors your app will run on", check the box for "Phone and Tablet". For "Minimum SDK", keep the suggested API and leave all other options (TV, Wear, and Glass) unchecked.
- In the panel "Add an activity to Mobile", select "Blank Activity".
- Under "Choose options for your new file", leave the fields as they are.
Navigate to the project view (in the upper left panel) and explore the project directory tree. Describe the role of the following files (Hint: read "Building Your First App"):
app/src/main/res/layout/activity_my.xml
app/src/main/java/pt.ulisboa.tecnico.cmov.helloworld/MyActivity.java
app/src/res/AndroidManifest.xml
app/build.gradle
2. Run the application
To test your app you can use the emulator or a real device.
Emulator: To run the application on the emulator, perform the following steps:
- Create an Android Virtual Device (AVD): (a) launch the Android Virtual Device Management under "Tools > Android > AVD Manager", (b) click "Create Virtual Device", (c) in the "Select Hardware" window select a device configuration (e.g., Nexus 6), (d) select the desired system version for AVD (e.g., Lollipop - API 21 - ABI x86), and (e) finish.
- Launch the newly created AVD: in the Virtual Device Management panel, select the AVD and press the "play" icon (it can take a few minutes for the emulator to bootstrap).
- Run the app from Android Studio: (a) in Android Studio, click "Run" , (b) in the "Choose Device" window, click the radio button "Choose a running device", select the running AVD, and hit ok. The app should appear in the emulator
Real Device: If you have a real device and a USB cable, proceed as follows:
- Set up your device: (a) plug in your device to your development machine with a USB cable, (b) enable "USB debugging" on your device – on most devices running Android 3.2 or older, this option is located under "Settings > Applications > Development; on Android 4.0 and newer, it's in "Settings > Developer options". Note: On Android 4.2+, "Developer options" is hidden by default. To make it available proceed as described here.
- Run the app from Android Studio: (a) in Android Studio, click "Run" , (b) in the "Choose Device" window, select the "Choose a running device" radio button, and pick your device.
It is possible to manage multiple AVDs in Android Studio or in a command-line interface. To learn more about this topic, read "Managing Virtual Devices".
3. Debug the application
Add the following code line to the very end of method onCreate
of the MainActivity
class. Then re-deploy the app code and spot the message that gets displayed in the logcat panel.
Log.d("MainActivity", "This is my first debugging message.");
Place a breakpoint anywhere in the application code (e.g., in the Log.d
line), and execute the program in the debugger view. Explore the debugger functionalities by inspecting the state of the application and then resuming the process execution. While the app is stopped, it is possible to inspect the threads running on the emulator, resource utilization, etc.
4. Build a simple user interface
Implement the activity shown in the left-hand side of Figure 1. To this end, you must modify the default user interface (UI) layout in order to include a text field and a button. This will be done in XML (res/layout/activity_my.xml
). It is possible to specify the layout of an activity using Android Studio's GUI, but we leave it out as an exercise.
In Android, as shown in Figure 2, the layout of an activity's UI consists of a hierarchical tree of elements, each of which is called View
. The leaves of the tree correspond to single UI elements (e.g., buttons). Climbing upwards in the tree, these elements are aggregated into groups (ViewGroup
), which in turn can be arranged into higher-level groups. The root of the tree represents the top level panel of the activity. A ViewGroup
is also a View
.
Different ViewGroup
elements specify different arrangements for its child views. For example, the view group named LinearLayout
lays out child views in sequence, according to the way they appear in the XML. This sequence can be either vertical or horizontal orientation, as specified by the android:orientation
attribute. For more information see "Layouts".
Implement the new layout of Hello World
's main activity:
- Sketch the UI tree: draw a UI tree that reflects the layout of the activity shown in the left-hand side of Figure 1. Hint: use the views
Button
,EditText
, andLinearLayout
. - Write the corresponding XML code: Hint: use the contents of file activity_my.xml and see how it reflects your UI tree.
- Re-run the app from Android Studio.
5. Start another activity
Complete your app by starting another activity when the user presses the "Send" button:
- Create a new activity: (a) create a new file named
DisplayMessageActivity.java
in the project's source directory, next to the originalMyActivity.java
file, (b) add this code to the file, (c) to yourstrings.xml
file, add the activity title as illustrated by this XML code snippet, (iv) in your manifest file,AndroidManifest.xml
, within theApplication
element, add theactivity
element for yourDisplayMessageActivity
class as shown here. - Start the activity when the button is pressed: (a) add the
sendMessage
method shown here to classMyActivity
, (b) bind the button to thesendMessage
method by adding anandroid:onClick = "sendMessage"
attribute to the button layout (configured in fileactivity_my.xml
). - Re-execute the app from Android Studio: Your app should now yield the output displayed in Figure 1. Congrats!
Answer the following questions:
- What's the role of the
android:parentActivityName
attribute declared in the manifest file? - What's the purpose of variable
intent
created within theDisplayMessageActivity
class?
Exercise II – Demystifying Gradle
To manage the build process of a project, Android uses Gradle, an open source building automation system akin to Ant. It is important to understand how Gradle works because it will help you to fix build-related problems more promptly and enable you to manage your projects from the command line.
1. Basic Gradle commands
To introduce Gradle, we first explore its most basic commands. First, download it and install it on a local directory. Note that, first you will use the standard Gradle distribution, and later the distribution that comes with Android Studio.
- Download the gradle-2.1.1 distribution and unzip it to some local directory (e.g.,
~/bin
). We assume that the Java SDK is properly set up on your machine. - Create an environment variable called
GRADLE_HOME
and point it to the gradle installation folder; add$GRADLE_HOME/bin
to thePATH
environment variable. You can then execute thegradle
command from any directory.
On a terminal window, type the following commands and learn what they do:
gradle -v gradle -q help gradle -q tasks gradle -q properties
Create a folder for a hypothetical project (e.g., example1
) and create a file named build.gradle
. This file can be seen as Gradle's Makefile
. Add the following contents to the file:
task compileTask << { System.out.println "compiling..." }
Repeat the gradle -q tasks
command, and spot the task defined in build.gradle
. Then, run the task by executing:
gradle -q compileTask
Modify build.gradle
as follows:
defaultTasks 'buildTask' task compileTask << { System.out.println "compiling..." } task buildTask (dependsOn:compileTask) << { System.out.println "building..." }
Interpret the output of Gradle when issuing the following commands:
gradle -q compileTask gradle -q buildTask gradle -q
As you may have guessed by now, tasks are the building blocks to manage a project. They do things like: compile, build, run tests, package, etc. However, you don't have to write all these tasks by hand. In fact, Gradle can be extended with plugins that define tasks for specific project types: Java plugin, WAR plugin, Android plugin, etc. Next, you will build a Java project using the Gradle Java plugin.
2. Simple Java project with Gradle Java plugin
To introduce the Gradle Java plugin, we will implement a simple Java library. This library implements a domain class called Quote
for managing famous quotes. A quote contains an ID, the author of the quote, and the quote text.
Create a directory for the project called example2
. Place file build.gradle in the project directory and file Quote.java in a project subdirectory src/main/java/pt/ulisboa/tecnico/cmov/quote
.
Answer the following questions (Hint: refer to "Gradle Tutorial: Part 2: Java Projects"):
- What's the purpose of the statement
apply plugin: "java"
inbuild.gradle
? - Execute
gradle tasks
and explore the tasks defined by the Gradle Java plugin. In particular, rungradle build
and explain the outcome of this task. - Why is
Quote.java
placed in that particular directory? - Explain the meaning of the blocks
dependencies
andrepositories
in thebuild.gradle
file.
Modify the class to implement the following Main
method:
public static void main(String[] args) { System.out.println("Running the Quote application"); Quote q = new Quote(); q.setId(new Long(1)); q.setWho("Julius Caesar"); q.setWhat("I came, I saw, I conquered."); System.out.println(q); }
In order to execute this code from Gradle, we need to add an additional plugin. Modify build.gradle
by adding the following code, and then execute "gradle run
". Analyze what happened. Hint: read "Application Plugin".
apply plugin:'application' mainClassName = "pt.ulisboa.tecnico.cmov.quote.Quote"
3. Multiple Java projects
Typically, a project is not a monolithic piece of software, but consists of multiple components, e.g., libraries or APIs. Gradle can gracefully handle complex projects by structuring them into sub-projects. Each sub-project is placed in a sub-directory and managed by a specific build.gradle
file.
To understand how Gradle manages sub-projects, download and uncompress the project file example3.zip and answer the following questions (Hint: see "Gradle Tutorial: Part 3: Multiple Java Projects"):
- Which sub-projects is this project broken up to? Determine how to execute Gradle in order to build (i) the entire project, and (ii) each sub-project individually.
- Identify the dependencies of each sub-project and draw the project's dependency graph.
4. Gradle and Android Studio
Android Studio leverages Gradle to manage its projects using the Gradle Android plugin. Refer to the Hello World project implemented in Exercise I. With the help of the tutorial "Gradle Tutorial: Part 6: Android Studio + Gradle", perform the following exercises:
- Identify within the internal structure of the project, which files are relevant to Gradle and what their role is.
- Clean up and rebuild the project using the Gradle tasks panel of Android Studio.
- Repeat the previous operations using the Gradle console.
- Re-execute the clean and build tasks using an external terminal and the Gradle distribution bundled in Android Studio (Hint: explore the script
gradlew
).
At this point, it should be clear that there's no magic under the hood. For future reference, consider the following guides:
- Android Build System Overview
- Gradle User Guide
- Gradle Java Plugin User Guide
- Gradle Plugin User Guide for Android Tools
Exercise III – TODO list app
Implement a simple TODO list application consisting of a single activity. The activity must show two views arranged vertically: an EditText
view, and a ListView view. The user types a string in the EditText view, and the ListView will be updated with the new string placed in the top of the list.
- Hint 1: Use an ArrayAdapter to bind an ArrayList containing the string list to the ListView.
- Hint 2: To capture the input action of the user on the EditText view, implement setOnKeyListener of this view.