1. 通知播报流程分析:
Android 中用 NotificationManager 处理通知事务,在构建 Notification 时,一般会传入一个音频地址给其中的 sound 字段进行播报,而播报的处理是通过启动 com.android.server.NotificationManagerService 这个服务来完成的,NotificationManagerService 排队处理 notifications,启动
android.media.AudioService 来获取 com.android.systemui.media.RingtonePlayer,然后实例化一个 com.android.systemui.media.NotificationPlayer 来异步播放 sound,流程图如下:
2. 通知音频焦点分析:
在第五步中的 play() 方法中,NotificationPlayer 在工作线程中通过获取音频焦点来播放指定的铃音:
这就是说,如果需要循环播放则焦点持续标记(duration hint)设为 AUDIOFOCUS_GAIN,否则为 AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK。因为循环播放时,预示需要持续通知直到用户知道后显式释放焦点为止,一般适合比较紧急的通知,比如来电通知;如果不需要循环播放,则预示是一个临时的音频预警(duration <= 45 s),在用户显式释放焦点之前如果超过临时设定的阈值(45秒)则会自动释放焦点,这一般适用于非紧急的通知,大多数的通知都应是这种情况。
注意:在 NotificationPlayer 中并没有实现 AudioManager.OnAudioFocusChangeListener() 进行更为复杂的焦点得失处理,这样设计的考虑是因为通知机制的优先级通常是高于其它音频应用的,即它一旦开始则即使焦点被抢占也不会放弃播放过程,直到用户确定已知为止。
3. 参考资料: