Android多媒体-MediaPlayer唤醒锁及音频焦点

MediaPlayer的唤醒锁

  一般使用MediaPlayer播放音频流,推荐使用一个Service来承载MediaPlayer,而不是直接在Activity里使用。可是Android系统的功耗设计里,为了节约电池消耗,假设设备处于睡眠状态。系统将试图减少或者关闭一些没设备必须的特性。包含CUP和Wifi硬件。然后,假设是一个后台播放音乐的应用,减少CUP可能导致在后台执行的时候干扰音频的正常播放。关闭Wifi将可能导致网络音频流的获取出现错误。

  为了确保MediaPlayer的承载的服务在系统睡眠的时候继续正常执行下去。Android为我们提供了一种唤醒锁(wake locks)的机制。它能够在系统睡眠的,依旧保持锁定硬件的正常工作。

  确保在MediaPlayer执行的时候,哪怕系统睡眠了CUP也能正常执行。须要使用MediaPlayer.setWakeMode()为MediaPlayer设定唤醒锁。以下是setWakMode()的签名:

  setWakeMode(Context context, int mode)

  第一个參数是当前上下文,第二个參数为须要加锁的状态,被设定为int类型的常量,定义在PowerManager这个final类中。

PowerManager是专门用来管理Android功率消耗的锁定状态,与锁定CUP相关的,有四种,分别设定CUP、屏幕、键盘等的各种保持唤醒的状态。在这里仅仅须要设定为PARTIAL_WAKE_LOCK就可以。

mediaPlayer = new MediaPlayer();
// 设定CUP锁定
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);

一般对于锁而言。锁定了通常须要解锁。可是这里的唤醒说与MediaPlayer关联,所以仅仅须要在使用完之后release()释放MediaPlayer就可以,无需显式的为其解锁。在使用setWakeMode设定唤醒锁的时候,还必须为应用赋予对应的权限:

<uses-permission android:name="android.permission.WAKE_LOCK"/>

再来说说怎样锁定wifi硬件在系统睡眠的时候保持正常执行。wifi锁通过WifiLock进行操作,而WifiLock通过WifiManager进行管理,通过WifiManager.createWifiLock()进行Wifi锁定。

    WifiManager.WifiLock createWifiLock(int lockType, String tag)

  这种方法有多个重载。这里介绍的这个,第一个參数设定锁的状态,为一个int类型的常量,定义在Context类中,这里的应用场景一般设定为WIFI_MODE_FULL就可以。

第二个參数为WifiLock的标志,用于确定wifiLock的。

wifiLock= ((WifiManager) getSystemService(this.WIFI_SERVICE)).createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
wifiLock.acquire();

当然,在应用中把Wifi锁定之后。还须要在MediaPlayer.release()的时候为wifi硬件解锁。为避免意外关闭的情况,最好在Android组件的onDestory()里对其进行释放,释放Wifi锁使用WifiLock.release()。

/**
* 停止播放
*/
 protected void stop() {
	if (mediaPlayer != null && mediaPlayer.isPlaying()) {
              mediaPlayer.stop();
              mediaPlayer.release();
              mediaPlayer = null;
              // 释放wifi锁
             wifiLock.release();
             btn_play.setEnabled(true);
             Toast.makeText(this, "停止播放", 0).show();
         }

     }

     @Override
     protected void onDestroy() {
         // 在activity结束的时候回收资源
         if (mediaPlayer != null && mediaPlayer.isPlaying()) {
             mediaPlayer.stop();
             mediaPlayer.release();
             mediaPlayer = null;
             // 释放wifi锁
             wifiLock.release();
         }
         super.onDestroy();
     }

MediaPlayer的音频焦点

  众所周知,Android是一个多任务的操作系统。所以对于音频的播放。或许有几个不同的媒体服务会同一时候播放,这样可能导致一个比較杂乱的声音环境,而错过一些重要的声音提醒。在Android2.2之后,Android提供了一种应用协商使用设备音频输出的机制。这样的机制称为音频焦点。

  当应用程序须要输出音频或通知的时候,须要请求音频焦点,当请求得到音频焦点之后,监听音频焦点的变换,当音频焦点变换了,依据返回回来的音频焦点码进行对应的处理。音频焦点的注冊使用音频管理器的AudioManager.requestAudioFocus()方法设定。

