Linux.com

Home Learn Linux Linux Documentation Android Programming for Beginners: Part 2

Android Programming for Beginners: Part 2

In the first part of this two-part series on getting started with Android coding, you set up your development environment, built a basic countdown app, and got acquainted with the Android API. In this second article we'll have a closer look at the structure of an Android app, create a menu, and write a second activity to input a countdown time. We'll also look at running your app on a physical phone.

Menu options

There are three Android menu types. The Options Menu is the menu that appears when you hit the menu button (on older Android) or is shown in the Action bar (newer Android), and you can also access contextual menus and popup menus. We're going to use the Options Menu to allow you to set the count down time.

Eclipse creates an stub Options Menu method with a new main Activity:

public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.activity_main, menu);
  return true;
}

getMenuInflater() allows you to follow best practice and create your menu in XML rather than in code. Edit res/menu/activity_main.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/set_time" android:title="@string/set_time"></item>
</menu>

and add the @string reference to res/values/strings.xml. You can fiddle around more with menu ordering and other options in the Layout tab, if you want.

onMenuItemSelected()is fired when the user chooses a menu item:

public boolean onMenuItemSelected(int id, MenuItem item) {
  switch(item.getItemId()) {
    case R.id.set_time:
      setTime();
      return true;
    default:
      // we don't have any other menu items
  }
  return super.onMenuItemSelected(id, item);
}

All we do is get the menu item ID (set in the XML above) and act accordingly. We're now ready to write the setTime()method, which will call another Activity.

 android 2 menuMenu item is showing at the bottom of the screen.

Activities

First, a little bit of background. Android is structured as a whole bunch of modules, the idea being that parts of one app can easily hook into parts of other apps, maximising code reuse. There are four main application components:

  1. Activites: provide a screen and UI for a particular action. An app has at least one main Activity, and may have lots of other associated Activities.
  2. Services: run in the background doing something (checking email, playing music, etc), without a UI.
  3. Broadcast Receiver: receive announcements broadcast by the system and do something accordingly.
  4. Content Provider: makes data available to other apps.

Intents are messages which are used to jump into a module, or to pass information between modules. We're going to set up a second Activity to enter the time to count down for, using a scroller widget, called using the menu and setTime():

private void setTime() {
  Intent i = new Intent(getBaseContext(), CountdownSetTime.class);
  startActivityForResult(i, SET_TIME_REQUEST_ID);    
}

This Intent simply starts the new CountdownSetTime Activity, and tells the current Activity to expect a result. In CountdownSetTime.java, the work is done in the onCreate()method:

public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.set_time);
  context = this.getApplicationContext();
  Spinner spinner = (Spinner) findViewById(R.id.spinner);
  ArrayList<Integer> spinnerList = new ArrayList<Integer>();
  for (int i = MIN; i <= MAX; i++) {
    spinnerList.add(i);
  }
  ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(context,
          android.R.layout.simple_spinner_item, spinnerList);
  adapter.setDropDownViewResource(
          android.R.layout.simple_spinner_dropdown_item);
  spinner.setAdapter(adapter);
  spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    public void onItemSelected(AdapterView<?> parent,
      View view, int pos, long id) {
      secondsSet = (Integer)parent.getItemAtPosition(pos);
    }
    public void onNothingSelected(AdapterView<?> parent) {
      // Do nothing.
    }
};

The XML layout in res/layout/set_time.xmllooks like this:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  >
  <Spinner
    android:id="@+id/spinner"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="50px"
    android:text="@string/spinner_text"
  />
  <Button
    android:id="@+id/ok_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/spinner"
    android:layout_marginLeft="10dip"
        android:text="@string/ok_text" />
  <Button
    android:id="@+id/cancel_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/spinner"
    android:layout_toRightOf="@id/ok_button"
    android:layout_marginLeft="10dip"
        android:text="@string/cancel_text" />
</RelativeLayout>

