- 浏览: 433519 次
- 性别:
- 来自: 苏州
文章分类
最新评论
-
yehuiyan8002:
支持中文查询
快熟查找联系人 -
lehehe:
现成的接口,免费试用,http://www.haoservic ...
天气Widget -
D.Z:
android:focusable="false&q ...
CheckBox在ListView 而导致其OnItemClickListener不会被触发 -
freecode:
碰到该问题,CheckBox的android:focusabl ...
CheckBox在ListView 而导致其OnItemClickListener不会被触发 -
echohfut:
哥们,新博客是不是在墙外啊?不能访问。还有你怎么进行博客迁移的 ...
博客 迁移
流媒体播放
之所以为理论篇 因为该篇仅实现了播放功能 但还有一些其他待解决/完善功能 所以称之为理论篇
而且该篇以原理居多 故暂不释放源码
[原理]
写道
其实 原理很简单
1. 下载目标URI
2. 当下载了 96*10/8 Byte 开始播放之
3. 一边播放 一边下载
4. 当下载了 100 byte 暂停播放 重置播放目标 并继续播放
5. 下载完成后 重置播放目标 并继续播放
1. 下载目标URI
2. 当下载了 96*10/8 Byte 开始播放之
3. 一边播放 一边下载
4. 当下载了 100 byte 暂停播放 重置播放目标 并继续播放
5. 下载完成后 重置播放目标 并继续播放
[代码 步骤]
1. 开辟Thread
public void startStreaming(final String mediaUri){ Runnable r = new Runnable(){ @Override public void run() { // TODO Auto-generated method stub try { readStream(mediaUri); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; new Thread(r).start(); }
2. 创建目标URI 并下载之
public void readStream(String mediaUri) throws MalformedURLException, IOException{ URLConnection uc = new URL(mediaUri).openConnection(); uc.connect(); InputStream is = uc.getInputStream(); if(is == null){ //error, InputStream is null } dlMedia = new File(context.getCacheDir(),"downloadingMedia.dat"); if(dlMedia.exists()){ dlMedia.delete(); } FileOutputStream fo = new FileOutputStream(dlMedia); byte buf[] = new byte[16384]; loadByte = 0; do { int numread = is.read(buf); loadByte += numread; if(numread <= 0){//end of stream, so exist break; } fo.write(buf, 0, numread); testMediaBuffer(); } while(true); is.close(); //buffer all stream to MediaPlayer if end of stream transferBufferToMediaPlayer();
3. 根据此刻下载的byte 判断是:开始播放 还是 缓冲下载数据
public void testMediaBuffer(){ Runnable update = new Runnable(){ @Override public void run() { // TODO Auto-generated method stub //initial MediaPlayer if null if(mp == null){ if(loadByte >= INTIAL_KB_BUFFER){ loadByte = 0; startMediaPlayer(); } }//load buffer while 1000 else if(loadByte > BUFFER_KEY_BYTE) { loadByte = 0; transferBufferToMediaPlayer(); } } }; handler.post(update); }
4. 开始播放 并跟踪播放进度
public void startPlayProgressUpdater() { //float progress = mp.getCurrentPosition(); if (mp.isPlaying()) { Runnable notification = new Runnable() { public void run() { startPlayProgressUpdater(); } }; handler.postDelayed(notification,100); } } public 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(dlMedia,bufferedFile); mp = createMediaPlayer(bufferedFile); // We have pre-loaded enough content and started the MediaPlayer so update the buttons & progress meters. mp.start(); startPlayProgressUpdater(); } catch (IOException e) { //Log.e(getClass().getName(), "Error initializing the MediaPlayer.", e); return; } }
5. 缓冲下载数据
private void transferBufferToMediaPlayer() { try { //remember current position int curPosition = mp.getCurrentPosition(); // Copy the currently downloaded content to a new buffered File. Store the old File for deleting later. File bufferedFile = new File(context.getCacheDir(),"playingMedia" + (counter++) + ".dat"); moveFile(dlMedia,bufferedFile); // Pause the current player now as we are about to create and start a new one. So far (Android v1.5), // this always happens so quickly that the user never realized we've stopped the player and started a new one mp.pause(); // Create a new MediaPlayer rather than try to re-prepare the prior one. mp = createMediaPlayer(bufferedFile); mp.seekTo(curPosition); mp.start(); // Lastly delete the previously playing buffered File as it's no longer needed. bufferedFile.delete(); }catch (Exception e) { //error, to print } }
6. 文件移动
private void moveFile(File oldLocation, File newLocation) throws IOException { if ( oldLocation.exists( )) { BufferedInputStream reader = new BufferedInputStream( new FileInputStream(oldLocation) ); BufferedOutputStream writer = new BufferedOutputStream( new FileOutputStream(newLocation, false)); try { byte[] buff = new byte[8192]; int numChars; while ( (numChars = reader.read( buff, 0, buff.length ) ) != -1) { writer.write( buff, 0, numChars ); } } catch( IOException ex ) { throw new IOException("IOException when transferring " + oldLocation.getPath() + " to " + newLocation.getPath()); } finally { try { if ( reader != null ){ writer.close(); reader.close(); } } catch( IOException ex ){ //Log.e(getClass().getName(),"Error closing files when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() ); } } } else { throw new IOException("Old location does not exist when transferring " + oldLocation.getPath() + " to " + newLocation.getPath() ); } }
7. 播放指定目标
private MediaPlayer createMediaPlayer(File mediaFile) throws IOException { MediaPlayer mPlayer = new MediaPlayer(); // 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; }
8. Toast 信息提示:
public void popMsg(String msg){ Toast.makeText(context, msg, Toast.LENGTH_LONG).show(); }
9. done, plx test it, post feedback, thanks
评论
2 楼
gryphone
2010-05-28
bingtian 写道
你好,这个如果已经播放缓冲的,音乐停止了,等缓冲开始多了,音乐还会继续播放吗?
是的啊 但是从效果看不是太好 我现在也在寻找更smooth的方法
1 楼
bingtian
2010-05-28
你好,这个如果已经播放缓冲的,音乐停止了,等缓冲开始多了,音乐还会继续播放吗?
发表评论
-
滑动抽屉 另一种解决办法
2010-07-09 17:43 0滑动抽屉 -
Spinner 定制化 增强版
2010-07-09 14:34 2608Spinner 作为下拉选 ... -
ListView 内容之分批显示
2010-06-25 20:38 5923ListView 内容循环显示 大家试想 假如 ... -
MediaScanner 研究
2010-06-23 15:21 3169MediaScanner 之所以拿MediaSc ... -
CheckBox在ListView 而导致其OnItemClickListener不会被触发
2010-06-22 20:55 19013CheckBox在ListView 而导致其OnItemCli ... -
获取Launcher 启动列表
2010-06-22 10:09 3138获取Launcher 启动列表 即 列出所有Launc ... -
PreferenceActivity 全接触
2010-06-19 12:53 9439PreferenceActivity 为了引入 ... -
android src 下载 编译 安装 全接触
2010-06-12 14:44 0android src - download install ... -
Intent.createChooser() 妙用
2010-06-12 11:14 5955Intent.createChooser(ntent targ ... -
SMS管理:收信箱 发信息 编写新信息
2010-06-07 08:14 14443SMS管理 [功能] 1. 收信箱:显示 ... -
求 android 手机 帮忙测试sms服务系统 谢谢
2010-06-05 08:25 1451Hi guys, 最近一段时间没有更新blog 因为一 ... -
NDK 搭建与HelloWorld
2010-05-19 09:48 3224NDK [前提] 1. Cygwin 用于安装 ... -
自定义字体
2010-05-15 10:49 1220自定义字体: []代码 步骤] 1 ... -
模糊查找 再深入
2010-05-15 09:41 3158模糊查找 再深入 应某位大哥要求 再次对 SQLite ... -
快捷方式Bar + ViewGroup - 自定义
2010-05-09 09:20 2470TabActivity - 自定义 其实 这篇感觉极鸡 ... -
View 拖动&插入 研究
2010-05-09 07:14 3983View 拖动&插入 即: ... -
带图标 快捷键 Menu - 终极版
2010-05-04 20:23 1837Menu 改头换面 扩展如下: 1. 图标化文字 2 ... -
*.gif 解码 - 实践
2010-05-02 18:58 1733*.gif decode 前面已经说过 今天不打算再说了 ... -
*.gif 解码 - 理论
2010-05-01 21:11 1522我们知道Android 默认是不支持*.gif 的 但是 ... -
shortcut+livefolder
2010-04-19 13:08 1493shortcut+livefolder Live ...
相关推荐
标题中的“关于播放流媒体文件续”提示我们这篇博文可能是对之前讨论的流媒体播放技术的延续或深入探讨。在IT行业中,流媒体文件是指在传输过程中被连续接收和播放的多媒体内容,如在线视频、音频等。这些文件通常...
总的来说,"基于P2P的流媒体技术"这篇论文应该涵盖了P2P流媒体的核心原理、实现技术和潜在问题,对于理解这个领域的理论和实践都有重要的参考价值。通过深入阅读和分析,我们可以更全面地了解如何利用P2P技术来优化...
总的来说,这四篇论文全面地探讨了P2P技术与流媒体的结合,从理论到实践,从模型设计到实际应用,为理解P2P在流媒体领域的潜力提供了深入的洞察。通过深入阅读这些论文,读者可以深入了解P2P流媒体技术的工作原理,...
通过深入理解和学习这个基于P2P的流媒体点播源码,开发者不仅可以掌握P2P网络的基本原理,还能了解到如何将这些理论应用于实际的流媒体点播系统中。这对于理解网络通信、流媒体处理以及跨平台开发具有很高的学习价值...
综上所述,流媒体在WCDMA网中的应用研究涉及了基础理论、体系结构设计、关键技术和应用案例等多方面内容。随着移动通信技术的不断发展和网络带宽的提升,流媒体技术将在移动互联网领域发挥越来越重要的作用。本篇...
综上所述,这篇文章详细探讨了分层P2P流媒体中的数据分配问题,并给出了有效的算法解决方案,这些内容对于理解P2P流媒体技术以及设计高效的数据分配算法具有较高的理论价值和实践意义。通过阅读这篇文献,IT专业人员...
总的来说,这篇论文深入研究了基于智能手机的流媒体客户端的开发,涵盖了从技术标准、系统平台到具体实现的各个环节。对于想要了解和开发移动流媒体应用的工程师和研究人员来说,具有很高的参考价值。它不仅提供了...
总的来说,这篇文档提供了一个完整的流媒体服务器构建教程,涵盖了从基础的DNS设置到专业流媒体服务器的安装和调试。通过这样的实践,读者不仅能学习到理论知识,还能积累实际操作经验,为日后搭建和管理流媒体系统...
本篇毕业设计旨在通过数据测量和分析,揭示影响在线视频流媒体质量的关键因素,为优化服务质量提供理论依据。 首先,研究内容主要包括对视频流媒体业务的基本特征的了解。这涵盖了流媒体技术的工作原理,如流式传输...
《基于网络处理器的流媒体应用架构模型(VPL)》这篇文章主要探讨了在网络处理器上实现流媒体应用的...这篇研究为网络处理器上的流媒体应用提供了重要的理论基础和实践指导,对于理解和优化此类应用的性能具有重要意义。
【标题】:“基于FFmpeg的稳定应用层组...总的来说,这篇论文深入研究了基于FFmpeg的稳定应用层组播流媒体直播系统,旨在解决组播技术在实际应用中遇到的稳定性问题,为构建高效、可靠的流媒体服务提供理论和技术支持。
在Android开发中,实现视频流媒体播放是一个常见的需求,尤其涉及到RTSP(Real Time Streaming Protocol)和HTTP协议时。IJKplayer是一个广受欢迎的开源媒体播放器库,它为开发者提供了强大的功能,支持多种视频格式...
《Android系统中RTMP流媒体直播的设计与实现》这篇文献主要探讨了在Android平台上利用RTMP协议进行高清音视频实时传输的技术方案,特别是在无线通信环境恶劣的地区如何保证远程视频监控的质量。RTMP(Real-Time ...
2. **在线视频流媒体**:Netflix、Amazon Prime Video等平台通过提供广泛的内容选择,包括经典电影、独立电影、国际剧集等,满足了不同观众群体的多样化需求,而非仅仅依赖于几部超级大片。 3. **电子商务**:...