Android多媒体框架包含了获取和回放音频,视频和各种类形的图像的功能,所以你可以很容易的把它们整合到你的应用中.你可以从存储在资源中的文件,文件系统中的文件,或从网络数据流中播放音频或视频,这些都是用MediaPlayer或JetPlayerAPI实现.你也可以使用MediaRecorderand Camera API来录制声音,视频或抓取图片.
下面的主题向你演示了如何使用Android框架来实现多媒体获取和回放.
-
MediaPlayer
如何在你的应用中播放音视频.
-
JetPlayer
如何使用通过JetCreator创建的内容播放交互式的音视频.
-
Camera
如何在你的应用中使用一个设备上的相机获取图片和视频.
-
AudioCapture
如何在你的应用中录制声音.
媒体回放
Android多媒体框架支持播放很多常见的媒体类型,所以你可以使用MediaPlayerAPI很轻松的整合音视频和图像到你的应用中.你可以从资源中,从文件中,从网络上播放音视频.
此文档向你演示了如何写一个媒体播放应用,如何与用户和系统交互,从而获得最好的性能和用户体验.
注:你只能把音视频播放到标准的输出设备上.当前,它们是扬声器或蓝牙耳机.你不能在电话通话时播放音频文件.
基础
以下类被用于播放音频和视频:
-
MediaPlayer
此类是播放音视频的主要API.
-
AudioManager
此类管理设备上的音频源和输出.
Manifest声明
在使用MediaPlayer开发之前,确保你的manifest中声明了允许使用的相关特性.
-
InternetPermission - 如果你使用MediaPlayer来播放网络流中的内容,你的应用必须请求网络存取权限.
<uses-permissionandroid:name="android.permission.INTERNET" />
-
WakeLock Permission -如果你的播放应用需要阻止屏幕变暗或阻止处理器睡眠,或使用MediaPlayer.setScreenOnWhilePlaying()或MediaPlayer.setWakeMode()方法,你必须请求此权限.
<uses-permissionandroid:name="android.permission.WAKE_LOCK" />
使用MediaPlayer
媒体框架中最重要的组件之一就是MediaPlayer类.此类的对象可以用少量的设置即能获取,解码和播放音视频.它支持多种媒体源,比如:
本地资源.
内部URI,比如你从ContentResolver取得的URI.
-
外部URI(流媒体)
要了解Android支持的媒体类型列表,请看AndroidSupported Media Formats 文档.
下面是如何播放本地资源中的音频的例子(保存在你的应用的res/raw/文件夹下):
MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1); mediaPlayer.start(); //不需要调用prepare(); create()为你做了
在例子中,"raw"资源是一个系统不会以某种方式进行分析的文件.然而,此资源的内容不能是原始音频,它应是一种适当编码和格式化的媒体文件(当然是被支持的格式).
以下是如何播放一个本地URI的例子(URI是你用ContentResolver获取的):
Uri myUri = ....; // initialize Uri here MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setDataSource(getApplicationContext(), myUri); mediaPlayer.prepare(); mediaPlayer.start();
从一个基于HTTP流的的远程URL播放看起来是这样的
String url = "http://........"; // your URL here MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.setDataSource(url); mediaPlayer.prepare(); // might take long! (for buffering, etc) mediaPlayer.start();
注:如果你传入了一个URL来流式播放一个在线文件,这个文件必须前进式下载progressivedownload.
警告:当使用setDataSource()时你必须捕获和传递IllegalArgumentException和IOException,因为你引用的文件可能不存在.
异步Preparation
使用MediaPlayer,在其本质上来说可以是简单直接的.然而,对于一个典型android应用来说还有一些重要的事情要记住.例如,prepare()调用可能耗时很常,因为它可能需要获取并打开解码媒体数据.所以,由于有些方法会执行很长时间,那么你就不能从你的应用的UI线程中调用它.否则会导致UI挂起,直到此方法返回为止.这是很差劲的用户体验,还会导致一个ANR(应用没有反应)错误.即使你认为你的资源加载的很快,但记住界面中任何耗时超过10秒的东西将导致一个显著的暂停并使用户对你的应用产生慢的印像.
要避免挂起UI线程,应产生另外的线程来"prepare"MediaPlayer并且在完成时通知主线程.然而,色虽然你可以亲自写线程中的逻辑,但是更常用的是使用框架所提供的一个方便的途径:使用prepareAsync().此方法在后台开始"准备"过程并立即返回.当媒体"准备"完成,MediaPlayer.OnPreparedListener的onPrepared()方法(通过setOnPreparedListener()设置的)被调用.
管理状态
对MediaPlayer要记住的另一个方面就是"基于状态".即,MediaPlayer有一个内部的状态,因为特定的操作只能在特定的状态时才有效,所以你必须在写代码时一直注意到它的变化.如果你在错误的状态下执行一个操作,系统可能抛出一个异常或导致一个意外的行为.
MediaPlayer类文档中展示了一个完整的状态图例,它阐明了哪个方法使MediaPlayer从一个状态进入另一个状态.例如,当你创建一个新的MediaPlayer,它处于Idle状态.此时,你应调用setDataSource()初始化它,使它进入"已初始化"状态.之后,你应使用prepare()或prepareAsync()"准备"它.当MediaPlayer准备完成,它将进入Prepared状态,这表示你可以调用start()来播放了.此时,如图表所示,你可以调用start(),pause(),和seekTo()以及其它一些方法使MediaPlayer的状态在Started,Paused和PlaybackCompleted状态之间转换.当你调了stop(),注意你不能再调用start(),除非你重新prepare MediaPlayer.
当你写代码与MediaPlayer交互时,要时刻记住MediaPlayer的状态变化图,因为在错误的状态下调用它的方法是常见的bug的原因.