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);不能生效,即便添加该行仍然从扬声器播出 |
设备 | audio path | media paly new | |
Actually you don't need audioManager.setSpeakerphoneOn(false); . And also, you need to create MediaPlayer not with static method MediaPlayer.create(), but you need to create it with new MediaPlayer()... – Andranik Jun 12 '14 at 18:40 up vote
16
down vote
accepted
Audio handling on Android is going to be pretty horrible for a while. The APIs are pretty weird, poorly documented, and keep changing/deprecating/breaking between versions. Even the AudioManager code has FIXMEs in it. Anyway, there are several stream types in Android (music, notifications, phone calls, etc.) and applications are meant to choose the appropriate one for playback. I imagine the majority of Android apps should use the music/media type (STREAM_TYPE_MUSIC). You set this on your MediaPlayer using the setAudioStreamType method. The SDK does allow you to set a single stream type as solo — causing all other streams to be muted — but I don't believe you can identify the audio being played back by particular applications and somehow pause/unpause it. Music applications in general will use the PhoneStateListener to pause themselves when a call comes in. So in your case, you could "borrow" the phone call stream for your MediaPlayer and use the method call AudioManager.setStreamSolo(AudioManager.STREAM_VOICE_CALL, true) when playback begins, then un-solo the stream with false when playback or your Activity is done. I can tell you that this works, but I can't remember offhand whether you need to also set the audio mode to MODE_IN_CALL when using the voice call stream (like this: AudioManager.setMode(AudioManager.MODE_IN_CALL)). If you find that is required, then you need to make sure you return the mode to MODE_NORMAL once playback completes, otherwise whenever you press the volume hard keys, it'll say "In-call volume"! However, if and when you do want to change back to MODE_NORMAL, you must check that a genuine phone call isn't happening at that time... Maybe you could use another stream type rather than the voice call one, but I'm just speaking from experience working on an app that could use either the speakerphone or the earpiece for audio playback, which requires the use of the voice call stream. Like I said, audio handling isn't particularly fun... ;)
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.
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其他应用引起的音频焦点变化。
How to respond to hardware audio key presses, request audio focus when playing audio, and respond appropriately to changes in audio focus.
引用:
http://blog.csdn.net/thl789/article/details/7423523
Android Audio Play Out Channel的更多相关文章
- Android Audio遇到播放无声时的分析
在Android Audio开发过程中,有遇到播放ringtone时无声,但播放Music可以听到声音,关于无声问题的分析,在此做个笔记,方便以后回顾. 分析方向: 1:在音量控制面板中确认该音频流对 ...
- 转载:android audio policy
Audio policy basic:https://www.cnblogs.com/CoderTian/p/5705742.html Set volume flow:https://blog.csd ...
- Android Audio控制和MediaButton远程控制(音视频控制配合)
使用过Android系统的朋友应该都知道,Android里面声音是区分好几种情况,每种情况下的音频大小是独立的.也就是说你调节了电话铃声大小不会影响多媒体播放的声音大小.这个涉及了AudioStrea ...
- [Android][Audio] audio_policy.conf文件分析
不同的Android产品在音频的设计上通常是存在差异的,而这些差异可以同过Audio的配置文件audio_policy.conf来获得.在Android系统中音频配置文件存放路径有两处,存放地址可以从 ...
- Android Audio System 之一:AudioTrack如何与AudioFlinger
Android Framework的音频子系统中,每一个音频流对应着一个AudioTrack类的一个实例,每个AudioTrack会在创建时注册到 AudioFlinger中,由AudioFlinge ...
- Android Audio Focus的应用(requestAudioFocus)
网址:http://blog.csdn.net/dadoneo/article/details/8252933 FROM: http://www.linuxidc.com/Linux/2012-04/ ...
- 转---Android Audio System 之一:AudioTrack如何与AudioFlinger交换音频数据
引子 Android Framework的音频子系统中,每一个音频流对应着一个AudioTrack类的一个实例,每个AudioTrack会在创建时注册到 AudioFlinger中,由AudioFli ...
- android audio
package com.javacodegeeks.android.audiocapturetest; import java.io.IOException; import android.media ...
- 转载:android audio flinger
https://blog.csdn.net/innost/article/details/6142812 https://blog.csdn.net/zyuanyun/article/details/ ...
随机推荐
- jodd-StringTemplateParser使用
StringTemplateParser 时一个string模板的解析器.在string模板中定义类似jsp标签的宏. 在解析过程中,宏被对值替换,值通过自定义的MacroResolver解析得到. ...
- curl模拟Http请求
一.get请求 curl "http://www.baidu.com" 如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地 curl -i "http://w ...
- 分治法(一)(zt)
这篇文章将讨论: 1) 分治策略的思想和理论 2) 几个分治策略的例子:合并排序,快速排序,折半查找,二叉遍历树及其相关特性. 说明:这几个例子在前面都写过了,这里又拿出来,从算法设计的策略的角度把它 ...
- postgres函数
1.数据修复最先考虑通过db内做修复,实在不行,在考虑外部应用程序通过jdbc修复. 比如一个场景:profile_image_url与enlarge_image_url都是微博用户信息返回的字段. ...
- 给label绘制下划线
UIlabel本身没有下划线的属性,使用绘制的方法,添加下滑下,并且赋给该label一个action作为响应方法,实现DIY超链接的效果. //调用 #import "UnderLineLa ...
- extjs采用fileupload进行文件上传后台实现
前台js: form: Ext.define("GS.base.BasicImportForm",{ extend:"Ext.form.Panel", ...
- Float精度 在JS的解决方法
最近在做一个工资核算的系统,所有的运算全部在前台进行,因此用了的是JS来做. 做完以后,经手工核算,发现一个奇怪的问题.就是JS算出来的结果跟用计算器算出来的结果有差距. 想了很久,也没有想出问题出在 ...
- HTML超出文本显示省略号...[text-overflow]
需要对div或者span同时应用Css: text-overflow:ellipsis; white-space:nowrap; overflow:hidden; 即可实现所想要得到的溢出文本显示省略 ...
- 怒学三算法 POJ 2387 Til the Cows Come Home (Bellman_Ford || Dijkstra || SPFA)
Til the Cows Come Home Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33015 Accepted ...
- HDU 1003 Max Sum && HDU 1231 最大连续子序列 (DP)
Max Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...