在2.2中流式传输shoutcast流中断的android代码

时间:2010-09-30 20:23:22

标签: android audio-streaming shoutcast

以下代码适用于Android 2.1update1 -

package com.troubadorian.android.teststreaming;



import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.Gallery;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.Gallery.LayoutParams;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.ViewSwitcher;

public class TestStreaming extends Activity 
{
 private Button streamButton;

 private ImageButton playButton;

 private TextView textStreamed;

 private boolean isPlaying;

 private StreamingMediaPlayer audioStreamer;

 @Override
 public void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  // requestWindowFeature(Window.FEATURE_NO_TITLE);

  setContentView(R.layout.main);
  initControls();


 }
 protected void onDestroy()
 {
  super.onDestroy();

  Toast.makeText(TestStreaming.this, "...exiting application..." ,Toast.LENGTH_SHORT).show();
  if ( audioStreamer != null) 
  {
   audioStreamer.interrupt();
  }

 }

 private void initControls()
 {
  textStreamed = (TextView) findViewById(R.id.text_kb_streamed);
  streamButton = (Button) findViewById(R.id.button_stream);
  streamButton.setOnClickListener(new View.OnClickListener()
  {
   public void onClick(View view)
   {

    String urlstring2 = "url to a shoutcase stream";


    Toast
    .makeText(
      TestStreaming.this,
       "The following stream is about to start" + urlstring2,   
      Toast.LENGTH_LONG).show();
    startStreamingAudio(urlstring2);
   }
  });

  playButton = (ImageButton) findViewById(R.id.button_play);
  playButton.setEnabled(false);
  playButton.setOnClickListener(new View.OnClickListener()
  {
   public void onClick(View view)
   {
    if (audioStreamer.getMediaPlayer().isPlaying())
    {
     audioStreamer.getMediaPlayer().pause();
     playButton.setImageResource(R.drawable.button_play);
    } else
    {
     audioStreamer.getMediaPlayer().start();
     audioStreamer.startPlayProgressUpdater();
     playButton.setImageResource(R.drawable.button_pause);
    }
    isPlaying = !isPlaying;
   }
  });
 }
 private void startStreamingAudio(String urlstring) {
  try { 
   final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar);
   if ( audioStreamer != null) {
    audioStreamer.interrupt();
   }
   audioStreamer = new StreamingMediaPlayer(this,textStreamed, playButton, streamButton,progressBar);
   audioStreamer.startStreaming(urlstring,5208, 216);
   streamButton.setEnabled(false);
  } catch (Exception e) 
  {
   Log.e(getClass().getName(), "Error starting to stream audio.", e);                  
  }

 }

 public void onItemSelected(AdapterView parent, View v, int position, long id)
 {
  mSwitcher.setImageResource(mImageIds[position]);
 }

 public void onNothingSelected(AdapterView parent)
 {
 }

 public View makeView()
 {
  ImageView i = new ImageView(this);
  i.setBackgroundColor(0xFF000000);
  i.setScaleType(ImageView.ScaleType.FIT_CENTER);
  i.setLayoutParams(new ImageSwitcher.LayoutParams(
    LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
  return i;
 }

 private ImageSwitcher mSwitcher;

 public class ImageAdapter extends BaseAdapter
 {
  public ImageAdapter(Context c)
  {
   mContext = c;
  }

  public int getCount()
  {
   return mThumbIds.length;
  }

  public Object getItem(int position)
  {
   return position;
  }

  public long getItemId(int position)
  {
   return position;
  }

  public View getView(int position, View convertView, ViewGroup parent)
  {
   ImageView i = new ImageView(mContext);

   i.setImageResource(mThumbIds[position]);
   i.setAdjustViewBounds(true);
   i.setLayoutParams(new Gallery.LayoutParams(
     LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
   i.setBackgroundResource(R.drawable.picture_frame);
   return i;
  }

  private Context mContext;

 }

 private Integer[] mThumbIds =
 { R.drawable.calculator, R.drawable.calendar, R.drawable.camera };

 private Integer[] mImageIds =
 { R.drawable.calculator, R.drawable.calendar, R.drawable.camera };

}

使用StreamingMediaPlayer类,如下所示 -

package com.troubadorian.android.teststreaming;

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.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;

/**
 * MediaPlayer does not yet support streaming from external URLs so this class
 * provides a pseudo-streaming function by downloading the content incrementally
 * & playing as soon as we get enough audio in our temporary storage.
 */
public class StreamingMediaPlayer
{

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



 private TextView textStreamed;

 private ImageButton playButton;

 private ProgressBar progressBar;

 // Track for display by progressBar
 private long mediaLengthInKb, mediaLengthInSeconds;

 private int totalKbRead = 0;

 // Create Handler to call View updates on the main UI thread.
 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)
 {
  this.context = context;
  this.textStreamed = textStreamed;
  this.playButton = playButton;
  this.progressBar = progressBar;
 }

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

  this.mediaLengthInKb = mediaLengthInKb;
  this.mediaLengthInSeconds = mediaLengthInSeconds;

  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
  */
 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);
  }

  downloadingMediaFile = new File(context.getCacheDir(),
    "downloadingMedia.dat");

  // Just in case a prior deletion failed because our code crashed or
  // something, we also delete any previously
  // downloaded file to ensure we start fresh. If you use this code,
  // always delete
  // no longer used downloads else you'll quickly fill up your hard disk
  // memory. Of course, you can also
  // store any previously downloaded file in a separate data cache for
  // instant replay if you wanted as well.
  if (downloadingMediaFile.exists())
  {
   downloadingMediaFile.delete();
  }

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

   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++) + ".dat");

   // We double buffer the data to avoid potential read/write errors
   // that could happen if the
   // download thread attempted to write at the same time the
   // MediaPlayer was trying to read.
   // For example, we can't guarantee that the MediaPlayer won't open a
   // file for playing and leave it locked while
   // the media is playing. This would permanently deadlock the file
   // download. To avoid such a deadloack,
   // we move the currently loaded data to a temporary buffer file that
   // we start playing while the remaining
   // data downloads.
   moveFile(downloadingMediaFile, bufferedFile);

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

   mediaPlayer = createMediaPlayer(bufferedFile);

   // We have pre-loaded enough content and started the MediaPlayer so
   // update the buttons & progress meters.
   mediaPlayer.start();
   startPlayProgressUpdater();
   playButton.setEnabled(true);
  } 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;
   }
  });

  // It appears that for security/permission reasons, it is better to pass
  // a FileDescriptor rather than a direct path to the File.
  // Also I have seen errors such as "PVMFErrNotSupported" and
  // "Prepare failed.: status=0x1" if a file path String is passed to
  // setDataSource(). So unless otherwise noted, we use a FileDescriptor
  // here.
  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
  {
   // First determine if we need to restart the player after
   // transferring data...e.g. perhaps the user pressed pause
   boolean wasPlaying = mediaPlayer.isPlaying();
   int curPosition = mediaPlayer.getCurrentPosition();

   // Copy the currently downloaded content to a new buffered File.
   // Store the old File for deleting later.
   File oldBufferedFile = new File(context.getCacheDir(),
     "playingMedia" + counter + ".dat");
   File bufferedFile = new File(context.getCacheDir(), "playingMedia"
     + (counter++) + ".dat");

   // This may be the last buffered File so ask that it be delete on
   // exit. If it's already deleted, then this won't mean anything. If
   // you want to
   // keep and track fully downloaded files for later use, write
   // caching code and please send me a copy.
   bufferedFile.deleteOnExit();
   moveFile(downloadingMediaFile, bufferedFile);

   // Pause the current player now as we are about to create and start
   // a new one. So far (Android v1.5),
   // this always happens so quickly that the user never realized we've
   // stopped the player and started a new one
   mediaPlayer.pause();

   // Create a new MediaPlayer rather than try to re-prepare the prior
   // one.
   mediaPlayer = createMediaPlayer(bufferedFile);
   mediaPlayer.seekTo(curPosition);

   // Restart if at end of prior buffered content or mediaPlayer was
   // previously playing.
   // NOTE: We test for < 1second of data because the media player can
   // stop when there is still
   // a few milliseconds of data left to play
   boolean atEndOfFile = mediaPlayer.getDuration()
     - mediaPlayer.getCurrentPosition() <= 1000;
   if (wasPlaying || atEndOfFile)
   {
    mediaPlayer.start();
   }

   // Lastly delete the previously playing buffered File as it's no
   // longer needed.
   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()
   {
    textStreamed.setText((totalKbRead + " Kb read"));
    float loadProgress = ((float) totalKbRead / (float) mediaLengthInKb);
    progressBar.setSecondaryProgress((int) (loadProgress * 100));
   }
  };
  handler.post(updater);
 }

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

    // Delete the downloaded File as it's now been transferred to
    // the currently playing buffer file.
    downloadingMediaFile.delete();
    textStreamed
      .setText(("Audio full loaded: " + totalKbRead + " Kb read"));
   }
  };
  handler.post(updater);
 }

 public MediaPlayer getMediaPlayer()
 {
  return mediaPlayer;
 }

 public void startPlayProgressUpdater()
 {
  float progress = (((float) mediaPlayer.getCurrentPosition() / 1000) / mediaLengthInSeconds);
  progressBar.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[8192];
    /* changing the size of the buffer */

    byte[] buff = new byte[16384];

    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());
  }
 }
}

