Android Audio Play Out Channel

1: 7嘴8舌

扬声器, 耳机, 和听筒

就是通过: audiomanager.setmode(AudioManager.MODE_IN_COMMUNICATION)
audiomanager.setSpeakerhponeOn(boolean value).这两个来设置.不过有的好像不支持的.

米手机上切换 扬声器和听筒不能切换

Android AudioTrack音频播放分析  音频资源在播放时,会经常出现冲突的情况,如在进行音乐播放时有电话呼入、有新消息的提示音需要播放等,此类的并发处理就需要有一个统一的处理策略。在
Android系统开发中,通过为不同的场景配置不同的播放接口,在底层执行统一的并发策略,使得开发者可以将精力更集中在应用本身。  A udioTrack、MediaPlayer、SoundPool、Ringtone、JetPlayer等都是Android音频处理中常用接口,本文将针对AudioTrack接口进行详细说明。  AudioTrack  AudioTrack用于管理单个的音频资源。 在构造AudioTrack实例时,会涉及到流类型、采样率、通道配置、音频格式、缓冲大小、播放模式等因素。  AudioTrack支持STREAM_VOICE_CALL、STREAM_SYSTEM、STREAM_RING、STREAM_MUSIC和STREAM_ALARM等流类型。  AudioTrack支持44100Hz、22050Hz、11025Hz等采样率。  AudioTrack支持单声道(CHANNEL_OUT_MONO)、立体声(CHANNEL_OUT_STEREO)等两种通道。  AudioTrack支持ENCODING_PCM_16BIT、ENCODING_PCM_8BIT等两种编码格式。  AudioTrack支持两种播放模式:静态模式(static mode)和流模式(Streaming mode)。其中静态模式由于没有从Java层向原生层传递数据造成的延迟,时延很小,当然受限于音频缓冲的大小,通常在游戏场景中用于播放时长很短的音频资源。当音频流较大不足以在音频缓冲中一次写入时,可采用流模式。  AudioTrack的播放状态包括PLAYSTATE_STOPPED、PLAYSTATE_PAUSED、PLAYSTATE_PLAYING等。  AudioTrack实例的状态包括STATE_INITIALIZED、STATE_NO_STATIC_DATA、STATE_UNINITIALIZED等。  向音频缓冲中添加数据的方法为write()。在设置音频缓冲时,其大小与采样率、通道和音频格式有关。其计算公式为:  缓冲大小=最小帧数×(通道==CHANNEL_OUT_STEREO?2:1)×(音频格式== PCM16?2:1)  而最小帧数则受制于采样率和音频设备的延迟等因素。  另外,在Android 2.3中,还引入了会话的概念,便于对单曲的音效进行处理。相应的方法包括:attachAuxEffect()、getAudioSessionId()、setAuxEffectSendLevel()等。  通过AudioTrack.OnPlaybackPositionUpdateListener监听器可以监听播放进度。 下面是一个背景音频的播放过程: 代码10-3  AudioTrack播放音频文件   

public class BackgroundAudio extends Thread { public static final int SAMPLE_RATE = 16000; 
public static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; public static final int BYTES_PER_SAMPLE = 2; 
public static final int PLAYBACK_STREAM = AudioManager.STREAM_MUSIC; …… 
public BackgroundAudio(byte[] data) { 
 //计算缓冲大小  final int minBufferSize = (BUFFER_TIME *SAMPLE_RATE*BYTES_PER_SAMPLE) / 1000; 
  //计算硬件的最小缓冲 
      final int minHardwareBufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE,AudioFormat.CHANNEL_OUT_MONO,AUDIO_FORMAT); 
        mBufferSize = Math.max(minHardwareBufferSize, minBufferSize);             mAudioTrack = new AudioTrack(PLAYBACK_STREAM, SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,  AUDIO_FORMAT, mBufferSize, AudioTrack.MODE_STREAM);         

     if (mAudioTrack.getState() == AudioTrack.STATE_INITIALIZED) {                  writeAudio(); 
        start(); // 启动背景线程去推送音频数据             mAudioTrack.play();         } else { 
        Log.e(TAG, "Error initializing audio track.");           } } …… 
