今天比较开心,看到论坛上很多人都在询问如何写网络流媒体播放器?是否需要两个播放器轮流交替?因为Android没有提供像J2me那样的流创建的形式,总之还是不太好写,最近也在研究android流媒体播放,这里提供一个很早之前写的demo,以供大家相互学习和参考。
/** * Android提供的接口仍然是不能直接通过流创建Player,但是Android提供了很全面的文件系统接口,现在用一种新的方法来解决: <br> * <1>,把下载下来的数据先写到临时的文件中 <br> * <2>,用临时文件创建Player<br> * todo: <br> * <1>,清理没有用的临时文件。<br> * <2>,暂停逻辑的优化。---抛出异常。。。。<br> * <3>,分段下载的逻辑处理,这和<2>有关系。<br> * <4>,整体优化 * * @author shenrenkui * */ public class AudioPlayer implements OnErrorListener, OnBufferingUpdateListener, MediaPlayer.OnCompletionListener { private static final String TAG = "AudioPlayer"; private MediaPlayer mPlayer; private String current; private static final int MIN_BUFF = 100 * 1024; private int totalKbRead = 0; private Handler handler = new Handler(); private File DLTempFile; private File BUFFTempFile; private final String TEMP_DOWNLOAD_FILE_NAME = "tempMediaData"; private final String TEMP_BUFF_FILE_NAME = "tempBufferData"; private final String FILE_POSTFIX = ".dat"; private final int PER_READ = 1024; private boolean pause; private boolean stop; private final int UNKNOWN_LENGTH = -1; private Handler mHandler = null; public void setHandler(Handler handler) { mHandler = handler; } public void play(final String path) { downloadOver = false; totalKbRead = 0; try { Log.v(TAG, "playing: " + path); if (path.equals(current) && mPlayer != null) { mPlayer.start(); return; } current = path; mPlayer = null; new PlayThread(current).start(); } catch (Exception e) { } } private void setListener() { if (mPlayer != null) { mPlayer.setOnErrorListener(this); mPlayer.setOnBufferingUpdateListener(this); mPlayer.setOnCompletionListener(this); } } /** * 下载数据,分段下载 * todo:联网方式和分段 * @param mediaUrl * @param start * @param end */ private void playFromNet(String mediaUrl, int start, int end) { URLConnection cn = null; FileOutputStream out = null; InputStream is = null; try { cn = new URL(mediaUrl).openConnection(); cn.connect(); is = cn.getInputStream(); int mediaLength = cn.getContentLength(); if (is == null) { return; } deleteTempFile(true); DLTempFile = File.createTempFile(TEMP_DOWNLOAD_FILE_NAME, FILE_POSTFIX); out = new FileOutputStream(DLTempFile); byte buf[] = new byte[PER_READ]; int readLength = 0; while (readLength != -1 && !stop) { if (pause) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } continue; } readLength = is.read(buf); if (readLength > 0) { try { out.write(buf, 0, readLength); totalKbRead += readLength; } catch (Exception e) { Log.e(TAG, e.toString()); } } dealWithBufferData(); } if (totalKbRead == mediaLength) { downloadOver = true; dealWithLastData(); // 删除临时文件 if (DLTempFile != null && DLTempFile.exists()) { DLTempFile.delete(); } } } catch (MalformedURLException e) { Log.e(TAG, e.toString()); } catch (IOException e) { Log.e(TAG, e.toString()); } finally { if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } } private boolean downloadOver = false; private boolean wasPlayed = false; private void dealWithBufferData() { if (mPlayer == null || !wasPlayed) { if (totalKbRead >= MIN_BUFF) { try { startMediaPlayer(); } catch (Exception e) { } } } else if (mPlayer.getDuration() - mPlayer.getCurrentPosition() <= 1000) { deleteTempFile(true); transferBufferToMediaPlayer(); } } private void startMediaPlayer() { try { deleteTempFile(true); BUFFTempFile = File.createTempFile(TEMP_BUFF_FILE_NAME, FILE_POSTFIX); FileSystemUtil.copyFile(DLTempFile, BUFFTempFile); mPlayer = new MediaPlayer(); setListener(); mPlayer.setDataSource(BUFFTempFile.getAbsolutePath()); mPlayer.prepare(); mPlayer.start(); wasPlayed = true; } catch (IOException e) { } } private void transferBufferToMediaPlayer() { try { boolean wasPlaying = mPlayer.isPlaying(); int curPosition = mPlayer.getCurrentPosition(); mPlayer.pause(); BUFFTempFile = File.createTempFile(TEMP_BUFF_FILE_NAME, FILE_POSTFIX); FileSystemUtil.copyFile(DLTempFile, BUFFTempFile); mPlayer = new MediaPlayer(); mPlayer.setDataSource(BUFFTempFile.getAbsolutePath()); mPlayer.prepare(); mPlayer.seekTo(curPosition); boolean atEndOfFile = mPlayer.getDuration() - mPlayer.getCurrentPosition() <= 1000; if (wasPlaying || atEndOfFile) { mPlayer.start(); } } catch (Exception e) { } } private void dealWithLastData() { Runnable updater = new Runnable() { public void run() { transferBufferToMediaPlayer(); } }; handler.post(updater); } public void onCompletion(MediaPlayer mp) { if (mHandler != null) { mHandler.sendEmptyMessage(Preferences.MEDIA_ENDED); } } public boolean onError(MediaPlayer mediaPlayer, int what, int extra) { if (mediaPlayer != null) { mediaPlayer.stop(); mediaPlayer.release(); } if (mHandler != null) { mHandler.sendEmptyMessage(Preferences.MEDIA_ERROR); } return true; } public void onBufferingUpdate(MediaPlayer arg0, int percent) { Log.d(TAG, "onBufferingUpdate called ---> percent:" + percent); if (mHandler != null) { mHandler.sendEmptyMessage(Preferences.EMDIA_BUFF_CHANGE); } } private class PlayThread extends Thread { private String url; PlayThread(String url) { this.url = url; } public void run() { if (!URLUtil.isNetworkUrl(url)) { mPlayer = new MediaPlayer(); setListener(); try { // if (url.startsWith("content://")) { // mPlayer.setDataSource(MediaPlayService.this, Uri // .parse(url)); // } else { mPlayer.setDataSource(url); // } mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); setVolume(0f); mPlayer.prepare(); mPlayer.start(); } catch (IllegalArgumentException e) { Log.e(TAG, e.toString()); } catch (IllegalStateException e) { Log.e(TAG, e.toString()); } catch (IOException e) { Log.e(TAG, e.toString()); } } else { playFromNet(url, 0, UNKNOWN_LENGTH); } } } }