需求背景

要求某些场景已经插入耳机或连接了蓝牙耳机,需要使用扬声器播放音频

实现调研

有线耳机的情况

排除蓝牙耳机情况,使用有线耳机,切换时只需要打开/关闭扬声器即可。这样就可以实现在插入耳机的情况下,使用扬声器播放。 代码如下:

//切换为扬声器
AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
audioManager.setMicrophoneMute(false);
audioManager.setSpeakerphoneOn(true);//使用扬声器外放,即使已经插入耳机
//setVolumeControlStream(AudioManager.STREAM_MUSIC);//控制声音的大小
audioManager.setMode(AudioManager.STREAM_MUSIC);
//切换为耳机
mAudioManager.setSpeakerphoneOn(false);

另外,播放音频Android提供了两套Api,一套为MediaPlayer,偏上层。另一套AudioTrack偏底层。实验发现,在使用AudioTrack时需要添加增加AUDIO_SETTING权限。所以为了保险起见,需要加上如下权限:

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

蓝牙耳机

起初认为蓝牙耳机与有线耳机效果一样,但发现使用上述有线耳机的切换代码,效果为:切换至扬声器可从扬声器播放,关闭扬声器后。蓝牙耳机中无声音,扬声器也无声音。查找资料发现,需要手动打开蓝牙耳机,建立连接。代码如下:

  • 连接蓝牙耳机,关闭扬声器
    /*** 关闭扬声器*/private void offSpeaker() {if (mAudioManager == null) {mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);}Log.i("zxg", "isBluetoothSco 2:" + mAudioManager.isBluetoothScoOn());mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);//如果有蓝牙耳机设备连接,打开Sco通道使用蓝牙耳机播放音频if (isBluetoothHeadsetConnected()) {Log.i("zxg", "need start BluetoothSco");mAudioManager.startBluetoothSco();mAudioManager.setBluetoothScoOn(true);}//关闭扬声器mAudioManager.setSpeakerphoneOn(false);}
  • 关闭蓝牙Sco通道,打开扬声器
    /*** 打开扬声器*/private void speaker() {if (mAudioManager == null) {mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);}
//        mAudioManager.setMicrophoneMute(false);//关闭Scoif (isBluetoothHeadsetConnected()) {mAudioManager.setBluetoothScoOn(false);mAudioManager.stopBluetoothSco();}//打开扬声器mAudioManager.setSpeakerphoneOn(true);mAudioManager.setMode(AudioManager.STREAM_MUSIC);Log.i("zxg", "isBluetoothSco 1:" + mAudioManager.isBluetoothScoOn());}
  • 判断是否有蓝牙耳机与设备连接
    /*** 判断蓝牙耳机是否连接* @return*/private boolean isBluetoothHeadsetConnected() {BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();if (BluetoothProfile.STATE_CONNECTED == adapter.getProfileConnectionState(BluetoothProfile.HEADSET)) {return true;}return false;}
  • 注册广播监听

需要注意的是,打开/关闭Sco是异步的,并不是马上完成的,所以我们需要监听系统广播,收到相关广播后继续进行后续逻辑操作。在具体逻辑代码中可以通过mAudioManager.isBluetoothScoOn()判断Sco状态,以及在广播中更新标记位来记录Sco状态

    /*** 监听Sco变化广播*/private void registerBluetoothBroadCast() {registerReceiver(new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -100);Log.i("zxg", "EXTRA_SCO_AUDIO_STATE:" + state);}}, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));}
  • 添加权限

操作蓝牙需要申请如下权限

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

调研结果

使用以上代码嵌入出行司机端中,使用蓝牙/有线耳机切换,播放百度TTS语音。可以实现切换效果:即在连接蓝牙耳机/插入有线耳机时,可以通过扬声器播放音频。

参考资料

Android音频输出通道切换 -蓝牙 外放

android插入耳机状态使用扬声器外放音乐

蓝牙连接的sco问题

Android蓝牙耳机使用