private void writeAudio() {      int len = mData.length;      int count; 
  int maxBytes = Math.min(mBufferSize, len - mPos);  
  count = mAudioTrack.write(mData, mPos, maxBytes);      if (count < 0) { 
       Log.e(TAG, "Error writing looped audio data");          halt();        

  return;       } 
   mPos += count;    

if (mPos == len) { 
       mPos = 0; // Wraparound     }  } }
Media playback
Supported Media Formats
Audio Capture
JetPlayer
Camera  

        这次我先分享下Media Playback的中一些内容以及我学习中的感悟。  

        首先需要我们接触到的最主要的两个类分别是MediaPlayer、MediaManager。MediaPlayer是用来控制音频/视频流或者文件的播放的,需要我们注意的是MediaPlayer对象加上其支持的一些播放操作会形成一个状态机,在不合适的状态执行不合适的操作就会抛出异常,如果开发者不清楚自己创建的MediaPlayer对象当前处于哪个状态,就很有可能调用错误的方法造成程序的异常,而且这些错误很难被察觉,所以错误处理在这个部分就显得尤为重要。  

        下面要说的就是Audio Focus,举个例子,当你在听歌的时候,突然来了一条短信,如果不加处理,短信的声音很可能被音乐的声音湮没,你就会察觉不到。我们希望发生什么事情呢?我们希望这个时候音乐的声音较之前稍微降低些使得我们能够听到短信提示音,在短信提示音结束后音乐的声音再次回到正常。这个过程就是获取和释放audio focus的过程。  

        在写代码的时候,我忽略了一点:Audio Focus is cooperative in nature.  

申请audio focus  

[java] view plaincopyprint?AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
    AudioManager.AUDIOFOCUS_GAIN);    

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
    AudioManager.AUDIOFOCUS_GAIN);
处理focus change事件  

[java] view plaincopyprint?class MyService extends Service
                implements AudioManager.OnAudioFocusChangeListener {
    // ....
    public void onAudioFocusChange(int focusChange) {
        // Do something based on focus change...
    }
}    

class MyService extends Service
                implements AudioManager.OnAudioFocusChangeListener {
    // ....
    public void onAudioFocusChange(int focusChange) {
        // Do something based on focus change...
    }
}  

        申请audio focus和处理focus change一定是互相配合实现的,我一开始写了个service用来播放音乐,在start函数调用前并没有申请audio focus,但是我实现了onAudioFocusChange函数。我期待这个service在focus change时停止播放,但是我发现,当另外一个service申请到audio focus时,之前的service不会出现音乐停止播放的情况。
android培训,就选成都达内,最好的成都软件培训机构,如果你有“达内培训需要多少钱”、“达内培训怎么样”等问题,详情请咨询达内客服(http://www.sctarena.com),我们会给你详细的讲解。
 

android 听筒播放音乐

AudioManager.setMode(AudioManager.MODE_IN_CALL) //设定为通话中即可

还是这一句代码的事,不过记得要加上权限

android.permission.MODIFY_AUDIO_SETTINGS

还有一点需要注意的事,在播放完毕后需要

AudioManager.setMode(AudioManager.MODE_NORMAL);

不然其他软件播放都听筒发声了

实际操作中,仅仅上述代码并不能是实现需求:

荣耀:4..2.2

内核3.4.5


audiomanager.setMode(AudioManager.MODE_IN_CALL);


Nexus 5   5.0.1

内核2.4.0


audiomanager.setMode(AudioManager.MODE_IN_CALL);不能生效,即便添加该行仍然从扬声器播出

   
   
   
 

2:应用场景

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输出通道切换的处理是暂停当前的播放,不直接从新的通道里发出声来。

private class NoisyAudioStreamReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
            // Pause the playback
        }
    }
}

private IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);

private void startPlayback() {
    registerReceiver(myNoisyAudioStreamReceiver(), intentFilter);
}

private void stopPlayback() {
    unregisterReceiver(myNoisyAudioStreamReceiver);
}

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

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

图中:

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

3:Android 文档

Building Apps with Multimedia

These classes teach you how to create rich multimedia apps that behave the way users expect.

  1. Managing Audio Playback

    If your app plays audio, it’s important that your users can control the audio in a predictable manner. To ensure a great user experience, it’s also important that your app manages the audio focus to ensure multiple apps aren’t playing audio at the same time.
    
    After this class, you will be able to build apps that respond to hardware audio key presses, which request audio focus when playing audio, and which respond appropriately to changes in audio focus caused by the system or other applications.
    为用户提供便捷的音频状态控制对良好的用户体验是非常重要的。
    
    你可以构建响应物理音频按键,获取音频播放焦点,以及适时的响应由于系统or其他应用引起的音频焦点变化。
  2. How to respond to hardware audio key presses, request audio focus when playing audio, and respond appropriately to changes in audio focus.
    1. Controlling Your App‘s Volume and Playback
    2. Managing Audio Focus
    3. Dealing with Audio Output Hardware

