Audio 输出通道有很多,Speaker、headset、bluetooth A2DP等。通话或播放音乐等使用Audio输出过程中,可能发生Audio输出通道的切换。比如,插入有线耳机播放音乐时,声音是从耳机发出的;而此时拔出耳机,Audio输出通道会发生切换。如果音乐播放器不做处理,Audio输出是被切换到扬声器的,声音直接从Speaker发出。我们在编写程序时,要捕获并按照需求来处理这样的事,本文就是讲解如何处理的。

Android中可以通过android.media.AudioManager查询当前Audio输出的情况,并且在Audio输出发生变化时,捕获并处理这种变化。

一、Audio输出状态查询与控制

android.media.AudioManager提供的下列方法可以用来查询当前Audio输出的状态:

  • isBluetoothA2dpOn():检查A2DPAudio是否通过蓝牙耳机;
  • isSpeakerphoneOn():检查扬声器是否打开;
  • isWiredHeadsetOn():检查线控耳机是否连着;注意这个方法只是用来判断耳机是否是插入状态,并不能用它的结果来判定当前的Audio是通过耳机输出的,这还依赖于其他条件。

另外还有一些设置这些Audio输出的setXYZ()方法,这些方法在一般使用Audio输出的应用程序不要直接调用,他们由系统来管理,实现Audio输出通道的自动切换。除非,界面提供给用户切换的菜单或按钮,而用户选择了却换,比如要直接选择扬声器发声,可直接调用setSpeakerphoneOn()。

二、Audio输出通道切换的事件的捕获与处理

因为耳机插拔、蓝牙耳机的断开,Audio输出通路会自动切换。此时正在播放Audio的程序要获得通知,知道这一事件的发生。Android中是通过广播ACTION_AUDIO_BECOMING_NOISY这个Intent通知的。

处理广播的较好的方式,是动态注册/注销自己所关心的广播。下面代码演示了,开始播放时注册广播的Receiver;停止播放时注销广播的Receiver。对Audio输出通道切换的处理是暂停当前的播放,不直接从新的通道里发出声来。

  1. private class NoisyAudioStreamReceiver extends BroadcastReceiver {
  2. @Override
  3. public void onReceive(Context context, Intent intent) {
  4. if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
  5. // Pause the playback
  6. }
  7. }
  8. }
  9. private IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
  10. private void startPlayback() {
  11. registerReceiver(myNoisyAudioStreamReceiver(), intentFilter);
  12. }
  13. private void stopPlayback() {
  14. unregisterReceiver(myNoisyAudioStreamReceiver);
  15. }
  1. private class NoisyAudioStreamReceiver extends BroadcastReceiver {
  2. @Override
  3. public void onReceive(Context context, Intent intent) {
  4. if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
  5. // Pause the playback
  6. }
  7. }
  8. }
  9. private IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
  10. private void startPlayback() {
  11. registerReceiver(myNoisyAudioStreamReceiver(), intentFilter);
  12. }
  13. private void stopPlayback() {
  14. unregisterReceiver(myNoisyAudioStreamReceiver);
  15. }

三、Audio输出通道切换的典型场景—— 用耳机听音乐时,拔出耳机

听耳机听音乐时,耳机别拔出的时序图如下:

图中:

  • AudioNoisy Client注册了侦听广播AudioManager.ACTION_AUDIO_BECOMING_NOISY;
  • 用耳机一直在听音乐;
  • HeadsetObserver一直在监视耳机状态的变化。检测到耳机被拔出之后,发出广播AudioManager.ACTION_AUDIO_BECOMING_NOISY;
  • AudioNoisy Client收到了广播,发送暂停命令给MediaPaybackService去暂停当前的播放。

小结

Audio 输出通道切换时,要根据具体需求来做相应的处理。