It defines a Spinner and two buttons, within a RelativeLayout. A Spinner displays data; an array holds the data; and an ArrayAdapter translates between the two. Our Spinner just displays numbers (seconds to count down), so the data is held by an Integer ArrayList, holding the integers between our MIN and MAX values. android.R.layout.simple_spinner_item and android.R.layout.simple_spinner_dropdown_itemare stock Android layout resources that set up the look of the spinner item and the dropdown. You could also choose to create your own resources.

onItemSelectedListener() sets up a Listener to act when an item is picked, setting the secondsSet class variable. To pass this value back to the original Activity, we set up OK and Cancel buttons. You've already seen the code for a button and its OnClickListener in the previous article, so here I'll just show the onClick()method for the OK button:

public void onClick(View view) {
  Intent i = new Intent();
  Bundle bundle = new Bundle();
  bundle.putInt(CountdownActivity.SET_TIME_KEY, secondsSet);
  i.putExtras(bundle);
  setResult(RESULT_OK, i);
  finish();
}

A Bundle is used to store information in an Intent, so it can be passed between Activities. Each value (here we just have a single Integer) is stored with a String key. For the cancel button, no Bundle is needed. Just create an Intent, set the result as RESULT_CANCELLED, and call finish().

android 2 spinnerChoosing the number of seconds on a hardware phone.

You'll also need to register the new Activity by adding this line to AndroidManifest.xml:

<activity android:name=".CountdownEnterTime"></activity> 

Finally, then, we need something to handle the Intent back in CountdownActivity; this is what the onActivityResult()method is for:

private int countdownSeconds = 10;  // default value of 10 secs
[ .... ]
protected void onActivityResult(int requestCode, int resultCode, Intent i) {
  super.onActivityResult(requestCode, resultCode, i);
  if (resultCode == RESULT_CANCELED) {
    return;
  }
  assert resultCode == RESULT_OK;
  switch(requestCode) {
    case SET_TIME_REQUEST_ID:
      Bundle extras = i.getExtras();
      countdownSeconds = extras.getInt(SET_TIME_KEY);
      countdownDisplay.setText(Long.toString(countdownSeconds));
      break;
    default:
      // do nothing; we don't expect any other results
    }
  }
}

Check for RESULT_CANCELLED first, as this will be the same for any returning Activity, and you will always ignore it and return. The assertstatement makes it clear that beyond this point, the result is assumed to be OK. If any other value is returned, the method will throw an error. The number of seconds is stored in a class variable, and displayed to the user.

Finally, to make the timer do the right thing, we need to change one line in the start button's onClick()method:

showTimer(countdownSeconds * MILLIS_PER_SECOND)

If you run the app on an emulator now, you should be able to pick a time and watch it count down.

Installing on a phone

You can hook your phone up via USB and run on that rather than on the software emulator. For some uses (e.g. the accelerometer and the GPS) it is better to test it on a phone, rather than in the emulator. Just plug in the USB cable, and turn on USB Debugging in Settings / Developer Options. When you hit Run in Eclipse, you'll get the option to run it on your phone. If you want to be able to run your app in non-debugging mode, check out the Android info on publishing.

This app could obviously still use some improvement. Perhaps a start/stop button (check out the CountDownTimer API); a button rather than a menu item to set the time; a ringtone to go off when the alarm finishes; a different form of spinner; some graphical design improvements... Play around and see where you can take the code from here!

 

Comments

