Playing Back Wav in 2.2 Androids


It’s tough, and I just got it to work. See zipped code here.

The key was writing the streamed URL code to a local disk space (always same file). Despite the purported support, Android 2.2.1 does not support WAV streaming. That is, you can’t play it directly from a URL.

Basically wrote our own “setDataSource” to buffer the data locally before playback. Then, another key is to wait until MediaPlayer has “prepared”, this is done on a Listener method. Only do “start()” once it’s “onPrepared”.

This demo API code was invaluable for breaking down the process flow and troubleshooting. I borrowed the setDataSource method from Davadum Srinivas – great stuff. Also, so nicely formatted and written!

I had determined WAV to be the right format to record and playback on iPhone and Android, and it all tested well, on my device which is 2.2.3. Sadly, my colleague’s (and 2 of his roommates!) devices are 2.2.1 and that broke the easy playback.

Here’s the code, if you like to scan before downloading (like I do)


package com.banane.chicken;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.webkit.URLUtil;

public class ChickenActivity extends Activity implements MediaPlayer.OnPreparedListener {

private MediaPlayer mMediaPlayer;

private static final String TAG = "ch aPlayer";

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

public void playMedia(View v){
try{
Log.d(TAG,"brawk");
String tmpPath = "http://s3.amazonaws.com/lyricsgame/ly_100001882208569_mountain.wav";
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setOnPreparedListener(this);

// this is where we do local buffering and writing
setDataSource(tmpPath);
Log.d(TAG,"done setting ready to prepare:");

mMediaPlayer.prepare();
// good test to see if properly prepared
Log.v(TAG, "Duration: ===>" + mMediaPlayer.getDuration());

} catch (Exception e){
Log.e(TAG, "error: " + e.getMessage(), e);
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
}

}
}

public void onPrepared(MediaPlayer mediaplayer) {
// start here, and only here
Log.d(TAG, "onPrepared called");
mediaplayer.start();
}

public void stopMedia(View v){
if(mMediaPlayer.isPlaying()){
mMediaPlayer.stop();
mMediaPlayer.release();
}
}

private void setDataSource(String path) throws IOException {
if (!URLUtil.isNetworkUrl(path)) {
mMediaPlayer.setDataSource(path);
} else {
URL url = new URL(path);
URLConnection cn = url.openConnection();
cn.connect();
InputStream stream = cn.getInputStream();
if (stream == null)
throw new RuntimeException("stream is null");
File temp = File.createTempFile("mediaplayertmp", "dat");
String tempPath = temp.getAbsolutePath();
FileOutputStream out = new FileOutputStream(temp);
byte buf[] = new byte[128];
do {
int numread = stream.read(buf);
if (numread <= 0) break; out.write(buf, 0, numread); } while (true); mMediaPlayer.setDataSource(tempPath); try { stream.close(); } catch (IOException ex) { Log.e(TAG, "error: " + ex.getMessage(), ex); } } } }