MEIC/MERC 2015/2016
Mobile and Ubiquitous Computing
Lab Guide 2
Android Application Components
Objectives:
- Introduction to application components: activities, services, broadcast receivers, and content providers.
- Fundamentals of application lifecycle: activity lifecycle, back stack, and tasks.
Material:
Exercise I: Activities
The goal of this exercise is to help understand the lifecycle of Android activities.
1. Write a simple application that allows the user to explicitly terminate the app by pressing a button. Proceed as follows:
-
In Android Studio, create a new project – in this process, assign names to your app (
Simple Activity
) and to the company domain (cmov.tecnico.ulisboa.pt
), and select "Blank Activity". -
Add a new button (text: "Finish") to the main activity by either using the UI editor of Android Studio or by editing the XML file
activity_main.xml
. -
Add a method "
public void finishButtonPressed(View view)
" to the activity main class and bind the button to this method by adding attributeandroid:onClick = "finishButtonPressed"
to the button layout (configured in fileactivity_my.xml
). -
In the method
finishButtonPressed
, add a method callfinish();
.
Compile and test the app. Confirm that the app terminates when the button is pressed.
2. Modify the application in order to print a debug message for all of the relevant events of the main activity's lifecycle.
First, you need to create callbacks for the lifecycle events by overriding the methods: onStart
, onResume
, onPause
, onStop
, onDestroy
, onRestart
. For a complete reference, read "Implement the lifecycle callbacks". (Hint: to automatically generate callback skeletons, place the cursor in the MainActivity
class, go to "Code > Override methods...", and select the methods.)
Then, modify each method to write a debug method as illustrated next. Naturally, you need to adapt the output message to reflect method from which the toast instruction is executed:
Toast.makeText(this, "onCreate", Toast.LENGTH_SHORT).show();
Perform the following exercises:
- Deploy the application and write down the sequence of messages displayed by the toast instructions.
- Press the "Finish" button. Observe and interpret the sequence of states.
- Re-execute the application. Press the emulator's "Home" button. What happens?
- Click on the launch pad (at the right of the "Home" button) and resume the app. What sequence of messages is displayed and why?
- In Android Studio, open the Android Device Monitor (ADM) tool under Tools > Android, select the "Emulator Control" tab, type in an incoming phone number (e.g., "1234"), and click the Call button to simulate an incoming call. Is the app paused or stopped?
- Still in ADM, press Hang Up button. What happens?
2. Decompress and import the project ActivityLifecycle.tgz into Android Studio. Compile and execute the app.
- Interpret the output produced by the app after navigating through the app's activities and studying the source code of the program.
- Write the activity wireframe of the app. In an activity wireframe, boxes represent activities, and arrows between boxes represent transitions across activities (see the class slides).
Exercise II: Services
The goal of this exercise is to understand how services work.
1. Import the project ServiceSimple.tgz into Android Studio. Compile and execute the app. Press the buttons "Start Service" and "Stop Service" by this sequence. Analyze the source code and explain the sequence of toasts displayed by the application. (Hint: see the state diagram in "Services".)
2. Modify the previous application so that the activity and the service can share non-volatile state. Use the application context to hold a counter for the number of times the service has been started. Increment the counter in the activity right before calling the startService
method. Modify the toast instruction of the service's onStartCommand
to print the current value of the counter. Read the instructions from the class slides to learn how to access the application context.
Exercise III: Broadcast Receivers
In this exercise, define a broadcast receiver that listens to telephone state changes. If the device receives an incoming phone call, then your receiver will be notified and message logged. Whenever you need, look up for help in the Android developers website.
- Create a new project with a single activity, which is necessary so that the user can execute the app and initialize the broadcast receiver.
-
In the manifest, declare a broadcast receiver named
MyPhoneReceiver
with intent filter set to intentandroid.intent.action.PHONE_STATE
, and declare user permissionandroid.permission.READ_PHONE_STATE
. -
Create class
MyPhoneReceiver
that extends from classBroadcastReceiver
, and override methodonReceive
; obtain incoming call state from the intent's extras, e.g., looking up stringTelephonyManager.EXTRA_INCOMING_NUMBER
, and log the call state usingLog.w(...)
method (you need to importandroid.util.Log
). - Install your application and simulate a phone call using the ADM tool. Confirm that your receiver is called by verifying that the logged message appears in the LogCat console.
Exercise IV: Notepad App
Implement a simple notepad application. The activity wireframe intended for this application is represented below.
The app consists of three activities. The main activity (ListNotesActivity) displays the titles of existing notes and a button for creating a new note. When the user presses that button (New Note), a new activity is created, named CreateNoteActivity. The CreateNoteActivity shows: a view for typing the note title, another view for typing the note text, and two buttons: OK for accepting the note, and Cancel for canceling the note. Pressing either of the buttons terminates that activity, but if Ok is pressed, the new note will be accepted and the note list updated, otherwise the note will be discarded. In the main activity, pressing a note title from the list results in creating a new activity (ReadNoteActivity), which shows the title and the content of that note. To terminate that activity the user must press the BACK button.
If an activity is paused or stopped, e.g., because the user pressed Home button, care must be taken so that, once the activity resumes execution, the user finds it in the same state as it was before being paused or stopped.