Android应用开发技巧|MediaPlayer中设定数据源的几种方法

作者:孔祥辉
前言
MediaPlayer类是android的sdk中实现多媒体支持的非常重要的一部分。内嵌了 ,支持等几种格式。对其的应用是我们通常情况下实现多媒体播放的必经之路。本文简单针对该类型对象的应用简单介绍并比较了7种设定数据源的方法。

正文
MediaPlayer类包含了7种设定数据源的方法,如下:
1.void setDataSource(String path)
设定使用的数据源(文件路径或http/rtsp地址)


2.void setDataSource(FileDescriptorfd, long offset, long length)
设定使用的数据源(filedescriptor)


3.voidsetDataSource(FileDescriptor fd)
设定使用的数据源(filedescriptor)


4.void setDataSource(Contextcontext, Uri uri)
设定一个如Uri内容的数据源


5.static MediaPlayercreate(Context context, Uri uri)
根据给定的uri方便的创建MediaPlayer对象的方法.


6.static MediaPlayercreate(Context context, int resid)
根据给定的资源id方便的创建MediaPlayer对象的方法.


7.static MediaPlayercreate(Context context, Uri uri, SurfaceHolder holder)
根据给定的uri方便的创建MediaPlayer对象的方法。

不难看出,这7个方法分属两类。其中setDataSource针对同一个MediaPlayer实例进行设定,修改它的数据源。而create实际上是类方法,它们返回一个具有特定数据源的新的MediaPlayer实例。
刚入手练习的时候,由于MediaPlayer对象的各方法都有其特定的可接受状态,很容易由于不当的方法调用产生运行时错误(如下图)。这种情况下,一个新生成的且状态确定的(create成功返回的实例处于Prepared状态,这也意味着不允许再调用prepare()方法)实例可以避免很多麻烦。







然而更多的时候,出于对资源或其他一些问题的考虑,我们都需要重用一个实例。这个时候就必须对setDataSource()方法的使用有所了解。这里我们先讨论一些可能存在的问题及如何解决,然后辅以实例以助大家更好的理解。
1.voidsetDataSource(FileDescriptor fd, long offset, long length) 与voidsetDataSource(FileDescriptor fd) 的关系:这两个方法实际上是相同的,后者是对前者的封装。但是,后者调用前者时采用了默认的参数offset和length,这就导致有些时候会出现数据源设定失败。一般情况下,还是推荐使用前者。


2.数据源参数(fd,path,uri,resid)的获取:这里分别说明这几个指定数据源的参数。首先path是一个完整路径的字符串,这个路径从设备的根目录(注意:DDMS中的文件结构与实际的目录结构有区别,设备的文件系统中建立了一些连接文件,建议善加利用)进行寻找。参数fd是一个FileDescriptor对象,该类型对象的获得不能通过构造函数。一般是先创建一个FileInputStream对象,再调用该对象的getFD()方法获取。参数uri是android.net.Uri类型的对象。这类型是一个对通用资源标志符(Uniform Resource Identifier, 简称"URI"。相关信息请见参考资料)的抽象。该类型的对象可以通过Uri.fromFile(File file)等方法获得。最后一个resid是一个int值,这是对可读写资源的一个唯一标示。可通过资源对象R获得。这里存在一个小问题,就是该资源将作为项目的一部分而存在,从而占用大量空间也不便于app本身的上载。

示例
下面针对setDataSource系列方法,实现一个简单的切换数据源的功能。
数据源切换:


if(mPlayer != null) { mPlayer.reset(); //获取数据源参数,这部分内容为了方便放在切换部分,实际应该根据//需要放在初始化部分 FileDescriptor fd; String path1 = "/sdcard/Fantasy.mp3"; String path2 = "/sdcard/Wait for You.mp3"; long offset = 0,length = 0x7ffffffffffffffL; FileInputStream fis; //尝试切换数据源 try { fis = new FileInputStream(path2); fd = fis.getFD(); if(switchFlag) { mPlayer.setDataSource(path1); tvStatus.setText(path1); } else { mPlayer.setDataSource(fd, offset, length); tvStatus.setText(path2); } switchFlag = !switchFlag; } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } //准备播放 try { mPlayer.prepare(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } 播放按键处理: try { if(mPlayer != null) { mPlayer.stop(); } mPlayer.prepare(); mPlayer.start(); tvStatus.setText("音乐播放中..."); } catch (Exception e) { tvStatus.setText("播放发生异常..."); e.printStackTrace(); //防止MediaPlayer因出错僵死 mPlayer.reset(); }




效果图:请注意进度条右端的音频时长的改变,说明数据源确实切换成功。




参考资料
这里感谢网上共享各类资源与知识的前辈,以下是参考到的资料与博文:
http://2528.iteye.com/blog/1338927
http://www.cnblogs.com/xiuluo--angel/archive/2011/12/15/2288247.html
http://hi.baidu.com/megachan/blog/item/f118f93fbb78e42170cf6cfa.html
http://my.oschina.net/zhangqingcai/blog/29660
http://blog.csdn.net/hellogv/article/details/5975864
http://weizhulin.blog.51cto.com/1556324/311694
http://liangruijun.blog.51cto.com/3061169/673776
http://topic.csdn.net/u/20110919/20/d2ac365e-168d-49b5-af36-8d2beb468989.html
http://baike.baidu.com/view/160675.htm



【Android应用开发技巧|MediaPlayer中设定数据源的几种方法】

    推荐阅读