最近接收公司的IM項目,遇到一個歷史遺留下來的問題(三星手機(jī)在語音消息播放時手機(jī)音量鍵無法控制聲音的大?。?。由于第一次接觸音頻類的東西。在這方面經(jīng)驗還是有些不足。在尋找這個問題的解決方案時,也是浪費了不少時間。在此記錄一下。希望可以幫助到有相同問題的小伙伴。
1、經(jīng)測試對比同行軟件:三星手機(jī)的音頻播放音量是由媒體音量控制,不管是外放還是聽筒模式。(這里項目是由MediaPlayer進(jìn)行播放的)
2、解決思路:1.通過監(jiān)聽手機(jī)側(cè)鍵,手動更改媒體音量。2.通過注冊廣播監(jiān)聽手機(jī)音量的改變,更改媒體音量。
具體代碼如下:(伸手黨福利)
第一種方案:
private lateinit var audioManager: AudioManager
private var mMusicMaxVolume = 0 //手機(jī)設(shè)置的最大媒體音量
private var mVoiceCallMaxVolume = 0//手機(jī)設(shè)置的最大通話音量
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 {
//如果是三星手機(jī),則聽筒模式音量設(shè)置要設(shè)置媒體音量(加上判斷三星手機(jī)代碼邏輯較嚴(yán)謹(jǐn))
if (audioManager.mode == AudioManager.MODE_IN_COMMUNICATION && !audioManager.isSpeakerphoneOn && (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)) {
//當(dāng)前通話音量
val mCurrentVoiceCallVolume =
audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL)
//計算出當(dāng)前媒體音量
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
)
//當(dāng)前改變的值
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大于最大值導(dǎo)致的異常奔潰情況
mLog.e(
"SamsungVolumeBroadCast",
"currentVolume=${mCurrentMusicVolume},mMusicMaxVolume=${mMusicMaxVolume}"
)
audioManager.setStreamVolume(
AudioManager.STREAM_MUSIC,
mCurrentMusicVolume,
AudioManager.USE_DEFAULT_STREAM_TYPE
)
}
}
}
還有注意的是切換聽筒模式的時候記得設(shè)置下媒體音量,以免一開始無聲
audioManager.isSpeakerphoneOn = false //關(guān)閉揚聲器
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
//三星手機(jī)聽筒模式要設(shè)置媒體音量
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
)