• Home
  • Tutorials
    • Game Development Tutorial>
      • Unit 1: Beginning Java>
        • Before you begin...
        • Day 1: Setting Up
        • Day 2: Java Basics
        • Day 3: More Basics
        • Day 4: Java Math
        • Day 5: More Math
        • Day 6: If... else...
        • Day 7: More Control Flow
        • Day 8: Looping
        • Day 9: More on Looping
        • Day 10: Inheritance, Interface
        • Day 11: Threads and Graphics
      • Unit 2: Creating a Game I>
        • Day 1: Foundations
        • Day 2: Basic Framework
        • Day 3: Taking User Input
        • Day 4: Enter the Robot
        • Day 5: Background and Sprites
        • Day 6: Adding Enemies
        • Day 7: Shooting Bullets
        • Day 8: Animations
        • Day 9: 2D-Arrays
        • Day 10: Painting the Tilemap
      • Unit 3: Creating a Game II>
        • Day 1: Level Creation - Part 1
        • Day 2: Level Creation - Part 2
        • Day 3: Level Creation - Part 3
        • Collision Detection Basics
        • Day 4: Collision Detection Part 1
        • Day 5: Collision Detection Part 2
        • Day 6: Collision Detection Part 3
        • Day 7: Health System & Death
        • Day 8: Basic AI & Final Touches
      • Unit 4: Android Game Development>
        • Day 1: Introduction to Android
        • Day 2: Setting up for Development
        • Day 3: Creating our First Android Application
        • Day 4: Parts of an Android Application
        • Day 5: The Android Game Framework: Part I
        • Day 6: The Android Game Framework: Part II
        • Create an Android Game From Scratch (or port your existing game)
        • Day 7: Creating an Android Game (From Start to Finish)
      • Reference Sheet
    • Zombie Bird Tutorial (Flappy Bird Remake)>
      • Unit 1: Building the Game>
        • Introduction
        • Day 1: Flappy Bird - An In-depth Analysis
        • Day 2: Setting up libGDX
        • Day 3: Understanding the libGDX Framework
        • Day 4: GameWorld and GameRenderer and the Orthographic Camera
        • Day 5: The Flight of the Dead - Adding the Bird
        • Day 6: Adding Graphics - Welcome to the Necropolis
        • Day 7: The Grass, the Bird and the Skull Pipe
        • Day 8: Collision Detection and Sound Effects
        • Day 9: Finishing Gameplay and Basic UI
        • Day 10: GameStates and High Score
        • Day 11: Supporting iOS/Android + SplashScreen, Menus and Tweening
        • Day 12: Completed UI & Source Code
    • Android Application Development Tutorial>
      • Unit 1: Writing Basic Android Apps>
        • Before you begin...
        • Day 1: Android 101
        • Day 2: Getting to Know the Android Project
        • Day 3: The Development Machine
        • Day 4: Building a Music App - Part 1: Building Blocks
        • Day 5: Building a Music App - Part 2: Intents
        • Day 6: Building a Music App - Part 3: Activity Lifecycles
  • New Forum
  • About Us
    • Contact Us
  • Our Games
    • TUMBL: FallDown
  • Facebook
  • Twitter

    Android Application Development: Day 1-6: Building a Music App - Part 3: Activity Lifecycles
Welcome to the next lesson of the Android application development series. In this lesson, we will be discussing how to receive Intents and retrieve information from them.

Before we begin, there was a slight error in the previous lesson. Open up activity_main.xml and make the following changes:


button3's android:text value should be "three" not "four." Likewise, button4's android:text value should be "four" not "three."

Here are the corrections:
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="19dp"
        android:layout_marginTop="19dp"
        android:text="One" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/button2"
        android:layout_marginLeft="19dp"
        android:layout_toRightOf="@+id/button1"
        android:text="Three" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/button1"
        android:layout_below="@+id/button1"
        android:layout_marginTop="38dp"
        android:text="Two" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/button2"
        android:layout_alignBottom="@+id/button2"
        android:layout_alignLeft="@+id/button3"
        android:text="Four" />