和布局文件如下 -

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <LinearLayout
 android:layout_height="wrap_content"
 android:layout_width="fill_parent"
 android:id="@+id/Logo"
 android:orientation="vertical">


 <LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10px">

 <TextView   android:id="@+id/text_kb_streamed"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:textStyle="bold"
    android:text="...streaming audio..."/>

  <Button android:id="@+id/button_stream"
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content"
   android:layout_marginTop="10px"
   style="?android:attr/buttonStyleSmall" 
   android:text="Start Streaming"/>


 <ProgressBar android:id="@+id/progress_bar"  
    android:layout_width="200px"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    style="?android:attr/progressBarStyleHorizontal"/>

 <ImageButton android:id="@+id/button_play"
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content"
     android:layout_marginTop="5px"
     style="?android:attr/buttonStyleSmall" 
     android:src="@drawable/button_pause"/>

</LinearLayout>

  </LinearLayout>
  <ViewFlipper
 android:id="@+id/MainFlipper"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:layout_below="@+id/Logo"
 android:layout_marginBottom="37dip">
  </ViewFlipper>
  <FrameLayout
 android:id="@+id/MediaPlayer"
 android:layout_width="fill_parent"
 android:layout_height="130dip"
 android:layout_alignParentBottom="true"
 android:layout_centerHorizontal="true">
  </FrameLayout>
