如今開始做音乐播放器的模块。遇到了几个问题

当播放音乐的过程中,去调节音量或者情景模式中的铃声设置,结果会有两种声音同一时候响起。

引起此问题的解决办法是音乐焦点问题没弄清

现分析一下音乐焦点的几个属性:源代码在frameworks/base/media/java/andorid/media/AudioManager.java中

public static final int AUDIOFOCUS_NONE = 0;

指示申请得到的Audio Focus不知道会持续多久,通常是长期占有。获得了Audio Focus;

public static final int AUDIOFOCUS_GAIN = 1;

指示要申请的AudioFocus是临时性的,会非常快用完释放的;

public static final int AUDIOFOCUS_GAIN_TRANSIENT = 2;

不但说要申请的AudioFocus是临时性的。还指示当前正在使用AudioFocus的能够继续播放,仅仅是要“duck”一下(减少音量)。

public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3;

public static final int AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE = 4;

AudioManager.OnAudioFocusChangeListener是申请成功之后监听AudioFocus使用情况的Listener,兴许假设有别的程序要竞争AudioFocus,都是通过这个Listener的onAudioFocusChange()方法来通知这个Audio
Focus的使用者的。

失去了Audio Focus,并将会持续非常长的时间

public static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN;

临时失去Audio Focus,并会非常快再次获得。必须停止Audio的播放。可是由于可能会非常快再次获得AudioFocus。这里能够不释放Media资源;

public static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT;

临时失去AudioFocus,可是能够继续播放,只是要在减少音量。

public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK =

            -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;

看看刚才改动的一个问题:

问题描写叙述:播放音乐时闹钟到来,把闹钟放在后台时进入文件管理器播放音频。闹钟仍然在响应,闹钟和音乐同一时候响起;

问题分析:在闹钟铃声响起时,没有去做音频焦点的处理

解决方式:在packages/apps/deskclock/src/com/android/deskclock/alarms/AlarmKlaxon.java文件里加上焦点处理

改动后的源代码:

