Android MediaPlayer works fine in Custom audio Streaming application up to Android 2.1 but not in higher versions

The problem is that content type "audio/aacp" streaming is not supported directly. Some decoding libraries can be used to play "aacp", please see the solution below:

Freeware Advanced Audio (AAC) Decoder for Android

How to use this library?

Consider legal issues while using it.

[T]he project http://code.google.com/p/aacplayer-android/ is licensed under GPL, so you can create commercial apps on top of it, but you need to fullfill the GPL - mainly it means to publish your code as well. If you use the second project http://code.google.com/p/aacdecoder-android/ , then you do not need to publish your code (the library is licensed under LGPL).


The StreamingMediaPlayer class is using a double-buffering technique to get around limitations in pre-1.2 releases of Android. All production releases of Android OS have included a MediaPlayer that supports streaming media(1). I would recommend doing that rather than using this double-buffering technique to get around the problem.

Android OS 2.2 replaced the old media player code with the FrightCast player which probably is acting differently in this case.

The line numbers in your stack trace don't map to the file you link to, so I assume there's a different version that you're actually using. I'm going to guess that that NullPointerException is being reported by MediaPlayer but neither the FileInputStream nor the returned FileDescriptor can be null.

(1) Prior to version 2.2 the media player wouldn't recognize ShoutCast streams with an "ICY/1.1" version header in the response. By creating a proxy that replaces this with "HTTP/1.1" you can resolve that. See the StreamProxy class here for an example.


i am using this code and run 2.2 to upper version for streaming downloaded.

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

import android.content.Context;
import android.media.MediaPlayer;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;


public class StreamingMediaPlayer {
private static final int INTIAL_KB_BUFFER =  96*10;//assume 96kbps*10secs/8bits per    byte

private TextView textStreamed;

private ImageButton playButton;

private ProgressBar progressBar;
ProgressBar pb;
int audiofiletime=0;
private long mediaLengthInSeconds;
private int totalKbRead = 0;
int totalsize=0;
int numread;
int totalBytesRead = 0;
private final Handler handler = new Handler();
private MediaPlayer mediaPlayer;
private File downloadingMediaFile; 
private boolean isInterrupted;
private Context context;
private int counter = 0;

public StreamingMediaPlayer(Context  context,TextView textStreamed, ImageButton playButton, Button  streamButton,ProgressBar progressBar,ProgressBar pb) 
{
    this.context = context;
    this.textStreamed = textStreamed;
    this.playButton = playButton;
    this.progressBar = progressBar;
    this.pb=pb;
}

/**  
 * Progressivly download the media to a temporary location and update the MediaPlayer as new content becomes available.
 */  
public void startStreaming(final String mediaUrl) throws IOException {


    //this.mediaLengthInSeconds = 100;


    Runnable r = new Runnable() {   
        public void run() {   
            try {   
                downloadAudioIncrement(mediaUrl);
            } catch (IOException e) {
                Log.e(getClass().getName(), "Unable to initialize the MediaPlayer for fileUrl=" + mediaUrl, e);
                return;
            }   
        }   
    };   
    new Thread(r).start();
}

/**  
 * Download the url stream to a temporary location and then call the setDataSource  
 * for that local file
 */  
@SuppressWarnings({ "resource", "unused" })
public void downloadAudioIncrement(String mediaUrl) throws IOException {

    URLConnection cn = new URL(mediaUrl).openConnection();   
    cn.connect();   
    InputStream stream = cn.getInputStream();
    if (stream == null) {
        Log.e(getClass().getName(), "Unable to create InputStream for mediaUrl:" + mediaUrl);
    }

    ///////////////////save sdcard///////////////
    File direct = new File(Environment.getExternalStorageDirectory()+"/punya");

    if(!direct.exists()) {
        if(direct.mkdir()); //directory is created;
    }

    String[] files=mediaUrl.split("/");

    String fileName=files[files.length-1];
    fileName = fileName.replace(".m4a", ".rdo");


    //create a new file, to save the downloaded file 

    File file = new File(direct,fileName);

    @SuppressWarnings("resource")
    FileOutputStream fileOutput = new FileOutputStream(file);

    ///////////////////end/////////////////

    totalsize=cn.getContentLength();

    //mediaLengthInKb = 10000;

    downloadingMediaFile = new File(context.getCacheDir(),fileName);

    if (downloadingMediaFile.exists()) {
        downloadingMediaFile.delete();
    }

    FileOutputStream out = new FileOutputStream(downloadingMediaFile);   
    byte buf[] = new byte[16384];
    int incrementalBytesRead = 0;
    do {
        numread = stream.read(buf);   
        if (numread <= 0)   
            break;   
        out.write(buf, 0, numread);
        fileOutput.write(buf, 0, numread);
        totalBytesRead += numread;
        incrementalBytesRead += numread;
        totalKbRead = totalBytesRead/1000;
        // pb.setMax(100);
        // pb.setProgress(totalKbRead);

        testMediaBuffer();
        fireDataLoadUpdate();
    } while (validateNotInterrupted());   
    stream.close();
    if (validateNotInterrupted()) {
        fireDataFullyLoaded();
    }
}  

private boolean validateNotInterrupted() {
    if (isInterrupted) {
        if (mediaPlayer != null) {
            mediaPlayer.pause();
            //mediaPlayer.release();
        }
        return false;
    } else {
        return true;
    }
}


/**
 * Test whether we need to transfer buffered data to the MediaPlayer.
 * Interacting with MediaPlayer on non-main UI thread can causes crashes to so perform this using a Handler.
 */  
private void  testMediaBuffer() {
    Runnable updater = new Runnable() {
        public void run() {
            if (mediaPlayer == null) {
                //  Only create the MediaPlayer once we have the minimum buffered data
                if ( totalKbRead >= INTIAL_KB_BUFFER) {
                    try {
                        startMediaPlayer();
                    } catch (Exception e) {
                        Log.e(getClass().getName(), "Error copying buffered conent.", e);               
                    }
                }
            } else if ( mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000 ){ 
                //  NOTE:  The media player has stopped at the end so transfer any existing buffered data
                //  We test for < 1second of data because the media player can stop when there is still
                //  a few milliseconds of data left to play
                transferBufferToMediaPlayer();
            }
        }
    };
    handler.post(updater);
}

private void startMediaPlayer() {
    try {   
        //File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".m4a");

        //moveFile(downloadingMediaFile,bufferedFile);

        //  Log.e(getClass().getName(),"Buffered File path: " + bufferedFile.getAbsolutePath());
        //  Log.e(getClass().getName(),"Buffered File length: " + bufferedFile.length()+"");

        mediaPlayer = createMediaPlayer(downloadingMediaFile);

        //mediaPlayer.start();
        startPlayProgressUpdater();         
        //playButton.setEnabled(true);
        playButton.setVisibility(View.VISIBLE);
    } catch (IOException e) {
        Log.e(getClass().getName(), "Error initializing the MediaPlayer.", e);
        return;
    }   
}

private MediaPlayer createMediaPlayer(File mediaFile)
        throws IOException {
    MediaPlayer mPlayer = new MediaPlayer();
    mPlayer.setOnErrorListener(
            new MediaPlayer.OnErrorListener() {
                public boolean onError(MediaPlayer mp, int what, int extra) {
                    Log.e(getClass().getName(), "Error in MediaPlayer: (" + what +") with extra (" +extra +")" );
                    return false;
                }
            });

    FileInputStream fis = new FileInputStream(mediaFile);
    mPlayer.setDataSource(fis.getFD());
    mPlayer.prepare();
    return mPlayer;
}

/**
 * Transfer buffered data to the MediaPlayer.
 * NOTE: Interacting with a MediaPlayer on a non-main UI thread can cause thread-lock and crashes so 
 * this method should always be called using a Handler.
 */  
private void transferBufferToMediaPlayer() {
    try {

        boolean wasPlaying = mediaPlayer.isPlaying();
        int curPosition = mediaPlayer.getCurrentPosition();

        File oldBufferedFile = new File(context.getCacheDir(),"playingMedia" + counter + ".m4a");
        File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".m4a");

        bufferedFile.deleteOnExit();   
        moveFile(downloadingMediaFile,bufferedFile);

        //mediaPlayer.pause();
        mediaPlayer.release();

        mediaPlayer = createMediaPlayer(bufferedFile);
        mediaPlayer.seekTo(curPosition);

        boolean atEndOfFile = mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition() <= 1000;
        if (wasPlaying || atEndOfFile){
            mediaPlayer.start();
        }

        oldBufferedFile.delete();

    }catch (Exception e) {
        Log.e(getClass().getName(), "Error updating to newly loaded content.", e);                  
    }
}