它的签名例如以下:

    int requestAudioFocus(AudioManager.OnAudioFocusChangeListener l, int streamType, int durationHint)

  这种方法的返回值是int类型,其含义被定义在AudioManager中以常量表示AUDIOFOCUS_REQUEST_FAILED(获取音频焦点成功)、AUDIOFOCUS_REQUEST_GRANTED(获取音频焦点失败)。

当中重要的是第一个參数。为音频焦点变化的回调函数。在当中能够设定假设音频焦点变换了。当前应用怎样管理MediaPlayer。第二个參数为媒体流的类型,第三个參数为持续的状态。

  AudioManager.OnAudioFocusChangeListener为音频焦点变换的监听器,当中须要实现一个方法:onAudioFocusChange(int focusChange)在音频焦点变换的时候回调。它有一个參数,为当前表示音频焦点对于当前应用的状态码。通过这个状态码指定相应的操作,有些时候音频状态改变了,并不一定须要停止音频的播放。

  focusChange有一下几种状态码:

AUDIOFOCUS_GAIN:获得音频焦点。

AUDIOFOCUS_LOSS:失去音频焦点。而且会持续非常长时间。这是我们须要停止MediaPlayer的播放。

AUDIOFOCUS_LOSS_TRANSIENT:失去音频焦点,但并不会持续非常长时间,须要暂停MediaPlayer的播放。等待又一次获得音频焦点。

AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:临时失去音频焦点,可是无需停止播放,仅仅需减少声音方法。

 audioManager = (AudioManager) getSystemService(this.AUDIO_SERVICE);
 int result = audioManager.requestAudioFocus(
	  new OnAudioFocusChangeListener() {

	      @Override
	     public void onAudioFocusChange(int focusChange) {
	          switch (focusChange) {
	          case AudioManager.AUDIOFOCUS_GAIN:
	              // 获得音频焦点
	             if (!mediaPlayer.isPlaying()) {
	                 mediaPlayer.start();
	             }
	             // 还原音量
	             mediaPlayer.setVolume(1.0f, 1.0f);
	             break;

	         case AudioManager.AUDIOFOCUS_LOSS:
	             // 长久的失去音频焦点,释放MediaPlayer
	             if (mediaPlayer.isPlaying())
	                 mediaPlayer.stop();
	             mediaPlayer.release();
	             mediaPlayer = null;
	             break;

	         case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
	             // 展示失去音频焦点,暂停播放等待又一次获得音频焦点
	             if (mediaPlayer.isPlaying())
	                 mediaPlayer.pause();
	             break;
	         case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
	             // 失去音频焦点,无需停止播放,减少声音就可以
	             if (mediaPlayer.isPlaying()) {
	                 mediaPlayer.setVolume(0.1f, 0.1f);
	             }
	             break;
	         }
	     }
	 }, AudioManager.STREAM_MUSIC,
	 AudioManager.AUDIOFOCUS_GAIN);

总结

  以上就解说了MediaPlayer的一些高级的内容,在掌握了MediaPlayer的使用之后。开发有关音乐播放类的应用的时候就能够得心应手了。

从用户体验的方面出发,假设真实开发一款播放器类的软件,须要监听AUDIO_BECOMING_NOISY的广播,它会在音频输出源从其它输出源变换到设备扬声器的时候发出此广播。监听广播在音频输出源改变到设备扬声器的时候。停止播放。这样确保在耳机或额外的音频输出硬件与设备断开连接的时候。不至于又一次从扬声器继续输出音频播放。

源代码链接:http://download.csdn.net/detail/duanyu218/7475569

时间: 2024-10-10 14:15:09

Android多媒体-MediaPlayer唤醒锁及音频焦点的相关文章

Android多媒体-MediaPlayer使用方式