引用:

http://blog.csdn.net/thl789/article/details/7423523

时间: 2024-10-27 18:38:06

Android Audio Play Out Channel的相关文章

Android -- Audio Native服务之启动流程分析(一)

Android -- Audio Native服务之启动流程分析(一) Android中的Audio系统是比较庞大.繁杂的一部分内容, 其中会涉及较多的音频编解码.多媒体制式与Android Audio HAL设备管理的知识.随着Android的发展,其所支持的音频设备也变得越来丰富,如扬声器.耳机.听筒等等:这种变化也为Android管理如此丰富的音频设备以及如何正确.合理地切换音频输出提出了更高的要求.面对如此繁杂的管理要求,我们分析Android Audio服务的历程想必也不会轻松.接下来

android audio开发的一些专用术语(待翻译)

Audio Terminology IN THIS DOCUMENT Generic Terms Digital Audio Hardware and Accessories Audio Signal Path Android-Specific Terms Sample Rate Conversion This document provides a glossary of audio-related terminology, including a list of widely used, g

Android Exception 10((server)&#39; ~ Channel is unrecoverably broken and will be disposed!)

08-11 19:22:35.028: W/MemoryDealer(2123): madvise(0x43e16000, 12288, MADV_REMOVE) returned Operation not supported on transport endpoint 08-11 19:22:35.038: W/InputDispatcher(2714): channel '4236b890 com.tongyan.activity/com.tongyan.activity.SettingA

Android Audio System 之一:AudioTrack如何与AudioFlinger

Android Framework的音频子系统中,每一个音频流对应着一个AudioTrack类的一个实例,每个AudioTrack会在创建时注册到 AudioFlinger中,由AudioFlinger把所有的AudioTrack进行混合(Mixer),然后输送到AudioHardware中 进行播放 TAG: AudioTrack  音频系统  AudioFlinger 引子 Android Framework的音频子系统中,每一个音频流对应着一个AudioTrack类的一个实例,每个Audi

关于android audio路由策略的修改

关于android audio路由策略的修改 在工作时,往往有这样一些需求:1)希望针对不同的audio stream type(例如music.tts), 有输出到不同的输出设备(例如speaker.headset.BT.usb audio等)的需求,另外还有输出设备的优先级的需求.例如AUX(headset) > BT > FMTX > speaker.即例如BT连接了,那么音频就输出到BT,而不是FM发射.2)针对不同的audio stream type和不同的输出设备,有不同的输

关于android audio路由策略的修改(续)

关于android audio路由策略的修改(续) 承接我的上一篇https://blog.51cto.com/8906847/2367935 文章. 例如你在HUD抬头显示设备中,需要加入FMTX功能,即fm发射功能,另外需要在打开fmtx广播时,音频优先走fmtx芯片,而不是走speaker.那么可以这样实现:1)方法一:通过特定状态标记,来修改audiopolicy的engine.cpp2)方法二:是使用类似如下的方式:如果是Java的,那么可以仿照类似如下的方式:private Audi

[Android][Audio] audio_policy.conf文件分析

不同的Android产品在音频的设计上通常是存在差异的,而这些差异可以同过Audio的配置文件audio_policy.conf来获得.在Android系统中音频配置文件存放路径有两处,存放地址可以从AudioPolicyManagerBase.cpp文件中知道: #define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf" #define AUDIO_POLICY_CONFIG_FILE "/

Android audio HAL详解(一)

http://blog.csdn.net/kunis/article/details/16918937 1,HAL定义 HAL(hardware abstraction layer)从字面意思理解,称为硬件抽象层.它是Android framework层运行的基石,android系统上层所需要的所有有关硬件的操作都需要调用HAL相关的API,如GPS,BT,输入设备,Graphocs,Camera,Audio等.每种硬件设备Android系统都规范了一些功能,各个设备的HAL就是实现这些功能(调

Android Audio Focus的应用(requestAudioFocus)

网址:http://blog.csdn.net/dadoneo/article/details/8252933 FROM: http://www.linuxidc.com/Linux/2012-04/57902.htm ================================================ Android是多任务系统,Audio系统是竞争资源.Android2.2之前,没有内建的机制来解决多个程序竞争Audio的问题,2.2引入了称作AudioFocus的机制来管理对A