package com.android.deskclock.alarms;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnErrorListener;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Vibrator; import com.android.deskclock.Log;
import com.android.deskclock.R;
import com.android.deskclock.provider.AlarmInstance; import java.io.IOException;
/*add by leo.tan 20140717 for bugzilla 20064 start */
import android.os.Handler;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.os.Message;
/*add by <span id="summary_alias_container"><span id="short_desc_nonedit_display"></span></span> leo.tan 20140717 for bugzilla 20064 end */
/**
* Manages playing ringtone and vibrating the device.
*/
public class AlarmKlaxon {
private static final long[] sVibratePattern = new long[] { 500, 500 }; // Volume suggested by media team for in-call alarms.
private static final float IN_CALL_VOLUME = 0.125f; private static boolean sStarted = false;
private static MediaPlayer sMediaPlayer = null;
/*add by leo.tan 20140717 for bugzilla 20064 start */
private static final int FOCUSCHANGE = 3000; private static final int FADEDOWN = 5; private static final int FADEUP = 6; private static final int RETRY_REQUEST_FOCUS = 7; private static final int OVER_SHORT_VIBRATOR = 8;
private static OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
android.util.Log.v("AlarmKlaxon", "mAudioFocusListener::focusChange-->" + focusChange);
mHandler.obtainMessage(FOCUSCHANGE, focusChange, 0).sendToTarget();
}
};
/*add by leo.tan 20140717 for bugzilla 20064 end */
public static void stop(Context context) {
Log.v("AlarmKlaxon.stop()"); if (sStarted) {
sStarted = false;
// Stop audio playing
if (sMediaPlayer != null) {
sMediaPlayer.stop();
AudioManager audioManager = (AudioManager)
context.getSystemService(Context.AUDIO_SERVICE);
audioManager.abandonAudioFocus(null);
sMediaPlayer.release();
sMediaPlayer = null;
}
/*add by leo.tan 20140717 for bugzilla 20064 start */
final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.abandonAudioFocus(mAudioFocusListener);
/*add by leo.tan 20140717 for bugzilla 20064 end */
((Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE)).cancel();
}
} public static void start(final Context context, AlarmInstance instance,
boolean inTelephoneCall) {
Log.v("AlarmKlaxon.start()");
// Make sure we are stop before starting
stop(context); if (!AlarmInstance.NO_RINGTONE_URI.equals(instance.mRingtone)) {
Uri alarmNoise = instance.mRingtone;
// Fall back on the default alarm if the database does not have an
// alarm stored.
if (alarmNoise == null) {
alarmNoise = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
if (Log.LOGV) {
Log.v("Using default alarm: " + alarmNoise.toString());
}
}  TODO: Reuse mMediaPlayer instead of creating a new one and/or use RingtoneManager.
sMediaPlayer = new MediaPlayer();
sMediaPlayer.setOnErrorListener(new OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.e("Error occurred while playing audio. Stopping AlarmKlaxon.");
AlarmKlaxon.stop(context);
return true;
}
});
try {
// Check if we are in a call. If we are, use the in-call alarm
// resource at a low volume to not disrupt the call.
if (inTelephoneCall) {
Log.v("Using the in-call alarm");
sMediaPlayer.setVolume(IN_CALL_VOLUME, IN_CALL_VOLUME);
setDataSourceFromResource(context, sMediaPlayer, R.raw.in_call_alarm);
} else {
sMediaPlayer.setDataSource(context, alarmNoise);
}
startAlarm(context, sMediaPlayer);
}catch (Exception ex) {
Log.v("Using the fallback ringtone");
// The alarmNoise may be on the sd card which could be busy right
// now. Use the fallback ringtone.
try {
// Must reset the media player to clear the error state.
sMediaPlayer.reset();
setDataSourceFromResource(context, sMediaPlayer, R.raw.fallbackring);
startAlarm(context, sMediaPlayer);
} catch (Exception ex2) {
// At this point we just don't play anything.
Log.e("Failed to play fallback ringtone", ex2);
}
}
} if (instance.mVibrate && !inTelephoneCall) {
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(sVibratePattern, 0);
} sStarted = true;
} // Do the common stuff when starting the alarm.
private static void startAlarm(Context context, MediaPlayer player) throws IOException {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
// do not play alarms if stream volume is 0 (typically because ringer mode is silent).
if (audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0) {
player.setAudioStreamType(AudioManager.STREAM_ALARM);
player.setLooping(true);
player.prepare();
audioManager.requestAudioFocus(null,
AudioManager.STREAM_ALARM, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
player.start();
}
/*add by leo.tan 20140717 for bugzilla 20064 start */
//在这个地方进行焦点的请求
  final int requestResult = audioManager.requestAudioFocus(mAudioFocusListener,
AudioManager.STREAM_ALARM,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
/*add by leo.tan 20140717 for bugzilla 20064 end */
} private static void setDataSourceFromResource(Context context, MediaPlayer player, int res)
throws IOException {
AssetFileDescriptor afd = context.getResources().openRawResourceFd(res);
if (afd != null) {
player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
}
} /*add by leo.tan 20140717 for bugzilla 20064 start */
private static void setVolume(float vol) {
if(sMediaPlayer != null){
sMediaPlayer.setVolume(vol, vol);
}
}
//用handler来对焦点进行处理
private static Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case FOCUSCHANGE: {
switch (msg.arg1) {
case AudioManager.AUDIOFOCUS_LOSS:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
mHandler.removeMessages(FADEUP);
mHandler.sendEmptyMessage(FADEDOWN);
break;
case AudioManager.AUDIOFOCUS_GAIN:
mHandler.removeMessages(FADEDOWN);
mHandler.sendEmptyMessage(FADEUP);
break;
}
break;
}
case FADEDOWN:
// Turn off the sound
setVolume(0.0f);
break;
case FADEUP:
// Turn on the sound
setVolume(1.0f);
break;
}
}
};
/*add by leo.tan 20140717 for bugzilla 20064 end */
}
<span id="summary_alias_container"></span>

