CS 491 Lecture 2 – PopMusic
Today we continue our discussion of Android development and start to dissect the pillars of all interactive applications: the classes Activity
and View
. Before that, though, let’s gather some requirements and do some rough design for today’s app: a bubble-wrap popper. Partner up with a neighbor and take 5 minutes to answer some questions:
- What should the app do? What features do we want?
- What should it look like?
- How should the user interact with it?
Activity
Class Activity
is defined by the Android SDK as a single, focused task that directly involves the user. You can think of an Activity
instance as a single screen or level in your mobile app.
For each app, there’s a main Activity
that gets started when the app first loads. It very likely will spawn other Activity
s to accomplish related tasks or subtasks.
Let’s see Activity
s at work in the Google Maps app. Here I’m looking for directions from campus to the mall, and I get the route spelled out for me on the left. When I click on “Show on map,” a new Activity
is spawned to show the route visually.
At least, I’m guessing that the developers used two Activity
s here, because the spirit of an Activity
is to be self-contained. If the UI changes drastically within an app, you are probably switching to a new Activity
.
Before we write an Activity
, let’s talk about attaching a UI.
View
Activity
s are associated with a particular user interface. The OHA chose not to use Java’s Swing as their interface library. They rolled their own. The standard widgets are essentially the same, but the API is different.
The granddaddy superclass of all UI elements is View. To show read-only text, we use a TextView
(similar to JLabel
without an icon). To show editable text, we use an EditView
(similar to JTextField
and JTextArea
). To show a list, we use ListView
(similar to JComboBox
). With these three classes alone, we can get a lot done. We’ll explore other subclasses later.
Layout
Widgets need to be arranged on the screen in a flexible manner. We do not hardcode positions with absolute pixel coordinates. Instead, we make our View
s children of various layouts. We can arrange widgets in tables (TableLayout
), in horizontal or vertical stacks (LinearLayout
), or more wildly (RelativeLayout
, FrameLayout
, AbsoluteLayout
, …). We’ll assign various layout parameters to our widgets which will control how they fill the space allotted to them by the layout.
Feet Wet
Let’s go ahead and flesh out some of these ideas in a novelty application. We’re going to write a real crowd-pleaser: a bubblewrap-popping application. In preparation for that, let’s actually write a little sandbox app that we can play around with code in.
AndyTest
I’m calling the sandbox app AndyTest. I create a new Android project for it and add the code below as the main Activity
. We can explain this one later. It’s essentially a menu for a bunch of smaller testing Activity
s we’ll write throughout the semester.
package org.twodee.andytest; import android.app.ListActivity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; public class AndyTest extends ListActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String[] items = { "LifecycleTest", }; setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items)); } @Override protected void onListItemClick(ListView listView, View itemView, int position, long id) { super.onListItemClick(listView, itemView, position, id); try { Class<?> clazz = Class.forName("org.twodee.andytest." + getListAdapter().getItem(position)); Intent intent = new Intent(this, clazz); startActivity(intent); } catch (ClassNotFoundException e) { } } }
Event-driven Programming
In your previous programming experiences, you may have gotten control of your program right away in the main method. And you kept that control all the way until main finished. That’s not how UI-driven applications work. There’s no main method in our control. We just write what are called callbacks, methods that get called when the system detects certain events. This is called event-driven programming, and we’ll see this will form how we implement our Activity
s.
Let’s make a new Activity
called LifecycleTest
. Activity
has methods onCreate
, onStart
, onRestart
, onResume
, onPause
, onStop
, and onDestroy
. These are all callbacks called by the Android system itself, not by us. They will be called when our app is created, started, restarted, etc.
Let’s override them in our subclass. Eclipse makes this easy: Source, Override/Implement Methods… And let’s have each pop up a little text blurb when it’s called. Text blurbs can be displayed with the Toast
class:
private void log(String message) { Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); }
Let’s call this method in each of the callbacks. Run it and see what happens! It should fail. We need to register each Activity
in our app in something called the manifest.
<activity android:name=".LifecycleTest" android:label="LifecycleTest" />
Run it again. Hit back. Reorient the device. Lock the device.
The sequence in which these callbacks get called is outlined in the Android documentation:
It’s in these methods where we get control. Typically, we can focus on just three of them: onCreate
, onPause
, and onResume
. The first is called to do one-time initialization and the other two will transition us in and out a paused state, such as when a phone call activity supersedes our game of Minesweeper.
PopMusic
Let’s write our bubblewrap-popping Activity
in a new project. Let’s call it PopMusic
. We’ll need the following resources the resources from popmusic.zip.
Where do we put the contents? Images go in res/drawable. Ideally, we’ll have different resolutions of these images for the different screen densities of the various Android devices. We’re not quite that sophisticated yet. By convention, the sound files go in res/raw, which holds files that have only one version used on all devices.
Now, we’ll need to complete the following tasks:
- Create a custom View subclass.
- Override it’s onDraw method to show what we want it to show.
- Handle user input.
The code will be posted later, after we write it.
TODO
- Read the What is Android? and Application Fundamentals sections of the Dev Guide.
- Check out homework 0.
Haiku
Iron thieves with no wives, kids
“There’s no app for me!”