Android实现使用流媒体播放远程mp3文件的方法

发布时间:2019-10-14 09:02 来源:互联网 当前栏目:网站服务器

本文实例讲述了Android实现使用流媒体播放远程mp3文件的方法。分享给大家供大家参考,具体如下:

package com.shadow.util;
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 java.util.ArrayList;
import java.util.List;
import com.shadow.service.AudioPlayService.LocalBinder;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
/**
 * 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 extends Service{
  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;
  private static Runnable r;
  private static Thread playerThread;
  private LocalBinder localBinder = new LocalBinder();
  private MediaPlayer player;
  private boolean isPause = false;   //播放器是否处于暂停状态
  private boolean isSame = false;   //所点播歌曲是否是当前播放歌曲
  private Integer position = -1;    //设置播放标记
  private List<String> music_name;   //歌曲列表
  private List<String> music_path;
   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;
    r = new Runnable() {
      public void run() {
        try {
          Log.i("downloadAudioIncrement", "downloadAudioIncrement");
          downloadAudioIncrement(mediaUrl);
        } catch (IOException e) {
          Log.e(getClass().getName(), "Unable to initialize the MediaPlayer for fileUrl=" + mediaUrl, e);
          return;
        }
      }
    };
    playerThread = new Thread(r);
    playerThread.start();
    //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.addRequestProperty("User-Agent","NSPlayer/10.0.0.4072 WMFSDK/10.0");
    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;
    }
  }
  public void pausePlayer(){
    try {
      getMediaPlayer().pause();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  public void startPlayer(){
    getMediaPlayer().start();
  }
  public void stopPlayer(){
    getMediaPlayer().stop();
  }
  /**
   * 根据文件创建一个mediaplayer对象
   */
  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;
}


        
 
  • 1、
  • 2、
  • 3、
  • 4、
  • 5、
  • 6、
  • 7、
  • 8、
  • 9、
  • 10、
  • 11、
  • 12、
  • 13、
  • 14、
  • 15、
  • 16、
  • 17、
  • 18、
  • 19、
  • 20、
  • 21、
  • 22、
  • 23、
  • 24、
  • 25、
  • 1、
  • 2、
  • 3、
  • 4、
  • 5、
  • 6、
  • 7、
  • 8、
  • 9、
  • 10、
  • 11、
  • 12、
  • 13、
  • 14、
  • 15、
  • 16、
  • 17、
  • 18、
  • 19、
  • 20、
  • 21、
  • 22、
  • 23、
  • 24、
  • 25、