Audio系统是竞争资源,因为在只有一个音频输出,2.2引入了称作AudioFocus的机制来管理对Audio资源的竞争的管理与协调。
按照AudioFocus的机制,在使用Audio之前,需要申请AudioFocus,在获得AudioFocus之后才可以使用Audio;如果有别的程序竞争你正在使用的Audio,你的程序需要在收到通知之后做停止播放或者降低声音的处理。值得指出的是,这种机制是需要合作完成的,需要所有使用Audio资源的程序都按照这种机制来做,而如果有程序在它失去AudioFocus的时候仍然在使用Audio,AudioFocus拿它也没办法。而这一点对于开放系统的Android来说很致命的:用户可能安装没遵守这种机制的程序,或者版本太老还没引入这种机制的程序,这最终会导致很差的用户体验。
获取或放弃AudioFocus的方法都在android.media.AudioManager中,获取AudioFocus用requestAudioFocus();用完之后,放弃AudioFocus,用bandonAudioFocus()。
使用前,用requestAudioFocus()申请AudioFocus,并根据应用的实际选取恰当的durationHint值;
正确的在AudioManager.OnAudioFocusChangeListener中响应AudioFocus失去和重新获取事件;
Audio使用结束,用abandonAudioFocus()归还AudioFocus。
TYPE_RINGTONE 手机来电铃声
TYPE_ALARM 手机闹钟铃声
TYPE_NOTIFICATION 手机提示音
ToneGenerator Android系统拨号盘按键发声(专门播放DTMF类型)
STREAM_DTMF 双音多频
拨号音 摘机后受话器中便有一种“嗡--”的连续音,这种声音就是拨号音,它表示自动交换机或对方呼叫中心系统已经做好了接续准备,允许用户拨号。拨号音又叫DTMF音。是同时发出2个频率进行叠加的音。
AudioFocusChangeListner 监听声音焦点
AUDIOFOCUS_GAIN 获取较长期的焦点
AUDIOFOCUS_LOSS 失去较长期的焦点
AUDIOFOCUS_GAIN_TRANSIENT 获取的短暂的焦点,不久就会失去
AUDIOFOCUS_LOSS_TRANSIENT 临时失去了音频焦点,不久就会再返回来
MediaRecorder 用于录像录音
file.renameTo 把当前文件重命名(移动)为某个文件
.aac文件 高级音频编码
SeekBar.OnSeekBarChangeListener 当进度改变后用于通知客户端的回调函数。这包括用户通过手势、方向键或轨迹球触发的改变, 以及编程触发的改变。
onProgressChanged 进度已经被修改
onStartTrackingTouch 用户已经开始一个触摸拖动手势
onStopTrackingTouch 用户触摸手势已经结束
TYPE_RINGTONE 手机来电铃声
TYPE_ALARM 手机闹钟铃声
TYPE_NOTIFICATION 手机提示音
ToneGenerator Android系统拨号盘按键发声(专门播放DTMF类型)
STREAM_DTMF 双音多频
拨号音 摘机后受话器中便有一种“嗡--”的连续音,这种声音就是拨号音,它表示自动交换机或对方呼叫中心系统已经做好了接续准备,允许用户拨号。拨号音又叫DTMF音。是同时发出2个频率进行叠加的音。
AudioFocusChangeListner 监听声音焦点
AUDIOFOCUS_GAIN 获取较长期的焦点
AUDIOFOCUS_LOSS 失去较长期的焦点
AUDIOFOCUS_GAIN_TRANSIENT 获取的短暂的焦点,不久就会失去
AUDIOFOCUS_LOSS_TRANSIENT 临时失去了音频焦点,不久就会再返回来
MediaRecorder 用于录像录音
file.renameTo 把当前文件重命名(移动)为某个文件
.aac文件 高级音频编码
SeekBar.OnSeekBarChangeListener 当进度改变后用于通知客户端的回调函数。这包括用户通过手势、方向键或轨迹球触发的改变, 以及编程触发的改变。
onProgressChanged 进度已经被修改
onStartTrackingTouch 用户已经开始一个触摸拖动手势
onStopTrackingTouch 用户触摸手势已经结束
res/raw这个文件夹是放音频文件的。
代码中R.raw.class.getDeclaredFields()获得所有字段,再遍历取出想要的属性(如果想要歌曲需判断下是否是语音通话),如:
if (!fields[i].getName().equals("voicecall")) {
rawName = fields[i].getName();
1。点击VoiceCall进入判断,如果没在播放歌曲并且获取音频焦点成功便播放音乐:
if (!mediaPlayer.isPlaying()) {
if (AudioManager.AUDIOFOCUS_REQUEST_GRANTED == audioManager.requestAudioFocus(voiceCallFocusChangeListner, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN)) {
mediaPlayer.start();
如果在播放则暂停并放弃音频焦点,AudioAttributes是一个封装音频各种属性的类,设置音频流属性。:
mediaPlayer.pause();
AudioAttributes.Builder attrBuilder = new AudioAttributes.Builder();
attrBuilder.setLegacyStreamType(AudioManager.STREAM_VOICE_CALL);
AudioFocusRequest.Builder audioFocusBuilder = new AudioFocusRequest.Builder(1);
audioFocusBuilder.setOnAudioFocusChangeListener(voiceCallFocusChangeListner);
audioFocusBuilder.setAudioAttributes(attrBuilder.build());
audioManager.abandonAudioFocusRequest(audioFocusBuilder.build());
声音类型:
STREAM_VOICE_CALL(通话)
STREAM_SYSTEM(系统声音)
STREAM_RING(铃声)
STREAM_MUSIC(音乐)
STREAM_ALARM(闹铃声)
2。点击System播放按键点击声音:
audioManager.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD);
3。touch DTMF,当按下时播放拨号盘设置按键的声音:
if(event.getAction() == MotionEvent.ACTION_DOWN){
if (ToneGenerator.TONE_DTMF_D == DTMFPos)
{
DTMFPos = ToneGenerator.TONE_DTMF_0;
}
toneGenerator.startTone(DTMFPos,1000);
当弹起时停止播放拨号盘设置按键的声音:
if(event.getAction() == MotionEvent.ACTION_UP){
toneGenerator.stopTone();
4。点击Ring获取手机来电铃声并播放:
ringtone = RingtoneManager.getRingtone(
mainActivity.getApplicationContext(), uriRing);
ringtone.setStreamType(AudioManager.STREAM_RING);
ringtone.play();
5。点击Notification获取手机提示音并播放:
ringtone.setStreamType(AudioManager.STREAM_NOTIFICATION);
6。点击Alarm获取手机闹钟铃声并播放:
ringtone.setStreamType(AudioManager.STREAM_ALARM);
7。点击TTS播放语音播报:
if (speech == null) speech = new TextToSpeech(mainActivity, new TTSListener());
speech.speak(str, TextToSpeech.QUEUE_ADD, bundle, this.toString());
8。点击RecorderClick录音。
9。点击Stop停止所有。
10。点击Previous播放上一曲。
11。点击Play播放或暂停歌曲。
12。点击Next播放下一首歌曲。
SimpleDateFormat time = new SimpleDateFormat("HH:mm:ss");
SimpleDateFormat("HH:mm:ss")加上HH后显示不正确解决方法:可以将毫秒数 - TimeZone.getDefault().getRawOffset();即可。