android AudioManager AUDIOFOCUS的更多相关文章

  1. Android audioManager

    Android audioManager AudioManager provides access to volume and ringer mode control. 获取对象 Use Contex ...

  2. Android Audio Focus的应用(requestAudioFocus)

    网址:http://blog.csdn.net/dadoneo/article/details/8252933 FROM: http://www.linuxidc.com/Linux/2012-04/ ...

  3. Android中的Audio播放:竞争Audio之Audio Focus的应用

    from://http://blog.csdn.net/thl789/article/details/7422931 Android是多任务系统,Audio系统是竞争资源.Android2.2之前,没 ...

  4. Android得到一个闹钟在第三方

    收集报警信息 闹铃时间,闹铃备注信息 闹铃引起系统变化的点: 1. Send Notification (正点闹钟能够设置不发送) 2. Play audio 闹铃信息结构体 ClockInfo{ S ...

  5. 【Android】实验7 BindService模拟通信 截止提交日期2016.5.3

    实验7 BindService模拟通信 [目的] 实现启动端和BindService之间的双向通信 [要求] 1)   实现从启动端传递一个数据至BindService端: 2)   实现使用Bind ...

  6. Android 音频管理器AudioManager

    音频管理器AudioManager,通过它可以管理android系统的音量或直接让系统静音,依旧是通过调用getSystemService()方法获取音频管理器AudioManager对象,获取到该对 ...

  7. Android之声音管理器《AudioManager》的使用以及音量控制

    以下为网上下载然后拼接-- Android声音管理AudioManager使用 手机都有声音模式,声音.静音还有震动,甚至震动加声音兼备,这些都是手机的基本功能.在Android手机中,我们同样可以通 ...

  8. Android中文API(129) —— AudioManager

    前言 本章内容是android.media.AudioManager,版本为Android 3.2 r1,翻译来自"文炜",欢迎访问他的博客:"http://www.cn ...

  9. 从头学起android&lt;AudioManager 声音编辑器.五十.&gt;

    我们用android经常使用的时候,手机的声音增大和缩小操作.在设定场景模式,它往往使用静音和振动运行,这通常是AudioManager来控制的. 今天我们就来看一下AudioManager 的使用. ...

随机推荐

  1. 使用Swift和SpriteKit写一个忍者游戏

    这篇文章的游戏使用SpriteKit和Swift语言来完毕. SpriteKit是苹果自己的游戏引擎,更能贴合iOS系统底层的API,只是架构和实现上都是模仿了Cocos2D.所以使用上事实上区别不大 ...

  2. Oracle学习(11):PLSQL程序设计

    PL/SQL程序结构及组成 什么是PL/SQL? •PL/SQL(Procedure Language/SQL) •PLSQL是Oracle对sql语言的过程化扩展 •指在SQL命令语言中添加了过程处 ...

  3. xcodeproj cannot be opened because the project file cannot be parsed.

    解决方法:    1.对.xcodeproj文件右键,显示包内容 2.双击打开 project.pbxproj 文件 3.找到以上类似的冲突信息(能够用commad + f搜索) 4.删除<&l ...

  4. 2015.03.12,外语,读书笔记-《Word Power Made Easy》 10 “如何讨论交谈习惯”学习笔记 SESSION 25

    1.about keeping one's mouth shut taciturn,名词形式taciturnity,沉默寡言. 美国第30任总统库里奇,以沉默寡言著称.他来自新英格兰,那里视tacit ...

  5. 0x21 剪枝

    这一章真是心态崩,剪枝太玄学啦,特别是那个搜索顺序我靠真的... poj1011 枚举答案,搜索记录当前到第几根木棒. 剪枝:1.从大到小排序 2.排除等效,这个感觉还行,就是木棒按大小顺序进去,去除 ...

  6. 【转】C# ABP WebApi与Swagger UI的集成

    以前在做WebAPI调用测试时,一直在使用Fiddler测试工具了,而且这个用起来比较繁琐,需要各种配置,并且不直观,还有一点是还得弄明白URL地址和要传递的参数,然后才能调用.  最近新入职,公司里 ...

  7. HTML文档 html,html5,css,css3

    HTML 各种标签及简单应用: http://www.w3school.com.cn 1 <p><p> 2 <br/> 3 <hr/>横线 4 < ...

  8. 谈谈javascript中原型继承

    什么是继承?拿来主义:自己没有,别人有,把别人的拿过来使用或者让其成为自己的 如何实现继承的方式 原型继承 混入继承 经典继承 1. 混入继承 由于一个对象可以继承自任意的对象,即:o可以继承自对象o ...

  9. SQL学习——基础语句(3)

    先上数据表 student表 grade 表 SQL Union 语句 合并两个或多个select查询结果集. select s_id from student union select  s_id ...

  10. PHP魔术方法__tostring()篇

    下面是关于__tostring 的运用 header('Content-type:text/html;charset="utf-8"'); /*存在内置方法_tostring()的 ...