</RelativeLayout>

但是相同的代码在Android 2.2中不起作用。可以修复到2.2运行吗?

这是我得到的错误 -

E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423): Error initializing the MediaPlayer.
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423): java.io.IOException: setDataSourceFD failed.: status=0x80000000
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at android.media.MediaPlayer.setDataSource(Native Method)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at android.media.MediaPlayer.setDataSource(MediaPlayer.java:749)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at com.troubadorian.android.teststreaming.StreamingMediaPlayer.createMediaPlayer(StreamingMediaPlayer.java:272)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at com.troubadorian.android.teststreaming.StreamingMediaPlayer.startMediaPlayer(StreamingMediaPlayer.java:237)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at com.troubadorian.android.teststreaming.StreamingMediaPlayer.access$2(StreamingMediaPlayer.java:212)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at com.troubadorian.android.teststreaming.StreamingMediaPlayer$2.run(StreamingMediaPlayer.java:190)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at android.os.Handler.handleCallback(Handler.java:587)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at android.os.Handler.dispatchMessage(Handler.java:92)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at android.os.Looper.loop(Looper.java:123)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at android.app.ActivityThread.main(ActivityThread.java:4627)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at java.lang.reflect.Method.invokeNative(Native Method)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at java.lang.reflect.Method.invoke(Method.java:521)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at dalvik.system.NativeStart.main(Native Method)
I/global  ( 1423): Default buffer size used in BufferedInputStream constructor. It would be better to be explicit if an 8k buffer is required.
I/global  ( 1423): Default buffer size used in BufferedOutputStream constructor. It would be better to be explicit if an 8k buffer is required.
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423): Buffered File path: /data/data/com.troubadorian.android.teststreaming/cache/playingMedia34.dat
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423): Buffered File length: 193188
E/MediaPlayer( 1423): Unable to to create media player
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423): Error initializing the MediaPlayer.
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423): java.io.IOException: setDataSourceFD failed.: status=0x80000000
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at android.media.MediaPlayer.setDataSource(Native Method)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at android.media.MediaPlayer.setDataSource(MediaPlayer.java:749)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at com.troubadorian.android.teststreaming.StreamingMediaPlayer.createMediaPlayer(StreamingMediaPlayer.java:272)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at com.troubadorian.android.teststreaming.StreamingMediaPlayer.startMediaPlayer(StreamingMediaPlayer.java:237)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at com.troubadorian.android.teststreaming.StreamingMediaPlayer.access$2(StreamingMediaPlayer.java:212)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at com.troubadorian.android.teststreaming.StreamingMediaPlayer$2.run(StreamingMediaPlayer.java:190)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at android.os.Handler.handleCallback(Handler.java:587)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at android.os.Handler.dispatchMessage(Handler.java:92)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at android.os.Looper.loop(Looper.java:123)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at android.app.ActivityThread.main(ActivityThread.java:4627)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at java.lang.reflect.Method.invokeNative(Native Method)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at java.lang.reflect.Method.invoke(Method.java:521)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423):       at dalvik.system.NativeStart.main(Native Method)
I/global  ( 1423): Default buffer size used in BufferedInputStream constructor. It would be better to be explicit if an 8k buffer is required.
I/global  ( 1423): Default buffer size used in BufferedOutputStream constructor. It would be better to be explicit if an 8k buffer is required.
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423): Buffered File path: /data/data/com.troubadorian.android.teststreaming/cache/playingMedia35.dat
E/com.troubadorian.android.teststreaming.StreamingMediaPlayer( 1423): Buffered File length: 194588
E/MediaPlayer( 1423): Unable to to create media player

