最近接收公司的IM项目,遇到一个历史遗留下来的问题(三星手机在语音消息播放时手机音量键无法控制声音的大小)。由于第一次接触音频类的东西。在这方面经验还是有些不足。在寻找这个问题的解决方案时,也是浪费了不少时间。在此记录一下。希望可以帮助到有相同问题的小伙伴。
1、经测试对比同行软件:三星手机的音频播放音量是由媒体音量控制,不管是外放还是听筒模式。(这里项目是由MediaPlayer进行播放的)
2、解决思路:1.通过监听手机侧键,手动更改媒体音量。2.通过注册广播监听手机音量的改变,更改媒体音量。
具体代码如下:(伸手党福利)
第一种方案:
private lateinit var audioManager: AudioManager
private var mMusicMaxVolume = 0 //手机设置的最大媒体音量
private var mVoiceCallMaxVolume = 0//手机设置的最大通话音量
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
mVoiceCallMaxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL)
mMusicMaxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
//如果是三星手机,则听筒模式音量设置要设置媒体音量(加上判断三星手机代码逻辑较严谨)
if (audioManager.mode == AudioManager.MODE_IN_COMMUNICATION && !audioManager.isSpeakerphoneOn && (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
//当前通话音量
val mCurrentVoiceCallVolume =
audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL)
//计算出当前媒体音量
val mCurrentMusicVolume =
mCurrentVoiceCallVolume * mMusicMaxVolume / mVoiceCallMaxVolume
Log.e(
"TAG",
"currentVolume=" + mCurrentMusicVolume + "mMusicMaxVolume=" + mMusicMaxVolume
)
audioManager.setStreamVolume(
AudioManager.STREAM_MUSIC,
mCurrentMusicVolume,
AudioManager.USE_DEFAULT_STREAM_TYPE
)
}
return super.onKeyDown(keyCode, event)
}
第二种方案:
private lateinit var volumeBroadCastReceiver: SamsungVolumeBroadCastReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
volumeBroadCastReceiver = SamsungVolumeBroadCastReceiver()
registerReceiver(
volumeBroadCastReceiver ,
IntentFilter(SamsungVolumeBroadCastReceiver.Action)
)
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(volumeBroadCastReceiver)
}
class SamsungVolumeBroadCastReceiver : BroadcastReceiver() {
companion object {
const val Action = "android.media.VOLUME_CHANGED_ACTION"
}
private var audioManager: AudioManager =
App.instance.getSystemService(Context.AUDIO_SERVICE) as AudioManager
private var mVoiceCallMaxVolume = 0
private var mMusicMaxVolume = 0
init {
mVoiceCallMaxVolume =
audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL)
mMusicMaxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
}
override fun onReceive(content: Context?, intent: Intent?) {
//改变的类型
val mVolumeType = intent?.getIntExtra(
"android.media.EXTRA_VOLUME_STREAM_TYPE",
-1
)
//当前改变的值
val mNewVolume = intent?.getIntExtra(
"android.media.EXTRA_VOLUME_STREAM_VALUE",
-1
) ?: -1
//改变前的值
val mOldVolume = intent?.getIntExtra(
"android.media.EXTRA_PREV_VOLUME_STREAM_VALUE",
-1
)
//一次音量改变会接收到两次action,这里判断一下mNewVolume和mOldVolume
if (intent?.action == Action && mVolumeType == AudioManager.STREAM_VOICE_CALL && !audioManager.isSpeakerphoneOn && (mNewVolume != mOldVolume)
) {
val mCurrentMusicVolume =
mNewVolume * mMusicMaxVolume / mVoiceCallMaxVolume
//记录一下 怕有计算出来的mCurrentMusicVolume大于最大值导致的异常奔溃情况
mLog.e(
"SamsungVolumeBroadCast",
"currentVolume=${mCurrentMusicVolume},mMusicMaxVolume=${mMusicMaxVolume}"
)
audioManager.setStreamVolume(
AudioManager.STREAM_MUSIC,
mCurrentMusicVolume,
AudioManager.USE_DEFAULT_STREAM_TYPE
)
}
}
}
还有注意的是切换听筒模式的时候记得设置下媒体音量,以免一开始无声
audioManager.isSpeakerphoneOn = false //关闭扬声器
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
//三星手机听筒模式要设置媒体音量
if (SystemUtil.isSamsung()) {
audioManager.setStreamVolume(
AudioManager.STREAM_MUSIC,
audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
AudioManager.USE_DEFAULT_STREAM_TYPE
)
}
audioManager.setStreamVolume(
AudioManager.STREAM_VOICE_CALL,
audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL),
AudioManager.USE_DEFAULT_STREAM_TYPE
)