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 = 16000public static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; public static final int BYTES_PER_SAMPLE = 2public 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 pathmedia 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输出发生变化时,捕获并处理这种变化。

AudioNoisy AudioManager

一、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 {@Overridepublic 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_Sequence.jpg

图中:

 

  •  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

转载于:https://www.cnblogs.com/conncui/p/4303795.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/574815.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c html转换成word,C#实现HTML转WORD及WORD转PDF的方法

本文实例讲述了C#实现HTML转WORD及WORD转PDF的方法。分享给大家供大家参考。具体如下&#xff1a;功能&#xff1a;实现HTML转WORD&#xff0c;WORD转PDF具体代码如下&#xff1a;using System;using System.Collections.Generic;using System.ComponentModel;using System.Dat…

bootstrap下拉框分页_【Bootstrap】 bootstrap-select2下拉菜单插件

这次开发了个小TRS系统&#xff0c;虽然是很小&#xff0c;但是作为初心者&#xff0c;第一次用到了很多看起来洋气使用起来有相对简单的各种前端(主要是和bootstrap配合使用)组件。包括bootstrap-select2&#xff0c;bootstrap-datetimepicker&#xff0c;bootstrap-fileinput…

Java-eclipse快捷键及设置

CtrlD: 删除当前行 CtrlAlt↓ 复制当前行到下一行(复制增加) CtrlAlt↑ 复制当前行到上一行(复制增加) Alt↓ 当前行和下面一行交互位置(特别实用,可以省去先剪切,再粘贴了) Alt↑ 当前行和上面一行交互位置(同上) Alt← 前一个编辑的页面 Alt→ 下一个编辑的页面(当然是针对上…

html 网页主题设置吗,如何使用css样式对html页面进行背景设置呢?

摘要:下文讲述css样式对html页面的背景色、背景图片进行相关设置的方法分享&#xff0c;如下所示:在html中&#xff0c;定义元素的背景信息&#xff0c;可以采用以下css属性&#xff0c;如下所示:css属性功能background在此属性中,我们将所有的背景设置都放入此属性值中backgro…

redis 缓存 @class: 会有 $hibernateproxy_微信亿级在线点赞系统,用Redis如何实现?

点赞功能大家都不会陌生&#xff0c;像微信这样的社交产品中都有&#xff0c;但别看功能小&#xff0c;想要做好需要考虑的东西还挺多的&#xff0c;如海量数据的分布式存储、分布式缓存、多 IDC 的数据一致性、访问路由到机房的算法等等。图片来 Pexels本文介绍大型社交平台点…

Xcode怎样调整模拟器大小

快捷键&#xff1a; Command 1&#xff1a;显示100%大小 Command 2&#xff1a;显示50%大小&#xff08;默认&#xff09;转载于:https://www.cnblogs.com/xiaofeng6636/p/4311753.html

查询hive表_大数据中Hive与HBase的区别与联系

二者区别Hive&#xff1a;Hive是基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张数据库表&#xff0c;并提供简单的sql查询功能。Hive本身不存储和计算数据&#xff0c;它完全依赖于HDFS和MapReduce&#xff0c;Hive中的表纯逻辑。hive需要用到hdfs…

查询使用NoLock

当我们在操作数据库的时候&#xff0c;无论是查询还是修改数据库的操作我们都习惯使用using(var dbnew XXXDB()){}&#xff0c;但是如果仅仅是做查询&#xff0c;最好是使用NoLock&#xff0c;因为NoLock使用的是共享锁&#xff0c;可以减少死锁发生的机率。 从上图中代码可以看…

端午粽香html5游戏,《快乐端午粽飘香》亲子活动教案

《快乐端午粽飘香》亲子活动教案过端午节是我国两千多年来的习惯&#xff0c;为了让幼儿更好地了解端午节&#xff0c;感受端午节丰富的文化内涵&#xff0c;激发初步的爱国主义情感&#xff0c;丰富生活经验&#xff0c;应届毕业生考试网小编特意为大家整理了《快乐端午粽飘香…

d3js绘制y坐标轴_【ggplot2】 设置坐标轴

基本箱线图library(ggplot2)bp ggplot(PlantGrowth, aes(xgroup, yweight)) geom_boxplot()bp反转 x轴 与 y轴bp coord_flip()离散型数据的坐标轴改变坐标轴中各项目的顺序 > 特别注意, 离散数据的坐标轴中数据做为 factor 变量处理,他的位置取决于 level的顺序# 手动设置…

html5点击视频跳转,javascript – 播放后重定向html5视频

我有一个html 5视频,我删除了控制按钮并添加了一个js代码,以便用户在点击视频时播放视频.我需要做的是绑定一个额外的脚本,在播放视频后重定向页面而不重新加载页面.下面是我的js代码.function play(){var video document.getElementById(video);video.addEventListener(click…

setInterval

定义和用法&#xff1a; setInterval() 方法可按照指定的周期&#xff08;以毫秒计&#xff09;来调用函数或计算表达式。 setInterval() 方法会不停地调用函数&#xff0c;直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法…

Android working with volley

http://www.cnblogs.com/a284628487/p/4073771.html转载于:https://www.cnblogs.com/soaringEveryday/articles/4320262.html

maya藤蔓插件_MAYA快速打造藤蔓生长的路径动画教程

第一页&#xff1a;MAYA快速打造藤蔓生长的路径动画教程第二页&#xff1a;MAYA快速打造藤蔓生长的路径动画教程第三页&#xff1a;MAYA快速打造藤蔓生长的路径动画教程我相信很多人大部分时间在学习高级技巧&#xff0c;诸如zb mud啦&#xff0c;GI FG啦&#xff0c;motionBui…

移动端拖拽排序 html,移动端拖拽排序

var drag {bindDragEvent: function (isF) {var father document.getElementById("public_theme_list");//父容器var btns father.getElementsByClassName("public-drag-btn");//事件源对象var items father.getElementsByClassName("item")…

pyqt5 qscrollarea到达_pyqt5 QScrollArea设置在自定义侧(任何位置)

本例设置为垂直左侧scroll主要思想是利用一个长度为0的mid_frame&#xff0c;高度为待设置qwidget的高度&#xff0c;用mid_frame的moveEvent事件驱动qwidget的move我项目的效果图&#xff1a;代码及注释from PyQt5.Qt import *from sys import argv# 主窗口class Main(QMainWi…

html页面判断是否登录,egg(103)--egg之定义公共的中间件判断用户是否登录以及去结算页面制作...

判断用户是否登录中间件app/middleware/userauth.jsmodule.exports (options, app) > {return async function init(ctx, next) {//判断前台用户是否登录 如果登录可以进入 ( 去结算 用户中心) 如果没有登录直接跳转到登录var userinfo ctx.service.cookies.get(userinfo)…

3月初的日记:网站工作记录

一直在备考。考一个关于自己本身工作的资格证。也一直在忙碌中&#xff0c;三个项目的并驾齐驱。 可以说&#xff0c;我也很忙。 东北今天下了很大雪&#xff0c;厚厚的&#xff0c;踩上去咯吱咯吱的响&#xff0c;这样的安逸更容易使得心静下来。 但是&#xff0c;其实我是焦虑…

电子科技大学研究生计算机与科学,2019年电子科技大学计算机科学与工程学院考研复试分数线...

据电子科技大学研究生院消息&#xff0c;2019年电子科技大学计算机科学与工程学院考研复试分数线及调剂信息已出&#xff0c;详情如下&#xff1a;专业第一单元第二单元第三单元第四单元总分调剂调剂开放时间调剂结束时间公开招考人数081200计算机科学与技术50458090340不接收2…

debian 重复执行sh_debian 脚本启动方式

同所有的Unix一样,Debian启动时要执行init程序.init的配置文件(/etc/inittab)中指定的第一个执行脚本应该是/etc/init.d/rcS.该脚本执行/etc/rcS.d/目录中各脚本的扩展名指定或衍生进程完成诸如检查并挂载文件系,装载内核模块,启动网络服务,设定时钟等系统初始化工作.接着,为了…