先不多说,直接上代码 public class SimpleMediaPlayerActivity extends Activity { //private static final Uri mMusicUri = Uri.fromFile(new File("/sdcard/sound_file_1.mp3")); private static final Uri mMusicUri = Uri.parse("http://czanxi.azone.artron.net/u

Android开发之Mediaplayer状态转换图及音频焦点

前言 之前博客里已经将了MediaPlayer的简单应用,如何使用MediaPlayer在Android应用中播放音频.这篇博客在MediaPlayer使用的基础上,讲解一下MediaPlayer的一些高级功能的使用,以及它的状态转换.对MediaPlayer还不了解的朋友可以先看看之前那篇博客:Android--MP3播放器MediaPlayer. 本篇博客主要内容如下: MediaPlayer的状态变换 MediaPlayer的唤醒锁 MediaPlayer的音频焦点 MediaPlayer

【Android 多媒体开发】 MediaPlayer 状态机 接口 方法 解析

作者 : 韩曙亮 转载请著名出处 :  http://blog.csdn.net/shulianghan/article/details/38487967 一. MediaPlayer 状态机 介绍 Android MediaPlayer 状态即图例 : 1. Idle (闲置) 状态 和 End (结束) 状态 MediaPlayer 对象声明周期 : 从 Idle 到 End 状态就是 MediaPlayer 整个生命周期; -- 生命周期開始 : 进入 Idle (闲置) 状态; -- 生

android 音频焦点

音频焦点分为两种 1永久占用((AudioManager) getSystemService(AUDIO_SERVICE)) .requestAudioFocus(null, AudioManager.STREAM_MUSIC,                AudioManager.AUDIOFOCUS_GAIN); 2临时占用((AudioManager) getSystemService(AUDIO_SERVICE)) .requestAudioFocus(null, AudioManag

【Android 多媒体开发】 MediaPlayer 网络视频播放器

作者 : 万境绝尘 ([email protected]) 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/38895143 一. 相关模块解析 1. 播放载体 SurfaceView 简介 (1) SurfaceView 与 Surface SurfaceView 与 Surface 简介 : SurfaceView 中嵌入了一个 Surface, SurfaceView 可以操控 Surface 的 位置, 大小尺寸等;

Android入门笔记 - 多媒体 - MediaPlayer

今天我们来写一个超级超级简单的播放器,使用到的是android自带的音乐播放器类MediaPlayer,先上一张效果图: 里面只实现了播放器额基本功能,界面就不做了,因为不是重点哈. 代码: 1. layout/ activty_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/

Android多媒体开发介绍(转)

Android多媒体开发介绍 转自:http://blog.csdn.net/reiliu/article/details/9060557 一.       多媒体架构 基于第三方PacketVideo公司的OpenCORE来实现,支持所有通用的音频/视频/静态图像格式,包括:MPEG4.H.264.MP3.AAC.AMR.JPG.PNG.GIF等.从功能上分为两部分,一是音/视频的回放(PlayBack),二是音视频的纪录(Recorder). CODEC(编解码器)使用OpenMAX 1L

音频焦点整理

音频焦点总结 参考很多大神们的资料,再次表示感谢, 什么叫音频焦点 (audio focus)? android系统是一个多任务操作系统,因此同一时刻允许许多任务同时工作.但是这对音频类应用来说是个挑战,因为如果多个音频同时播放的话,很多情况下用户体验会相当的差!比如听音乐时,来了个电话,这时你的耳机里就是电话和音乐共同工作,绝对是个悲剧! 为了解决这个问题从android2.2开始引入audio focus的概念.为避免多个音乐 App 在同时请求音频播放的时候发生冲突,Android 平台使

android多媒体框架学习 详解 最新版本

一:多媒体框架概述   jellybean 的多媒体跟以前的版本,通过对比没啥变化,最大的变化是google终于舍得给multimedia建个独立的git了(framework/av),等你好久了!也体现了media 在整个android系统中的重要性!framework/av下都是些C/C++代码(libmedia,libmediaplayerservice,libstagefright),jni和 java api 还是保留在原来的位置,改革还不够彻底,但还是迈出了这一步,以后维护能更好的进