</RelativeLayout>
Now that that has been sorted out, let's move on to the next bit:

Recall that in the last lesson, we started a SecondActivity by using one of four buttons, each of which contained a button number that was bundled with the intent.

Now, we will be retrieving this button number in the SecondActivity and playing the corresponding song. We will be discussing the Activity Lifecycle along the way!

Let's start with the code:

Recall how we created an Intent (a message that holds data about a desired action) in Day 5 (MainActivity) (check that yours is identical, or it will not work. Eclipse, for some reason, changed the key "BUTTON NUMBER" during packaging, so if you are running downloaded code, you may have to fix this):

  Intent intent = new Intent(this, SecondActivity.class);
  intent.putExtra("BUTTON NUMBER", buttonNum);
  startActivity(intent);


Now, in the bottom of the onCreate() method of the SecondActivity class, we add the following:

Intent intent = getIntent();
int number = intent.getIntExtra("BUTTON NUMBER", 1);

(Make sure you import Intent).

Let's make sure that we understand what the two lines here are doing:
getIntent() will retrieve the Intent that was used to start the current Activity (screen). This means that the intent we created in Day 5 will be retrieved.

Next, we store in the integer "number" the button number of the pressed button, providing a default value of 1 in case it fails.

To make sure this is retrieving the intent correctly, let's try changing the TextView's value of the SecondActivity.
This should be familiar to you, as I have previously demonstrated this.

Open the activity_second.xml file.

We will add an ID to the textView:
android:id="@+id/textView"

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".SecondActivity" >

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</RelativeLayout>
Now go back to SecondActivity class. 

Add the following in the bottom of the onCreate() method:


  TextView tv = (TextView) findViewById(R.id.textView);
  tv.setText(String.valueOf(number));



Starting to understand how the casting works? We retrieve an object (a View) by it's ID (R.id.textView) and cast it as a TextView, and store it as tv.

Then we set the value of tv to number, which is converted to a String (setText cannot take in integers). As number represents the button that was pressed in the previous screen, the MainActivity, it will now show that number as the TextView's value:
Picture
Ta-da! It works as intended. Now rather than simply print it out, we will ask Android to play a music file.

I will use four pieces of royalty free music. I am a big fan of Matt McFarland's music, so we will use his!
http://www.mattmcfarland.com/

I downloaded the following four songs:
1. Nintendo was Cool
2. The Uncertain Hero
3. Strangled
4. Finding Happiness

For your convenience, I am providing a .zip version of the file, but if you like the music, check out Matt's site above! 
If you have slow internet, just use four small .mp3 files that you can find online, and name them song1, song2, song3, and song4.
day_6_music.zip
File Size: 18880 kb
File Type: zip
Download File

Extract the four files (using Alzip or Winrar or your extraction program of choice), and place them into the following directory inside your Application project: res/raw/. 

Create a raw folder if necessary, like so:

Placing the files:

Picture
Just to refresh our auto-generated R class, which is the class that provides a Java ID for each file in the res folder, go to Project > Clean, and clean the project.

This should make sure that we can reference our four new files without errors.

Now, open up SecondActivity again. In the onCreate() method, we want to start playing the music.

We will begin by adding the following.

1. Below the class declaration:
public class SecondActivity extends Activity {

Add:
private MediaPlayer mPlayer;
private int currentSong = 0;

A MediaPlayer is used to play songs/video. We are creating a new one called mPlayer. We do not initialize it yet, because we need to initialize it with the song information.

currentSong will keep track of the song that is playing right now, so that when the application pauses (user presses home button), it will remember which song was playing, so that you can resume it!

Let's talk about the Activity Lifecycle. Recall that onCreate() is called immediately when the Activity starts.

So, we will play the music in our onCreate() method:

This is what it will look like.

SecondActivity onCreate()

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        Intent intent = getIntent();
        int number = intent.getIntExtra("BUTTON NUMBER", 1);