Android中的Audio播放:控制Audio输出通道切换的更多相关文章

  1. Android中通过耳机按键控制音乐播放的实现

    今天在研究Android中实现Android 4.2.2源码中的Music应用的源码,关于通过耳机按键控制音乐播放的实现,有点好奇,就仔细分析了一下源码, 主要由 MediaButtonIntentR ...

  2. android中使用setVideoURI()播放视频

    最近在做一个demo,要求播放视频,记录一下.使用的是VideoView控件,如果播放网络视频的话,视频应该是渐进流式的,格式嘛,大家应该都知道,一般是H.263或者H.264格式的扩展名为3gp或者 ...

  3. Android中的音频播放(MediaPlayer和SoundPool)

    Android中音频和视频的播放我们最先想到的就是MediaPlayer类了,该类提供了播放.暂停.停止.和重复播放等方法.该类位于android.media包下,详见API文档.其实除了这个类还有一 ...

  4. Android中使用VideoView 播放视频

    VideoView一般结合MediaController类使用,它会提供一个友好的图形界面,通过该界面可以控制视频的播放 package com.test.videoview; import andr ...

  5. android中viewPager+fragment实现的屏幕左右切换(进阶篇)

    Fragment支持在不同的Activity中使用并且可以处理自己的输入事件以及生命周期方法等.可以看做是一个子Activity. 先看一下布局: 1 <LinearLayout xmlns:a ...

  6. Android中通过Fragment进行简单的页面切换

    首先是activity中的布局 <?xml version="1.0" encoding="utf-8"?> <androidx.constr ...

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

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

  8. 在iOS微信浏览器中自动播放HTML5 audio(音乐)的2种正确方式

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. 自定义css样式结合js控制audio做音乐播放器

    最近工作需求需要播放预览一些音乐资源,所以自己写了个控制audio的音乐播放器. 实现的原理主要是通过js调整audio的对象属性及对象方法来进行控制: 1.通过play().pause()来控制音乐 ...

随机推荐

  1. C++模板:读入优化

    int scan(int &x){ while(c=getchar(),c<'0'||c>'9');x=c-'0'; while(c=getchar(),c>='0'& ...

  2. JAVA中List、Map、Set的区别与选用

    类层次关系如下: Collection ├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap └WeakHashM ...

  3. Ubuntu Linux: How Do I install .deb Packages?

    Ubuntu Linux: How Do I install .deb Packages? Ubuntu Linux: How Do I install .deb Packages? by Nix C ...

  4. 先登录 在跳转到tabBar

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launc ...

  5. Linux虚拟机与外面系统ping不通,或者连不上网

    很多其它具体文档:http://download.csdn.net/download/zml_2015/8843061 非常多人在做linux课程设计的时候,用的linux虚拟机与外面的系统ping不 ...

  6. <META http-equiv=Content-Type content="text/html; charset=gb2312">

    META,网页Html语言里Head区重要标签之一 HTTP-EQUIV类似于HTTP的头部协议,它回应给浏览器一些有 用的信息,以帮助正确和精确地显示网页内容.常用的HTTP- EQUIV类型有: ...

  7. BZOJ 2015: [Usaco2010 Feb]Chocolate Giving( 最短路 )

    裸最短路.. ------------------------------------------------------------------------------------ #include ...

  8. Oracle 11g New 热补丁

    热补丁:概览 对于Oracle 实例上的bug 修复或诊断补丁程序,热补丁 可以执行以下操作: • 安装 • 启用 • 禁用 热补丁:概览 使用热补丁可以安装.启用和禁用 正在运行的 活动Oracle ...

  9. PDO获取数据的方法fetch()、fetchAll()、setFetchMode()、bindColumn()

    PDO的数据获取方法与其他数据库扩展都非常类似,只要成功执行SELECT查询,都会有结果集对象产生.不管是使用PDO对象中的query()方法,还是使用prepare()和execute()等方法结合 ...

  10. hdu 3625 第一类striling 数

    /** 第一类Stirling数是有正负的,其绝对值是包含n个元素的集合分作k个环排列的方法数目. 递推公式为, S(n,0) = 0, S(1,1) = 1. S(n+1,k) = S(n,k-1) ...