Android: Using the Soundpool Class and MediaPlayer for online streams
May 10 2011 06:13pm | | Share

Android: Using the Soundpool Class and MediaPlayer for online streams

By Alain Thibodeau

Android: Using the Soundpool Class

There are times when you want to play a short sound in your application warning the user that something has happened, or just to add sound effects. Using the MediaPlayer is a good way of playing a sound, but it is system taxing if you are using more than one sound, and playing them at the same time. The SoundPool class will allow you to manage and play multiple short sounds.

Below is a simple example of using the SoundPool class.

[cc lang="java" escaped="true" height="1100"]
package com.newyyz;

import android.app.Activity;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class SoundPoolActivity extends Activity {

SoundPool soundPool;
int ringSound = -1;
int bangSound = -1;

private Button btnPlayRing;
private Button btnPlayBang;
private Button btnPlayAll;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);

btnPlayRing = (Button) findViewById(R.id.btnRing);
btnPlayBang = (Button) findViewById(R.id.btnBang);
btnPlayAll = (Button) findViewById(R.id.btnAll);

setVolumeControlStream(AudioManager.STREAM_MUSIC);

soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
bangSound = soundPool.load(this, R.raw.hit, 1);
ringSound = soundPool.load(this, R.raw.ring, 1);

btnPlayRing.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
soundPool.play(ringSound, 1, 1, 0, 0, 1);
}
});

btnPlayBang.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
soundPool.play(bangSound, 1, 1, 0, 0, 1);
}
});

btnPlayAll.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
soundPool.play(bangSound, 1, 1, 0, 0, 1);
soundPool.play(ringSound, 1, 1, 0, 0, 1);
}
});
}
}
[/cc]

We start off on line 22 in the onCreate() method setting the content to our layout resource and preparing three buttons. These buttons will play our sound effects. The first one will play the ring sound, the second will play the bang sound and the third one will play both sounds at the same time.

Next we set the volume controls to the music stream on line 31. Then we create a soundpool and configure it to handle 2 concurrent streams. Set this value to what your needs are, usually around 15-20 if you are creating a game.

Once the soundPool is created, we can load our sound files, the soundpool's load method will return a handle so we can reference the sounds when we need them.

Finally, we have our listeners on each button that call the soundpool's play method. The first argument is the sound's handle that we received from the load method. The second and third arguments are the left and right volume that range between 0 and 1. The next one is the priority. Following the priority is the loop count with -1 for looping forever. The last argument is the playback rate, which increases or decreases the speed of the audio.

This is a brief example demonstrating the use of the soundPool class. For production, you would consider using a HashMap to keep track of your sounds, and have only one method to play them. Also, to be memory friendly, unloading sounds when no longer needed or releasing the soundPool altogether is a good idea.

soundPool.unload(ringSound);

or

soundPool.release();
soundPool

Android: Using the MediaPlayer for Online Streams

We've looked at ways of making use of the SoundPool class for smaller sounds like sound effects in a previous post. But, what about streaming audio from a server? Like an online radio station. This can be easily done using the MediaPlayer class.

Below is a quick and simple example using the MediaPlayer for streaming online content.

[cc lang="java" escaped="true" height="1200"]
package com.newyyz;

import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class StreamingAudioPlayerActivity extends Activity {

private Button playButton;
private Button stopButton;
private EditText urlEditText;
private TextView statusText;
private MediaPlayer mediaPlayer;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);

initView();
initMediaPlayer();
}

private void initView() {
urlEditText = (EditText) findViewById(R.id.UrlEditText);
urlEditText.setText("http://playradio.podzone.org:9090/Play96.mp3");

statusText = (TextView) findViewById(R.id.status);

playButton = (Button) findViewById(R.id.playButton);
playButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
playStream();
}
});

stopButton = (Button) findViewById(R.id.stopButton);
stopButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
stopStream();
}
});
}

private void initMediaPlayer() {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
statusText.setText("Playing...");
}
});
}

private void playStream() {
statusText.setText("Loading...");
playButton.setVisibility(View.GONE);
stopButton.setVisibility(View.VISIBLE);

try {
mediaPlayer.setDataSource(urlEditText.getText().toString());
mediaPlayer.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
}

private void stopStream() {
playButton.setVisibility(View.VISIBLE);
stopButton.setVisibility(View.GONE);
statusText.setText("");
mediaPlayer.stop();
mediaPlayer.reset();
}

@Override
protected void onDestroy() {
super.onDestroy();
mediaPlayer.release();
}
}

[/cc]

As usual in our onCreate() method we setup the view. In this case we setup an EditText, TextView and two button controls. One button is for playing and the other is for stopping the stream. The EditText control is for our stream's URL, and the TextView control is for giving the user some feedback about what is going on.

The next step is to create our MediaPlayer instance which we do in the initMediaPlayer() method. We also set the audio stream type and most importantly a listener for when the stream has finished preparing. In this example we are using the asynchronous version of the MediaPlayer's prepare method. The reason we are preparing the MediaPlayer asynchronously is that we are accessing a stream on the Internet. Because of this, preparing may take some time. If we were to use the synchronous prepare method, it would lock the application until the player is ready.

Upon hitting play, we update the buttons and the status. At this point we are ready to set the datasource and prepare our MediaPlayer instance. Once the MediaPlayer is prepared, we play the stream in the OnPreparedListener();

Stopping the stream is done in the stopStream() method. We simply swap our buttons and stop the MediaPlayer. Resetting the MediaPlayer will put the player in its uninitialized state so we can set a new (or the same) data source and re-prepare.

Should the user exit the app, we will want to clean up. This is handled in the override of the onDestroy() method where we simply release the mediaPlayer. Based on what your needs are, you will handle the MediaPlayer for the various activity's lifecycle phases.

So there we have it, a very simple media player for handling online streams. This could be the start of a very compelling Android application that can handle online streams, local files and video.

Media Player