请帮忙。

2 个答案:

答案 0 :(得分:4)

我跟踪了你的错误...... 查看Froyo的源代码,在frameworks / base / media / libmedia / mediaplayer.cpp中,它归结为这个函数。 此时,显然player参数为NULL

status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player)
{
    status_t err = UNKNOWN_ERROR;
    sp<IMediaPlayer> p;
    { // scope for the lock
        Mutex::Autolock _l(mLock);

        if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
                (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
            LOGE("setDataSource called in state %d", mCurrentState);
            return INVALID_OPERATION;
        }

        clear_l();
        p = mPlayer;
        mPlayer = player;
        if (player != 0) {
            mCurrentState = MEDIA_PLAYER_INITIALIZED;
            err = NO_ERROR;
        } else {
            LOGE("Unable to to create media player");
        }
    }

    if (p != 0) {
        p->disconnect();
    }

    return err;
}

来自同一文件中的函数status_t MediaPlayer::setDataSource(const char *url, const KeyedVector<String8, String8> *headers),它可以实例化IMediaPlayerService,但create方法由于某种原因必定已失败...

Android doc的一件事: 完成MediaPlayer后,您应该调用release()来释放资源。如果未释放,则过多的MediaPlayer实例可能会导致异常。

也许你应该检查createMediaPlayer函数只被调用一次?我想Eclair也会失败,但可能值得研究......

或许您所看到的是here

所描述的内容

希望有所帮助

答案 1 :(得分:0)

我的MediaPlayer代码遇到了同样的错误。我有各种结果播放位于原始目录中的简单test.ogg文件。我的AVD能够播放文件,SE Xperia Mini Pro播放声音,但我的三星SII使用下面的简单代码崩溃了。

MediaPlayer mediaPlayer = MediaPlayer.create(this.getBaseContext(), R.raw.test);
mediaPlayer.start();

我收到了和你一样的错误

Error initializing the MediaPlayer.
java.io.IOException: setDataSourceFD failed.

我进一步测试了通过本地网络播放该文件的两种手机的预期结果(SE播放文件而三星无法播放)。这几乎意味着不同的Android版本无法播放相同的声音,您需要使用不同的音频格式。

如果手机无法原生播放该文件,我唯一的解决方法是重新取样音频。