Android蓝牙耳机/扬声器音频切换相关推荐

  1. android听筒+扬声器自动切换,Android 扬声器与听筒的切换

    本文主要实现扬声器与听筒的切换.而android中实现对音量和振铃模式的控制主要通过AudioManager类来实现. AudioManager类 关于喇叭与听筒的主要方法 1. AudioManag ...

  2. android听筒+扬声器自动切换,Android VOIP中的扬声器、听筒切换

    在做voip通话的过程中,会频繁使用到免提播放和听筒接听的功能,而如何正确的切换,和AudioManager的调度是分不开的,直接上代码: //获取AudioManager服务 private val ...

  3. 【Android】Audio音频输出通道切换 - 蓝牙bluetooth、外放

    参考: [Android]Audio音频输出通道切换 - 蓝牙.外放 Android Audio 音频输出通道切换 为什么 iOS 或 Android 设备连接蓝牙设备后不能通过蓝牙设备接电话? xq ...

  4. 【Android】Audio音频输出通道切换 - 蓝牙、外放

    手机音频的输出有外放(Speaker).听筒(Telephone Receiver).有线耳机(WiredHeadset).蓝牙音箱(Bluetooth A2DP)等输出设备.在平时,电话免提.插拔耳 ...

  5. Android Audio和耳机,蓝牙耳机等音频外设

    文章目录 Android Audio和耳机,蓝牙耳机等音频外设 蓝牙连接处理 广播接收 AudioManager接口 Listener监听 蓝牙耳机和AudioService的交互 蓝牙的状态 A2D ...

  6. Android 听筒扬声器切换 并且监听音量变化

    记录一下. 在activity 监听按键: @Override public boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode = ...

  7. 乐鑫Esp32学习之旅11 入门 乐鑫esp-adf 音频框架开发,造一个蓝牙耳机,实现切换歌曲,获取歌曲信息等功能。(附带Demo)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 " ...

  8. Android P的音频架构(二)

    Android P的音频策略分析 本文主要讲解AudioPolicy部分,对音频策略流程的分析,音频策略代码在frameworks\av\services\audiopolicy中. 相关定义: fr ...

  9. android8.1上musicfx,Android自带音频均衡器MusicFx分析

    Android自带音频均衡器MusicFx分析 种种原因,我要简单分析一个Android中built-in的音频均衡器MusicFx.重点是它的默认值的来历.网上很少有文章讲了这个的除了这篇<c ...

最新文章

  1. cap理论与分布式事务的解决方案
  2. python新增练习(二)
  3. SAP库存管理预留功能评测
  4. python读取word指定内容_python解析html提取数据,并生成word文档实例解析
  5. matlab 不同长度的向量放入一个矩阵,Matlab:将不同长度的行叠加到矩阵上
  6. 解决开机POST提示Strike tne F1 key to continue,F2 to run the setup utility
  7. PHP通过计算经纬度获取附近的数据信息
  8. Download Apache Commons BeanUtils
  9. python实现图形旋转_Python3+OpenCV2实现图像的几何变换
  10. Bootstrap 排版和链接
  11. 矩池云上如何修改cuda版本
  12. java空间大战,看这篇足矣了!
  13. 虚拟机中PXE-MOF:Exiting intel PXE ROM.Operating system not found解决方法
  14. 图像处理三:图像变形forward warping和inverse warping
  15. python从入门到实践课后答案-Python编程:从入门到实践(课后习题8)
  16. 【语音去噪】基于matlab GUI LMS+RLS语音去噪【含Matlab源码 528期】
  17. IDAPython手册
  18. 将json文件格式转化成Excel表格形式
  19. 申报火热进行中|2021“科创中国”开源创新榜评选
  20. canvas实现图片剪切

热门文章

  1. 2.4 找准位置,水滴石穿
  2. DAVINCI DM3730开发攻略——序
  3. 挺进中端存储系统,SAS走上夺权路
  4. Cocos游戏引擎,让小保安成就大梦想
  5. 雅点DS4破解版 雅点GIF破解版 雅点HDR破解版
  6. 关于个人品德要求的看法
  7. 计算机软件为题的ppt,《计算机软件的组成》PPT课件.ppt
  8. 2020新目标,多读书 -- 免费的电子书网站推荐
  9. ouc 2022 移动软件开发 实验五:第一个 Android 应用小程序
  10. 近十年以来机器学习中最优秀的想法之一~领略GANs核心