Android Audio系统之RingerMode

来源:互联网 发布:淘宝好评兼职 编辑:程序博客网 时间:2024/05/12 06:41

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

田海立@CSDN

2012-04-11

本文介绍Android系统中Audio里的RingerMode。从使用的角度,只要关注第一节AudioManager中对于RingerMode的接口;后面章节讲解了AudioService中对于RingerMode的内部实现,以及如何改变RingerMode对某一个AudioStream的影响。

 

一、利用AudioManager使用RingerMode

RingerMode的获取与设置都是通过AudioManager来进行的。通过context.getSystemService(Context.AUDIO_SERVICE)获得AudioService的本地代理,然后通过调用AudioManager的getRingerMode()/setRingerMode()来获取当前的RingerMode或设置RingerMode。

RingerMode_AudioManager

RingerMode有三种:RINGER_MODE_SILENT,RINGER_MODE_VIBRATE和RINGER_MODE_NORMAL。

RingerMode设置之后,会有广播RINGER_MODE_CHANGED_ACTION发出,并且新的RingerMode会被设置在EXTRA_RINGER_MODE里,广播RINGER_MODE_CHANGED_ACTION的接收者时,可以通过Intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE)获得更改过的RingerMode。

 

二、RingerMode在AudioService中内部实现

AudioManager不过是在本地的一个代理,具体的实现还是在AudioService中。

RingerMode_AudioService

RingerMode在AudioService中通过mRingerMode记录;永久存储还是在Settings.System中,对应的设置项是MODE_RINGER,可通过Settings.System.getInt()/putInt()来操作。

《Android中的Audio播放:音量和远程播放控制》中描述的AudioStream是AndroidAudio系统的基础。因为设置RingerMode时,主要牵涉到静音操作,而Android的Audio音量和静音是按照AudioStream来设定的。

看AudioService中关于如何设置RingerMode的[方法setRingerModeInt()的实现]:

[java] view plaincopy
  1. mRingerMode = ringerMode;  
  2. int numStreamTypes = AudioSystem.getNumStreamTypes();  
  3. for (int streamType = numStreamTypes – 1; streamType >= 0; streamType--) {  
  4.     if (isStreamMutedByRingerMode(streamType)) {   
  5.         if (!isStreamAffectedByRingerMode(streamType) ||  
  6.                 mRingerMode == AudioManager.RINGER_MODE_NORMAL) {  
  7.             mStreamStates[streamType].mute(nullfalse);    // unmute {streamType}  
  8.             mRingerModeMutedStreams &= ~(1<< streamType);  
  9.         }  
  10.     } else {  
  11.         if (isStreamAffectedByRingerMode(streamType) &&  
  12.                 mRingerMode !=AudioManager.RINGER_MODE_NORMAL) {  
  13.             mStreamStates[streamType].mute(nulltrue);    // mute {streamType}  
  14.             mRingerModeMutedStreams |=~(1<< streamType);  
  15.         }  
  16.     }  
  17. }  

  • 改变RingerMode是否影响某一个AudioStream的音量(静音)是由isStreamAffectedByRingerMode(streamType:int) [Line#5 & Line#10]决定的,而该方法是检查mRingerModeAffectedStreams上针对该AudioStream的位上是否被置位,亦即,mRingerModeAffectedStreams是某个AudioStream是否受RingerMode影响的Bitmasks。
  • 如果AudioStream被静音,则在mRingerModeMutedStreams的相应位上置位做标志。所以mRingerModeMutedStreams是标识AudioStream是否因为RingerMode的设置而静音的所有Stream的Bitmasks。
  • RingerMode记录在mRingerMode,但永久存储是通过Settings.System,所以设置完具体的RingerMode之后,通过Settings.System.putInt(cr,Settings.System.MODE_RINGER, mRingerMode)保存当前的RingerMode。

 

三、配置RingerMode对特定AudioStream的影响

前节中讲到,某一个AudioStream是否受设置RingerMode影响是由mRingerModeAffectedStreams决定的,也就是即便设置RingerMode为静音/震动模式(RINGER_MODE_SILENT/RINGER_MODE_VIBRATE)之后, 某个AudioStream还不一定被设置为静音,而是否起作用,关键取决于mRingerModeAffectedStreams上对应于该AudioStream的位上取值。

mRingerModeAffectedStreams在AudioService中初始值是通过Settings.System.getInt(MODE_RINGER_STREAMS_AFFECTED, defVal)获取的

[java] view plaincopy
  1. mRingerModeAffectedStreams= Settings.System.getInt(cr,Settings.System.MODE_RINGER_STREAMS_AFFECTED,  
  2.         ((1 << AUdioSystem.STREAM_RING) | (1 << AudioSystem.STREAM_NOTIFICATION) |  
  3.         (1 << AudioSystem.STREAM_SYSTEM)| (1<< AudioSystem.STREAM_SYSTEM_ENFORCED)));  

可以看到,默认有四个AudioStream是受RingerMode设置的影响的。

这样,可以通过设置Settings.System.MODE_RINGER_STREAMS_AFFECTED来改变受RingerMode设置影响的AudioStream。

比如,Alarm的“静音模式下是否闹铃”的设置就是通过对AudioStreamSTREAM_ALARM的置位/去位实现的:

[java] view plaincopy
  1. int ringerModeStreamTypes = Settings.System.getInt(cr, Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);  
  2. if (pref.isChecked()) {  
  3.     // 静音模式下仍然闹铃,也就是Alarm不受RingerMode设置的影响  
  4.     ringerModeStreamTypes &= ~(1 << AudioManager.STREAM_ALARM);  
  5. else {  
  6.     // 静音模式下不闹铃,也就是Alarm受RingerMode设置的影响  
  7.     ringerModeStreamTypes |= (1 << AudioManager.STREAM_ALARM);  
  8. }  
  9. Settings.System.putInt(cr, Settings.System.MODE_RINGER_STREAMS_AFFECTED, ringerModeStreamTypes);  

 

一旦MODE_RINGER_STREAMS.AFFECTED被改变,AudioService中会重新获取并更新mRingerModeMutedStreams的值,并再通过setRingerModeInt()设置mRingerModeMutedStreams改变后的RingerMode。

AudioService中通过SettingObserver(继承ContentObserver)在侦听这个设置项的改变而实现的。

[java] view plaincopy
  1. SettingObserver() {  
  2.     mContentResolver.registerContentObserver(Settings.System.getUriFor(Settings.System.MODE_RINGER_STREAMS_AFFECTED), falsethis);  
  3.     // ...  
  4. }  
  5.   
  6. @override  
  7. public void onChange(boolean selfChange) {  
  8.     // ...  
  9.     int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver, Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);  
  10.     if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {  
  11.         mRingerModeAffectedStreams = ringerModeAffectedStreams;  
  12.         setRingerModeInt(getRingerMode(), false);  
  13.     }  
  14.     // ...  
  15. }  


总结

  1. RingerMode由Android系统统一管理的;
  2. 设置RingerMode是否影响某个AudioStream的设置是可配置的,可以通过配置来改变受RingerMode影响的AudioStream;
  3. RingerMode有所改变,可以通过广播获知。


0 0