Android开发官方文档---Managing Audio Playback

(1)使用硬件控制应用的声音,在Activity的生命周期内进行设置,只需一次并尽早调用,可以在Activity的OnCreate()方法中设置。

setVolumeControlStream(AudioManager.STREAM_MUSIC);

(2)使用播放按钮控制应用的声音,无论什么时候点击这些按钮,都会广播一个action为ACTION_MEDIA_BUTTON的Intent。

 

定义一个广播接收者就可以接收到广播,并执行相应的操作。

<receiverandroid:name=".RemoteControlReceiver"> 

    <intent-filter> 

       <action android:name="android.intent.action.MEDIA_BUTTON"/> 

    </intent-filter> 

</receiver>

 

public classRemoteControlReceiver extends BroadcastReceiver { 

    @Override 

    public void onReceive(Contextcontext, Intent intent) { 

        if(Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) { 

            KeyEvent event =(KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); 

            if (KeyEvent.KEYCODE_MEDIA_PLAY == event.getKeyCode()){ 

                // Handle key press. 

            } 

       } 

    } 

}

 

AudioManager am =mContext.getSystemService(Context.AUDIO_SERVICE); 

... 

// Start listening forbutton presses 

am.registerMediaButtonEventReceiver(RemoteControlReceiver); 

... 

// Stop listening forbutton presses 

am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);

 

注意:media button event receiver 并不像以往在Activity中注册和Activity不可见或销毁时反注册的情形,应该视应用在什么时候获取audio资源和释放audio资源时进行注册和反注册。

 

(3)管理Audio资源的焦点

使用requestAudioFocus获取声音资源焦点

获取成功返回AUDIOFOCUS_REQUEST_GRANTED

AudioManager am =mContext.getSystemService(Context.AUDIO_SERVICE); 

... 

// Request audio focusfor playback 

int result = am.requestAudioFocus(afChangeListener,       

                                 // Use the music stream. 

                                 AudioManager.STREAM_MUSIC, 

                                 // Request permanent focus. 

                                 AudioManager.AUDIOFOCUS_GAIN); 

    

