学习Android MediaPlayer
Android Media Playback
The Android multimedia framework includes support for playing variety of common media types, so that you can easily integrate audio, video and images into your applications. You can play audio or video from media files stored in your application's resources (raw resources), from standalone files in the filesystem, or from a data stream arriving over a network connection, all using MediaPlayer APIs.
Android多媒体框架包含对多种常见媒体类型的支持,所以你可以容易的在自己的应用中集成音频,视频和图片。你可以播放应用内的资源文件,或文件系统中独立的文件,也可以通过网络数据流来播放,这些功能都使用MediaPlayer APIs实现。
Note: You can play back the audio data only to the standard output device. Currently, that is the mobile device speaker or a Bluetooth headset. You cannot play sound files in the conversation audio during a call.
注意:你只能通过标准输出设备播放音频。当前,这包括移动设备的扬声器或者蓝牙耳机。你不能在用户打电话时播放音频。
The Basics
在Android Framework中,下面两个类用来播放声音和视频:
MediaPlayer
此类是播放声音和视频的主要API。
AudioManager
此类管理音频资源和音频在设备上的输出。
Manifest Declarations
Before starting development on your application using MediaPlayer, make sure your manifest has the appropriate declarations to allow use of related features.
在开始使用MediaPlayer之前,确保你的清单文件中声明了与相关特性有关的权限:
Internet Permission - 如果你使用MediaPlayer播放网络内容,应用需要网络访问权限。
Wake Lock Permission - 如果你的应用需要保持屏幕不变暗或者处理器不休眠,或者使用
MediaPlayer.setScreenOnWhilePlaying()
和MediaPlayer.setWakeMode()
方法,你需要请求以下权限:
Using MediaPlayer
One of the most important components of the media framework is the MediaPlayer class. An object of this class can fetch, decode, and play both audio and video with minimal setup. It supports several different media sources such as:
媒体框架中最重要的组件之一是MediaPlayer类。该类的对象可以用最少的步骤获取,解码和播放音频和视频。它支持多种媒体源,例如:
本地资源
内部URI,例如用于Content Resolver的URI
外部URL(流)
Android支持的媒体类型,见此文档:Android Supported Media Formats。
下面的例子显示了如何播放本地raw资源(应用res/raw目录下)
MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start(); // no need to call prepare(); create() does that for you
本例中,一个“raw”资源是一个系统不会尝试用特殊方式去解析的文件。然而,此资源的内容不能是原始音频。它应该是根据支持的格式恰当编码和格式化的文件。
下面的例子显示如何通过本地URI播放:
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播放在线媒体文件,该文件必须可以渐近下载(Progressive download)。
警告:在使用setDataSource()
时,必须捕获或者传递IllegalArgumentException和IOException,因为你引用的文件可能不存在。
Asynchronous Preparation
Using MediaPlayer can be straightforward in principle. However, it's important to keep in mind that a few more things are necessary to integrate it correctly with a typical Android application. For example, the call to prepare() can take a long time to execute, because it might involve fetching and decoding media data. So, as is the case with any method that may take long to execute, you should never call it from your application's UI thread.
原则上,使用MediaPlayer是简单直接的。然而集成在Android应用中时,有几点需要注意。例如,调用prepare()
可能会花费很长时间,因为此方法涉及到媒体数据的获取和解码,因此不应该在UI线程调用。
To avoid hanging your UI thread, spawn another thread to prepare the MediaPlayer and notify the main thread when done. However, while you could write the threading logic yourself, this pattern is so common when using MediaPlayer that the framework supplies a convenient way to accomplish this task by using the prepareAsync() method. This method starts preparing the media in the background and returns immediately. When the media is done preparing, the onPrepared() method of the MediaPlayer.OnPreparedListener, configured through setOnPreparedListener() is called.
要避免挂起UI线程,使用另一个线程来准备MediaPlaer,在完成时通知主线程。然而,虽然你可以自己写线程逻辑,此框架提供了prepareAsync
方法来简化这一工作。此方法立刻返回,在后台执行准备工作,完成后通过回调通知调用者。
Managing State
Another aspect of a MediaPlayer that you should keep in mind is that it's state-based. That is, the MediaPlayer has an internal state that you must always be aware of when writing your code, because certain operations are only valid when then player is in specific states. If you perform an operation while in the wrong state, the system may throw an exception or cause other undesireable behaviors.
关于MediaPlayer的另一个关注点是它是基于状态的。也就是说,你写代码时必须始终意识到MediaPlayer有内部状态,因为某些操作只在player处于特定状态时才有效。如果你在错误的状态下执行操作,系统可能会抛出异常或者引发其他不需要的行为。
MediaPlayer类文档中展示了MediaPlayer的完整状态图。
Releasing the MediaPlayer
A MediaPlayer can consume valuable system resources. Therefore, you should always take extra precautions to make sure you are not hanging on to a MediaPlayer instance longer than necessary. When you are done with it, you should always call release() to make sure any system resources allocated to it are properly released. For example, if you are using a MediaPlayer and your activity receives a call to onStop(), you must release the MediaPlayer, because it makes little sense to hold on to it while your activity is not interacting with the user (unless you are playing media in the background, which is discussed in the next section). When your activity is resumed or restarted, of course, you need to create a new MediaPlayer and prepare it again before resuming playback.
MediaPlayer会消费宝贵的系统资源,所以必须注意不要保持MediaPlayer实例超过需要的时间。当你用完时,应该调用release()
方法来确保分配给它的系统资源被合适的释放了。例如,如果你正在使用MediaPlayer,而Activity收到了onStop()
回调,则必须释放MediaPlayer(除非你在后台播放)。当Activity 重新获得焦点或者重新开始时,你需要创建一个新的MediaPlayer实例,并在恢复播放前准备它。
将MediaPlayer释放并制空:
mediaPlayer.release();
mediaPlayer = null;
As an example, consider the problems that could happen if you forgot to release the MediaPlayer when your activity is stopped, but create a new one when the activity starts again. As you may know, when the user changes the screen orientation (or changes the device configuration in another way), the system handles that by restarting the activity (by default), so you might quickly consume all of the system resources as the user rotates the device back and forth between portrait and landscape, because at each orientation change, you create a new MediaPlayer that you never release.
例如,如果你在Activity stop时忘了释放MediaPlayer,但在Activity create时创建了新的实例,那在用户反复旋转屏幕时,可能会很快就耗尽所有的系统资源,因为每次方向改变,你都创建了新的MediaPlayer对象,但从来没有释放。
Using a Service with MediaPlayer
If you want your media to play in the background even when your application is not onscreen—that is, you want it to continue playing while the user is interacting with other applications—then you must start a Service and control the MediaPlayer instance from there. You should be careful about this setup, because the user and the system have expectations about how an application running a background service should interact with the rest of the system. If your application does not fulfil those expectations, the user may have a bad experience. This section describes the main issues that you should be aware of and offers suggestions about how to approach them.
如果想让媒体文件在后台播放,需要启动一个Service,让后再Service中控制MediaPlayer实例。用户和系统对运行后台服务的应用如何同系统其它部分交互有一些期望,如果你的应用无法满足这些期望,用户可能会有糟糕的体验。本节描述了你需要注意的主要事项以及如何解决的建议。
Running asynchronously
First of all, like an Activity, all work in a Service is done in a single thread by default—in fact, if you're running an activity and a service from the same application, they use the same thread (the "main thread") by default. Therefore, services need to process incoming intents quickly and never perform lengthy computations when responding to them. If any heavy work or blocking calls are expected, you must do those tasks asynchronously: either from another thread you implement yourself, or using the framework's many facilities for asynchronous processing.
首先,同Activity一样,默认情况下Service中的所有工作也是在主线程中完成的。因此,服务需要快速的处理传入的intent,在响应意图是不能执行长时间操作。如果有大量的工作或者阻塞式的调用,就需要异步的完成。
For instance, when using a MediaPlayer from your main thread, you should call prepareAsync() rather than prepare(), and implement a MediaPlayer.OnPreparedListener in order to be notified when the preparation is complete and you can start playing. For example:
例如,在主线程中使用MediaPlayer时,你应该调用prepareAsync()而不是prepare(),实现MediaPlayer.OnPreparedListener
接口来通知准备已经完成。代码如下:
public class MyService extends Service implements MediaPlayer.OnPreparedListener {
private static final String ACTION_PLAY = "com.example.action.PLAY";
MediaPlayer mMediaPlayer = null;
public int onStartCommand(Intent intent, int flags, int startId) {
...
if (intent.getAction().equals(ACTION_PLAY)) {
mMediaPlayer = ... // initialize it here
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.prepareAsync(); // prepare async to not block main thread
}
}
/** Called when MediaPlayer is ready */
public void onPrepared(MediaPlayer player) {
player.start();
}
}
Handling asynchronous errors
On synchronous operations, errors would normally be signaled with an exception or an error code, but whenever you use asynchronous resources, you should make sure your application is notified of errors appropriately. In the case of a MediaPlayer, you can accomplish this by implementing a MediaPlayer.OnErrorListener and setting it in your MediaPlayer instance:
在同步的调用中,错误通常是通过异常或者错误码表示,但在异步调用时,你应该确保正确的接收到错误。对于MediaPlayer来说,你可以实现MediaPlayer.OnErrorListener
接口,设置给MediaPlayer实例:
public class MyService extends Service implements MediaPlayer.OnErrorListener {
MediaPlayer mMediaPlayer;
public void initMediaPlayer() {
// ...initialize the MediaPlayer here...
mMediaPlayer.setOnErrorListener(this);
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// ... react appropriately ...
// The MediaPlayer has moved to the Error state, must be reset!
}
}
It's important to remember that when an error occurs, the MediaPlayer moves to the Error state (see the documentation for the MediaPlayer class for the full state diagram) and you must reset it before you can use it again.
要记住当错误发生时,MediaPlayer转变为Error状态,在你使用它之前需要重置(reset)它。
学习Android MediaPlayer的更多相关文章
- Android(java)学习笔记180:Android MediaPlayer 播放prepareAsync called in state 8解决办法
使用android MediaPlayer播放音频文件时,有时会出现prepareasync called in state 8错误. 以下方法可以避免这个异常出现. 第一种方法: private ...
- Android(java)学习笔记123:Android MediaPlayer 播放prepareAsync called in state 8解决办法
1. 使用android MediaPlayer播放音频文件时,有时会出现prepareasync called in state 8错误. 以下方法可以避免这个异常出现. 第1种方法: priva ...
- 第一部分 Android MediaPlayer 概述
[IT168 技术文档]本文主要介绍的是Android中很重要也最为复杂的媒体播放器(MediaPlayer)部分的架构.对于Android这样一个完整又相对复杂的系统,一个MediaPlayer功能 ...
- Android MediaPlayer架构 -- MediaPlayer的创建过程
本文系作者自己学习之所用,文章内容仅出自作者拙劣之思考,问题之处烦请不吝指教. MediaPlayer 能被用来控制音/视频文件或流媒体的回放.Android中以MediaPlayer类作为音视频播放 ...
- 一培训机构设计的学习android课程内容:供大家参考
转自:http://www.cnblogs.com/csj007523/archive/2011/06/16/2082682.html 一培训机构设计的学习android课程内容:供大家参考 第一阶段 ...
- 想学习Android开发
最近被别人说知识面窄,心里受伤了.准备学学Android开发,如果能在手机里运行自己写的app,那是多么high ~~~ Android开发需要看什么资料呢? 说明:本人一直从事windows下的C+ ...
- 从零开始学习Android(一)Android环境的搭建
好久没有开始写博客了,最近开始学习Android,所以想把学习的笔记都一一记录下来.一来是方便自己以后资料的查询,其次也是给Android新手朋友进行学习使用,再次也希 望得到高手的指点.废话少说,我 ...
- 《IT蓝豹》吹雪花demo,学习android传感器
吹雪花demo,学习android传感器 吹雪花demo,学习android传感器,嘴巴对着手机底部吹一下就会出现飘着雪花效果. 算是学习android传感器效果.本例子主要是通过android.me ...
- 一起来学习Android自定义控件1
概述 Android已经为我们提供了大量的View供我们使用,但是可能有时候这些组件不能满足我们的需求,这时候就需要自定义控件了.自定义控件对于初学者总是感觉是一种复杂的技术.因为里面涉及到的知识点会 ...
随机推荐
- VS2010 C++ 优化配置
个人感觉VC6.0太土了,而且有很多bug存在,且微软早就不对其更新.所以,在选择C++编程的时候.使用IDE,VC6.0一段时间以后,我毅然决然的放弃了,觉得还是使用VS2010比较有前途. 但是当 ...
- Windows Server 2012从Evaluation版转成正式版
步骤 运行->CMD(管理员)->输入DISM /online /Get-CurrentEdition 看你的Edition ID是什么,如果是Evaluation的话,例如Standar ...
- Oracle数据库之创建表空间与用户
Oracle数据库之创建表空间与用户 一.创建表空间 基本语法表述: CREATE TABLESPACE tablespace_name [DATAFILE datafile_spec1 [,data ...
- 深入浅出Java 重定向和请求转发的区别
深入浅出Java 重定向和请求转发的区别 <span style="font-family:FangSong_GB2312;font-size:18px;">impor ...
- web UI
Semantic不错的UI,代码非常详细
- reaver 使用方法和技巧
reaver非常的不错,为我们ceng网带了最大的方便,使用简单,我来讲一下自己使用心得吧! 第一步,如果用虚拟机用vmware的,总会出现鼠标不灵点不到地方,换了一个 6.0.2 build-598 ...
- Altium Designer summer 9 布线 - 差分对布线
差分信号系统是采用双绞线进行信号传输的,双绞线中的一条信号线传送原信号,另一条传送的是与原信号反相的信号.差分信号是为了解决信号源和负载之间没有良好的参考地连接而采用的方法,它对电子产品的干扰起到固有 ...
- 为什么都反对XML而支持使用json呢?
一个使用上的因素:JSON的结构更容易映射至一般语言的数据结构. XML和JSON的主要组成成分: XML是element.attribute和element content. JSON是object ...
- myEclipse异常解决:Errors occurred during the build. Errors running builder Mule 3 hot deployment
选择一个项目—-右键Properties—-Builders—-取消 “JavaScript Validator” 和 Mule 3 hot deployment 的勾就OK了 根据具体异常,勾选. ...
- linux比较指令comm、diff、grep -Ff
Comm命令 如果想对两个有序的文件进行比较,可以使用comm命令. 语法:comm [- 123 ] file1 file2 说明:该命令是对两个已经排好序的文件进行比较.其中file1和file2 ...