- 浏览: 912595 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
天天来注册:
...
try catch finally 用法 -
tadpole_java:
谢谢你的分享。
二十七、Qt数据库(七)QSqlRelationalTableModel(转) -
359449749tan:
android之EditText文本监听(addTextChangedListener) -
michael_wang:
人过留名 多谢分享
Android NOtification 使用 -
wilsonchen:
wangqi0614 写道这个删除是删除所有的把?能不能值删除 ...
Android的SharedPreferences保存与删除数据简单实例
今天比较开心,看到论坛上很多人都在询问如何写网络流媒体播放器?是否需要两个播放器轮流交替?因为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);
}
}
}
}
/**
* 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);
}
}
}
}
发表评论
-
android push
2011-11-16 15:24 1604所有技术的概要介绍,并讲解了android2.2的新功能C2D ... -
[Android UI界面] 怎么设置popupwindow动画效果?
2011-07-16 12:34 1116http://www.eoeandroid.com/threa ... -
android解析XML
2011-07-11 11:32 1847为移动设备构建 Java 应用程序 Michael ... -
对话框和浮动Activity
2011-07-06 12:07 953在Android中,我们可以通 ... -
升级android sdk时A folder failed to be renamed or moved 错误的解决
2011-06-28 09:22 1695Downloading Android SDK Tools, ... -
android push机制-C2DM
2011-06-27 16:54 1518http://bigcat.easymorse.com/?p= ... -
XML解析
2011-06-24 15:45 846HttpPost httpRequest=new HttpP ... -
android上传图片到服务器,求服务器那边和android的Activity的完整代码。
2011-06-22 12:30 3247服务器端servlet代码:public void doPos ... -
android HTTP 通信, XML 解析, 通过 Hander 实现异步消息处理 (1)
2011-06-08 16:44 1013介绍 在 Android 中与服务端做 HTTP 通信,解析 ... -
eclipse 中android中文doc配置
2011-05-13 14:39 957http://hi.baidu.com/huangbz321/ ... -
jesson.shen浅谈HTTP中实现UDP/TCP
2011-05-10 16:38 934http://350526.blog.51cto.com/34 ... -
android 网络编程
2011-05-04 19:54 775http://hi.baidu.com/lfcaolibin/ ... -
android解析xml文件的方式
2011-05-01 22:54 885http://hi.baidu.com/%B2%BD%C2%C ... -
android进程间通信:使用AIDL
2011-04-13 10:59 865http://blog.csdn.net/saintsword ... -
Android实现开机自动运行程序
2011-04-12 18:00 1122有些时候,应用需要在开机时就自动运行,例如某个自动从网上更新内 ... -
android 如何从sqlite读取数据到spinner下拉中显示
2011-04-12 14:56 5581import android.app.Activity; im ... -
Android的SharedPreferences保存与删除数据简单实例
2011-04-12 11:37 520281、创建SharedPreferences对象: Stri ... -
Android使用LayoutInflater动态加载布局和操作控件
2011-04-11 16:22 1000http://www.cnmsdn.com/html/2010 ... -
dialog
2011-04-08 18:32 852http://topic.csdn.net/u/2011031 ... -
Android NOtification 使用
2011-04-07 15:55 3842一、 Notification 简介 ...
相关推荐
标题与描述中的关键词“Android流媒体播放器”指向了在Android平台上实现流媒体播放功能的特定技术领域。本文将深入探讨这一主题,包括其技术原理、实现方式以及关键代码示例,旨在为开发者提供一份详尽的技术指南。...
一款基于ffmpeg的android流媒体播放器
该项目是一款基于Java语言的EasyPlayerPro-Android流媒体播放器设计源码,包含219个文件,涵盖82个PNG图片文件、56个Java源文件、51个XML配置文件、9个SO库文件、4个Gradle构建文件以及少量其他类型文件。...
【Android流媒体播放器设计与实现】 在移动设备领域,Android操作系统因其开源特性和广泛的市场占有率,成为开发者构建各种应用程序的首选平台。特别是在多媒体应用方面,Android提供了丰富的API供开发者使用,但其...
实验结果显示,基于FFmpeg的Android流媒体播放器不仅能够流畅播放本地和远程视频,而且内存占用低,适合嵌入其他应用程序。这种播放器具有广阔的应用前景,可以用于视频分享、在线教育、远程监控等多个领域。 综上...
在Android平台上,调用系统默认播放器来处理RTSP(Real Time Streaming Protocol)流媒体是一项常见的任务。RTSP是一种协议,用于控制多媒体数据的实时传输,通常用于在线视频流服务。以下将详细介绍如何在Android...
在总体设计上,客户端(Android流媒体播放器)通过网络连接与服务端(GNUMP3d服务器)建立通信,请求并接收音频流数据。这一过程涉及到网络协议,如TCP/IP和HTTP,以及可能的流传输协议如RTSP或HTTP Live Streaming ...
在这个项目中,服务端可能负责处理媒体文件的上传、下载、流媒体传输等功能。 4. **多媒体播放器客户端**:"VideoPlayClient"可能是客户端应用程序的主体部分,包含用户界面和与服务端交互的逻辑。客户端可能利用...
在Android平台上设计一个流媒体播放器是一项复杂但充满挑战性的任务。这个项目主要涉及使用Android自带的MediaPlayer类来实现流媒体的播放功能。下面将详细阐述这个过程中的关键知识点。 一、Android MediaPlayer类...
在Android平台上,实时传输协议(Real-Time Messaging Protocol, RTMP)通常用于流媒体服务,例如直播视频。这个“Android端RTMP播放工具”是一个专为Android设备设计的应用,能够接收并播放通过RTMP协议传输的视频...
Android-Liunx 平台网络流媒体播放器的设计 Android-Liunx 平台网络流媒体播放器的设计是基于 Android 系统的音乐流媒体播放器的设计与实现和 Linux 系统音乐流媒体服务器 GNUMP3d 的搭建。该设计主要面向 Android...
基于Android的流媒体播放器项目 项目概述 本项目是一个基于Android平台的流媒体播放器,专注于提供高质量的视频和音频播放体验。项目集成了多种播放器功能,包括视频和音频流的播放、缓冲管理、播放控制、性能...
Android Liunx平台网络流媒体播放器的设计 本文主要讨论了Android Liunx平台网络流媒体播放器的设计和实现,以及Linux系统音乐流媒体服务器GNUMP3d的搭建。其中,音乐流媒体播放器采用了Android开源系统技术,利用...
在Android平台上,开发一个基于Android的媒体播放器是一项常见的任务,它涉及到许多核心技术和组件的集成。本项目名为“基于Android的媒体播放器”,旨在提供一个功能丰富的多媒体播放解决方案,包括文件浏览、背景...
"Android_liunx平台网络流媒体播放器的设计" 关于Android_liunx平台网络流媒体播放器的设计毕业论文,主要涉及到Android系统上音乐流媒体播放器的设计与实现和Linux系统音乐流媒体服务器GNUMP3d的搭建。论文中详细...
该RTSP播放器实现了主流RTSP播放器的基本功能,并有所拓展: 1、RTSP 标准码流(包括音视频)的实时预览播放; 2、网络数据流的断线重连; 3、对存储文件的解码播放以及控制; 4、音视频码流的同步存储...
《基于Android内核的流媒体播放器分析与研究》这篇文献主要探讨了Android操作系统在流媒体支持方面的局限性,并提出了通过移植开源流媒体解决方案Live555到Android内核中来增强其流媒体功能的方法。文章指出,...