您的位置:首页 > 移动开发 > Android开发

android日记:mediaPlayer的使用

2016-03-10 18:23 549 查看
一、MediaPlayer类是一个媒体的框架中最重要的部件。这个类的对象主要负责获取,解码,播放音频/视频。它支持几种不同的媒体来源,如:

1、应用本地资源(跟随应用一起打包的媒体资源,在应用目录res/raw/下)

MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);// 不需要调用prepare(),create()方法已经包含此步骤
mediaPlayer.start();


2、内部的URI资源(保存在sdcard下的资源,可以用ContentResolver获得)

Uri myUri = ....;
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();


3、网络上的URL流资源

String url = "http://........";
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // 这个过程可能需要一段时间,例如网上流的读取
mediaPlayer.start();


注意:prepare()方法涉及到获取和解码媒体数据,所以这是需要等待时间的,如果我们把MediaPlayer放在主线程 ,这是会导致UI线程阻塞,造成应用ANR,即使十分之一秒的时间,也会造成很糟糕的用户体验,所以我们应该把MediaPlayer放在另一个线程中处理。我们也可以使用prepareAsync()方法来异步准备,值得注意的是这个过程是异步的,如果还向上面一样的写法直接在后面调用start()方法,会导致程序报错,所以我们需要实现MediaPlayer.OnPreparedListener接口,然后如下代码执行:

mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener(){
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});


二、上面介绍了MediaPlayer的基本使用方法,下面说说状态机制。

MediaPlayer是基于状态的,也就是说他的各种方法是在特定的情况才才能调用的,如果在一个特定的状态下调用了错误的方法,系统会抛出一个异常或者导致其他不在预期内的错误情况发生。在谷歌官方文档上关于MediaPlayer的API中有一张状态图详细说明了各个状态之间的转换,图片如下:



从上图可以看出,在prepared状态下,只能调用start()、stop()、seekTo()方法,

在started状态下可以调用start()、stop()、seekTo()、Pause(),但是不能调用prepare(),只有等到stop状态下才能调用prepare()方法。熟悉这些状态,可以让你在写代码避免错误的发生。

众所周知,android系统的内存非常宝贵,然而像图片、音频、视频是最耗费内存的,操作不当就会造成OOM。所以我们在使用完MediaPlayer后,一定要及时及时释放资源,不然当前Activity被销毁后,进程不会被销毁,那么MeidaPlayer对象不会被释放,然后再次开启Activity将会重新创建一次MediaPlayer(如横竖屏切换),这样反复几次,很容易消耗掉所有资源,所以应该在Activity销毁之前及时调用release()释放你的资源,如下这样:

mediaPlayer.release();
mediaPlayer = null;


但是如果需要做例如音乐类的软件,这些音乐是需要背景播放的,这样如果我每次销毁Activity都释放mediaPlayer,这样音乐就不会再播放,这种体验很差,所以这不是背景音乐所需要的。所以我们可以把MediaPlayer放在Service里,由服务来控制MediaPlayer。

三、当背景音乐在播放时,手机可能会随时进入随眠状态(无操作一段时间),在这种状态下,系统会为了节省电源会关闭任何不必要的功能,包括CPU和WIFI,,这样背景音乐将会暂停,这不是我们想要的,所以我们必须阻止系统关闭服务。

我们可以使用wake locks(唤醒锁),它会告诉系统你正在使用某些功能,这样就可以一直保持该功能处于唤醒状态,即使锁屏无操作也能继续使用。这个锁会在paused和stoped状态下释放。代码如下:

mMediaPlayer = new MediaPlayer();
mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);//唤醒锁应该在初始化MediaPlayer的时候使用


在这需要注意的一点是,睡眠状态下系统关闭的一些功能是为了保证电池的使用寿命,所以我们应该有节制的使用唤醒锁。

当我们播放的是网络资源时,我们就需要给WIFI也加一个锁,注意这个锁需要手动去释放它。使用方法如下:

WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
wifiLock.acquire();//开启锁
.
.
.
.
//当不需要使用时应该释放
wifiLock.release();


四、如果你的背景音乐正在运行,这时突然提示信息的铃声响起,但是音频输出端口只有一个,所以会发生俩个音频同时发出高亮的声音,这在用户体验上是非常不好的,因为用户可能更想知道信息提示,如果你的背景音乐声音太大,将会遮住提示声音。这在2.2之前是没有一个解决方案的。在2.2之后,平台提出了Audio Focus(音频焦点)的方式,它是为了在各个应用之前进行协商谈判谁该使用音频设备的主要输出。(例如正在播放音乐,短信提示响起,这时焦点交给短信,音乐播放失去焦点应该降低声音),使用方法如下:

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);

if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {

}


class MyService extends Service
implements AudioManager.OnAudioFocusChangeListener {
// ....
public void onAudioFocusChange(int focusChange) {
// 音频焦点变化 需要做的事
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 应用