今天比较开心,看到论坛上很多人都在询问如何写网络流媒体播放器?是否需要两个播放器轮流交替?因为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);

}

}

}



}

更多相关文章

  1. ArcGIS for Android(安卓)支持模拟器开发
  2. Android应用程序窗口(Activity)的运行上下文环境(Context)的创建过程
  3. Android(安卓)Wear Preview- 创建通知(Creating Notifications fo
  4. Android(安卓)4.4以后设置状态栏颜色
  5. android5 sdk 下载地址大全
  6. Android(安卓)Studio V0.2.x For Windows下载地址
  7. Android视频教学下载大全(VeryCD上)
  8. ndk下载链接汇总
  9. Android:BadTokenException: Unable to add window

随机推荐

  1. 自定义ListView中的分割线(转)
  2. Android开发学习之Animation之Android帧
  3. 在iPhone 和 Android设备上,HTML5的关于键
  4. 【Android经典入门教程-下(bill译)】
  5. android AQuery框架执行回调 AjaxCallbac
  6. android中使用MediaPlayer播放视频
  7. 查看Android进程内存资源信息
  8. Linearlayout的android:divider属性
  9. 《Android高级开发》课程总结及知识点复
  10. Button设置elevation阴影