private void fireDataLoadUpdate() {
    Runnable updater = new Runnable() {
        public void run() {

            //float loadProgress = ((float)totalBytesRead/(float)mediaLengthInKb);
            //float per = ((float)numread/mediaLengthInKb) * 100;
            float per = ((float)totalBytesRead/totalsize) * 100;
            textStreamed.setText((totalKbRead + " Kb (" + (int)per + "%)"));
            progressBar.setSecondaryProgress((int)(per));
            pb.setSecondaryProgress((int)(per));

        }
    };
    handler.post(updater);
}

private void fireDataFullyLoaded() {
    Runnable updater = new Runnable() { 
        public void run() {
            transferBufferToMediaPlayer();

            downloadingMediaFile.delete();
            textStreamed.setText(("Download completed" ));

        }
    };
    handler.post(updater);
}

public MediaPlayer getMediaPlayer() {
    return mediaPlayer;
}

public void startPlayProgressUpdater() {
    audiofiletime   =mediaPlayer.getDuration();
    float progress = (((float)mediaPlayer.getCurrentPosition()/ audiofiletime) * 100);
    progressBar.setProgress((int)(progress));
    //pb.setProgress((int)(progress*100));

    if (mediaPlayer.isPlaying()) {
        Runnable notification = new Runnable() {
            public void run() {
                startPlayProgressUpdater();
            }
        };
        handler.postDelayed(notification,1000);
    }
}    

public void interrupt() {
    playButton.setEnabled(false);
    isInterrupted = true;
    validateNotInterrupted();
}

/**
 *  Move the file in oldLocation to newLocation.
 */
public void moveFile(File   oldLocation, File   newLocation)
        throws IOException {

    if ( oldLocation.exists( )) {
        BufferedInputStream  reader = new BufferedInputStream( new FileInputStream(oldLocation) );
        BufferedOutputStream  writer = new BufferedOutputStream( new FileOutputStream(newLocation, false));
        try {
            byte[]  buff = new byte[5461];
            int numChars;
            while ( (numChars = reader.read(  buff, 0, buff.length ) ) != -1) {
                writer.write( buff, 0, numChars );
            }
        } catch( IOException ex ) {
            throw new IOException("IOException when transferring " + oldLocation.getPath() + " to " + newLocation.getPath());
        } finally {
            try {
                if ( reader != null ){                      
                    writer.close();
                    reader.close();
                }
            } catch( IOException ex ){
                Log.e(getClass().getName(),"Error closing files when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() ); 
            }
        }
    } else {
        throw new IOException("Old location does not exist when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() );
    }
}
}