首页 > 系统 > Android > 正文

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

2020-07-28 14:50:20
字体:
来源:转载
供稿:网友

本文实例讲述了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;}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表