Subscribe to Comments Feed
  • spaerky mcdoogal Said:

    Great 2 part tutorial. Lots of useful info and a great springboard on to further learning. Thank you!

  • Viktor Said:

    Can you send me you source code? Have problems cant find a mistake. smog@hotmail.ru

  • Gil Said:

    Completely new to Android development, and Java in general, most all of my experience is way back in ansi C (and I'm rusty as hell). Having a couple specific issues.. SET_TIME_REQUEST_ID and SET_TIME_KEY are coming back undefined and I'm not sure how/where to define them. In CountdownSetTime.java, I'm getting error: "Abstract Methods do not Specify a Body." My file to the method creation is: package com.example.countdown; import android.os.Bundle; import android.view.View; import android.widget.Button; public interface CountdownSetTime { public void onCreate (Bundle savedInstanceState) { ----------- Any advice would be appreciated!

  • Jeff Said:

    First issue: you will need to define them yourself in CountdownActivity. The type of _ID should be int, and for _KEY it should be String. Make up the actual values yourself. They are used to match up the call to the external activity with the result.

  • ElBastardo Said:

    Jeff, that's the sort of thing that should be included in this tutorial. There's way too much information and detail left out.

  • Smog Said:

    Thank you for lessons. Go ahead! Waiting for 3 part :-)

  • Dennis Garavsky Said:

    Here is a working sample project I created based on these two tutorials: https://docs.google.com/open?id=0B1uF_SpOQUSYN1Budi1rdUJYVzg Although I find the official Android training materials at http://developer.android.com/training/index.html easier to follow for newbies, I highly appreciate the author's effort (being a programmer myself, I know how it is difficult to describe the things looking obvious to you to other people), because it 1) has helped me to create my first Android app after all! 2) this tutorial intentionally is missing some small pieces and thus forces your brain to work and learn more about the things instead of just blindly copying a ready fish. Thank you!

  • Leandro Said:

    Hi, Thanks for the post. As this is for newbies like me, more info would be great. But this endup being good for me, because made figure out, search, and have a better understanding of how the things are rellated. =) In order to create CountdownSetTime activity, right click the same package that has CountdownActivity and choose Android Activity. This wizard makes everything necessary for the activity, like create the menu and layout files and saves you the trouble to create everything by hand. In class CountdownSetTime: private final int MIN = 0; private final int MAX = 15; private android.content.Context context; protected static Integer secondsSet; - countdownSeconds is initialized with 10, but the app displays 00:30 because this is the value for @string/_00_30. That's why when you click start it shows 9 (10 is not displayed). You can set the value after the countdownDisplay is initialized: countdownDisplay.setText("00:" + countdownSeconds);

  • Rogerio J. Gentil Said:

    Hi. This second part isn't so easy for beginners.

  • ElBastardo Said:

    Shitty tutorials like these will drive devs to iOS for sure. Way too much fixing required.

  • Leandro Said:

    Respect others initiative. He spend his time and shared this for free. If you have any doubts post in the comments, but read other comments first to see if you find your solution.

  • El Mo Said:

    Erm... I think Juliet is a girl... but apart from that, yes, I agree with you. Don't diss the work of others, especially when given for free.

  • Bobo Tlaga Said:

    I am surprised that this got published. The purpose of this tutorial is to confuse and not educate. I think some people including some of the commenters are out to deceive people.

  • Ugh Said:

    Yeah, as other have said there's way too much left out of this tutorial. Tutorials should be essentially cut and paste. This tutorial is very little value if you're getting started with android and/or java and pasting the code produces all sorts of errors. Variables aren't defined, imports aren't mentioned. Poor tutorial.

  • Anelie Ivanova Said:

    Hi, Recently I came across some great articles on your site. The other day, I was discussing (https://www.linux.com/learn/docs/686857--android-programming-for-beginners-part-2)with my colleagues and they suggested I submit an article of my own. Your site is just perfect for what I have written! Would it be ok to submit the article? It is free of charge, of course! Let me know what you think Contact me at anelieivanova@gmail.com Regards Anele Ivanova

Upcoming Linux Foundation Courses

  1. LFD331 Developing Linux Device Drivers
    13 Oct » 17 Oct - Virtual
    Details
  2. LFS425 Linux Performance Tuning Crash Course
    16 Oct » 16 Oct - Düsseldorf, Germany
    Details
  3. LFS220 Linux System Administration
    20 Oct » 23 Oct - Virtual
    Details

View All Upcoming Courses

Become an Individual Member
Check out the Friday Funnies

Sign Up For the Linux.com Newsletter


Who we are ?

The Linux Foundation is a non-profit consortium dedicated to the growth of Linux.

More About the foundation...

Frequent Questions

Join / Linux Training / Board