        TextView tv = (TextView) findViewById(R.id.textView);
        tv.setText(String.valueOf(number));

        if (number == 1) {
            mPlayer = MediaPlayer.create(SecondActivity.this, R.raw.song1);
            currentSong = R.raw.song1;
        } else if (number == 2) {
            mPlayer = MediaPlayer.create(SecondActivity.this, R.raw.song2);
            currentSong = R.raw.song2;

        } else if (number == 3) {
            mPlayer = MediaPlayer.create(SecondActivity.this, R.raw.song3);
            currentSong = R.raw.song3;

        } else if (number == 4) {
            mPlayer = MediaPlayer.create(SecondActivity.this, R.raw.song4);
            currentSong = R.raw.song4;

            // Defaults are always a good idea:
        } else {
            mPlayer = MediaPlayer.create(SecondActivity.this, R.raw.song1);
            currentSong = R.raw.song1;

        }

        mPlayer.start();
    }
We use a series of if statements to determine which song to play. We even add a default value just in case something goes wrong. After loading up the MediaPlayer with the desired song, we call:

mPlayer.start();

Pretty straight forward.

Now here's the tricky part. What if the user pauses the app? Right now, if the user gets a call or if the user presses the home button, the music will continue to play. That is because we are not Overriding an onPause() method. So let's add one.

SecondActivity onPause()

    @Override
    protected void onPause() {
        super.onPause();
        if (mPlayer.isPlaying()) {
            mPlayer.pause();
        }
    }

The onPause() method is called whenever the application is hidden from the user. Typically this is when the user opens another Activity (or presses Back to return to MainActivity). We will first call super.onPause() (this is required, because there are certain calls in the Activity.class's onPause method - the method we are overriding - that must be called for proper system function). 

Then we simply check if mPlayer is playing before we pause it.

Now the music will pause when the user leaves the app, but what if he or she returns to it? Then onCreate method will NOT be called, as the Activity is not being created for the first time. Then we need to add the following method: onResume().


SecondActivity onResume()

    @Override
    protected void onResume() {
        super.onResume();
        if (mPlayer == null) {
            mPlayer = MediaPlayer.create(SecondActivity.this, currentSong);
        }

        mPlayer.start();
    }
First, we make sure that our mPlayer is not null. As we are juggling resources around in our mobile device, sometimes large memory objects may get lost. If it is null, we simply create a new one with the currentSong - the song that was playing when the app was paused.

Then we simply call .start() again to resume.

Finally, we must help the system clean up a little bit in case the application closes. It will be good practice for us to do our own clean up and make sure system resources are available for other apps, so let's do that:

SecondActivity onStop()

    @Override
    protected void onStop() {
        super.onStop();

        if (mPlayer.isPlaying()) {
            mPlayer.stop();
        }
    }
Same thing here. We call the super.onStop(), as the superclass's onStop method must be called to call critical methods upon Stopping an application. We will check if the mPlayer is playing, and then stop it, and everything will be ready to be disposed by Android.

Now when we run the application, it will handle music properly. When we pause and exit, it will cleanly stop the music as necessary. Now you have your first working media application!

I hope that you have learned a thing or two about Android from making this application (and enjoyed it too)! Specifically, you should be familiar with retrieving a View by its id (findViewById), casting it as a TextView or Button, and modifying it dynamically. You should also understand how layouts can be edited graphically or in XML, and be able to use Intents to open a new Activity. Finally, you should have a basic understanding of how the Activity Lifecycle works, and will be able to build on that in future lessons.


What do you want to learn next? Suggestions are welcome in the Forums.
Picture

Source Code:

day_6_source.zip
File Size: 57921 kb
File Type: zip
Download File

Go to Unit 1: Day 5
Day 7 Coming Soon!
comments powered by Disqus
© 2014 Kilobolt, LLC. All rights reserved.