if (result ==AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { 

   am.registerMediaButtonEventReceiver(RemoteControlReceiver); 

    // Start playback. 

}

注意:当完成playback操作之后记得要

//Abandon audio focus when playback complete     

am.abandonAudioFocus(afChangeListener);

告诉系统你不再需要焦点和取消与AudioManager.OnAudioFocusChangeListener关联。好让其它应用继续完成playback操作。

 

获取Audio焦点,其它的应用声音降低直到焦点返回?

// Request audio focusfor playback 

int result =am.requestAudioFocus(afChangeListener, 

                             // Use the music stream. 

                             AudioManager.STREAM_MUSIC, 

                             // Request permanent focus. 

                             AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK); 

 

if (result ==AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { 

    // Start playback. 

}

 

AUDIOFOCUS_GAIN

指示申请得到的AudioFocus不知道会持续多久,一般是长期占有;

AUDIOFOCUS_GAIN_TRANSIENT

指示要申请的AudioFocus是暂时性的,会很快用完释放的;

AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK

不但说要申请的AudioFocus是暂时性的,还指示当前正在使用AudioFocus的可以继续播放,只是要“duck”一下(降低音量)。

 

返回值,可能是:

 AUDIOFOCUS_REQUEST_GRANTED:申请成功;

 AUDIOFOCUS_REQUEST_FAILED:申请失败。

 

(4)处理焦点丢失,添加监听器

 AudioManager.OnAudioFocusChangeListener是申请成功之后监听AudioFocus使用情况的Listener,后续如果有别的程序要竞争AudioFocus,都是通过这个Listener的onAudioFocusChange()方法来通知这个AudioFocus的使用者的。

 

OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() { 

    public void onAudioFocusChange(intfocusChange) { 

        if(focusChange == AUDIOFOCUS_LOSS_TRANSIENT )

            // Pause playback 

        } elseif (focusChange == AudioManager.AUDIOFOCUS_GAIN) { 

            // Resume playback  

        } elseif (focusChange == AudioManager.AUDIOFOCUS_LOSS) { 

           am.unregisterMediaButtonEventReceiver(RemoteControlReceiver); 

           am.abandonAudioFocus(afChangeListener); 

            // Stop playback 

       } 

    } 

};

 

Duck模式:降低其它应用的声音

OnAudioFocusChangeListenerafChangeListener = new OnAudioFocusChangeListener() { 

    public void onAudioFocusChange(intfocusChange) { 

        if(focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { 

            // Lower the volume 

        } elseif (focusChange == AudioManager.AUDIOFOCUS_GAIN) { 

            // Raise it back to normal 

       } 

    } 

};

 

 AUDIOFOCUS_GAIN:获得了Audio Focus;

 AUDIOFOCUS_LOSS: 失去了AudioFocus,并将会持续很长的时间。这里因为可能会停掉很长时间,所以不仅仅要停止Audio的播放,最好直接释放掉Media资源。而因为停止播放Audio的时间会很长,如果程序因为这个原因而失去AudioFocus,最好不要让它再次自动获得AudioFocus而继续播放,不然突然冒出来的声音会让用户感觉莫名其妙,感受很不好。这里直接放弃AudioFocus,当然也不用再侦听远程播放控制【如下面代码的处理】。要再次播放,除非用户再在界面上点击开始播放,才重新初始化Media,进行播放。

 AUDIOFOCUS_LOSS_TRANSIENT:暂时失去AudioFocus,并会很快再次获得。必须停止Audio的播放,但是因为可能会很快再次获得AudioFocus,这里可以不释放Media资源;

 

AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:暂时失去AudioFocus,但是可以继续播放,不过要降低音量。

 

(5)典型的应用AudioFocus的场景

下面的时序图描述了AudioFocus被抢占与再次获取的典型场景:

Audio Focus被抢占与再次获取的时序图

注意:为了描述简单,此图中除了两个竞争AudioFocus的App之外,只用AudioManager表征了Android的AudioFocus机制中内部参与的对象,实际AudioManager只是外部的表象,内部参与的对象很多,回调函数也并非简单的直接由AudioManager调用,其中还包含了复杂的IPC机制。

图中:

AudioFocusClient通过requestAudioFocus()获取AudioFocus,在获得AudioFocus之后,开始播放Audio[Step#1 ~ #2];

其它程序(OtherApp)也通过requestAudioFocus()获取AudioFocus [Step#3]

AudioFocusClient失去了Audio Focus,在onAudioFocusChanged()中,根据focusChange【focusChange的值与OtherApp申请时的durationHint相反,即focusChange = -1*durationHint】的值,做第二节中所描述的处理[Step#4];

其它程序(Other App)获取AudioFocus之后,开始播放Audio[Step#5];

其它程序(OtherApp)使用Audio之后,通过abandonAudioFocus()归还AudioFocus [Step#6];

AudioFocusClient重新获得了Audio Focus,可做进一步的处理 [Step#7] 

小结

AudioFocus机制要参与各方充分理解并统一遵照施行,有没有遵照者或者实现有误的程序存在就可能打破这一机制,带来糟糕的用户体验。在保证Built-in程序没问题的前提下,如果进入AndroidMarket之前的程序都严格执行了AudioFocus相关的测试,应该也没问题。

使用Audio的程序要做到:

使用前,用requestAudioFocus()申请AudioFocus,并根据应用的实际选取恰当的durationHint值;

正确的在AudioManager.OnAudioFocusChangeListener中响应AudioFocus失去和重新获取事件;

Audio使用结束,用

abandonAudioFocus()

归还AudioFocus。

 

(6)AudioManager的一般使用

来自 <http://blog.csdn.net/winson_jason/article/details/8126856>

AudioManager除了能在AudioFocus中使用外,最主要的是它能控制声音和铃声

 

这里只讲述几个比较常用到的方法:

adjustVolume(intdirection, int flags) ——用来控制手机音量大小,当传入的第一个参数为 AudioManager.ADJUST_LOWER时,可将音量调小一个单位,传入AudioManager.ADJUST_RAISE 时,则可以将音量调大一个单位。

adjustStreamVolume(intstreamType, int direction, int flags)——(以步长)调节手机音量大小

参数1:声音类型,可取为STREAM_VOICE_CALL(通话)、STREAM_SYSTEM(系统声音)、STREAM_RING(铃声)、STREAM_MUSIC(音乐)、STREAM_ALARM(闹铃声)

参数2:调整音量的方向,可取ADJUST_LOWER(降低)、ADJUST_RAISE(升高)、ADJUST_SAME

参数3:可选的标志位

setStreamVolume(intstreamType, int index, int flags)——直接设置音量大小

getMode() ——返回当前音频模式,如NORMAL(普通), RINGTONE(铃声), or IN_CALL(通话)

setMode()——设置声音模式,可取值NORMAL(普通),RINGTONE(铃声), or IN_CALL(通话)

getRingerMode()——返回当前的铃声模式。如RINGER_MODE_NORMAL(普通)、RINGER_MODE_SILENT(静音)、RINGER_MODE_VIBRATE(震动)

setRingerMode(intringerMode) ——改变铃声模式

getStreamVolume(intstreamType) ——取得当前手机的音量,最大值为7,最小值为0,当为0时,手机自动将模式调整为“震动模式”。

getStreamMaxVolume(intstreamType)——获得当前手机最大铃声。

setStreamMute(intstreamType, boolean state)

//音量控制,初始化定义

AudioManagermAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);

//最大音量

int  maxVolume =mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);

//当前音量

int  currentVolume =mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

直接控制音量的多少:

以一步步长控制音量的增减,并弹出系统默认音量控制条:

 

//降低音量,调出系统音量控制

if(flag ==0){

            mAudioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC

                                                                            ,AudioManager.ADJUST_LOWER

                                                                            ,AudioManager.FX_FOCUS_NAVIGATION_UP);

}else if(flag ==1){ 

//增加音量,调出系统音量控制

            mAudioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC

                                                                            ,AudioManager.ADJUST_RAISE

        ,AudioManager.FX_FOCUS_NAVIGATION_UP);

}

 

常用方法:

androidaudioManager获取音量:

先获取AudioManager实例,

AudioManagermAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

//通话音量

int max =mAudioManager.getStreamMaxVolume( AudioManager.STREAM_VOICE_CALL ); 

int current =mAudioManager.getStreamVolume( AudioManager.STREAM_VOICE_CALL ); 

//系统音量

int max =mAudioManager.getStreamMaxVolume( AudioManager.STREAM_SYSTEM ); 

current =mAudioManager.getStreamVolume( AudioManager.STREAM_SYSTEM ); 

//铃声音量

max =mAudioManager.getStreamMaxVolume( AudioManager.STREAM_RING ); 

current =mAudioManager.getStreamVolume( AudioManager.STREAM_RING ); 

//音乐音量

max =mAudioManager.getStreamMaxVolume( AudioManager.STREAM_MUSIC ); 

current =mAudioManager.getStreamVolume( AudioManager.STREAM_MUSIC ); 

//提示声音音量

max =mAudioManager.getStreamMaxVolume( AudioManager.STREAM_ALARM ); 

current =mAudioManager.getStreamVolume( AudioManager.STREAM_ALARM ); 

 

(7)处理Audio硬件设备

查找正在使用的声音设备

if(isBluetoothA2dpOn()) { 

    // Adjust output forBluetooth. 

} else if(isSpeakerphoneOn()) { 

    // Adjust output forSpeakerphone. 

} else if(isWiredHeadsetOn()) { 

    // Adjust output for headsets 

} else {  

    // If audio plays and noone can hearit, is it still playing? 

}

 

当耳机设备或蓝牙设备断开连接之后,Audio设备自动切换到喇叭,会发送ACTION_AUDIO_BECOMING_NOISY 广播,注册一个广播接收者用于接收该 广播就可以控制声音播放

private classNoisyAudioStreamReceiver extends BroadcastReceiver { 

    @Override 

    public void onReceive(Contextcontext, Intent intent) { 

        if(AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) { 

            // Pause the playback 

       } 

    } 

 

private IntentFilterintentFilter = newIntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY); 

 

private voidstartPlayback() { 

   registerReceiver(myNoisyAudioStreamReceiver(), intentFilter); 

 

private voidstopPlayback() { 

   unregisterReceiver(myNoisyAudioStreamReceiver); 

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值