I am using MediaPlayer as a Service in my app. I have implemented a mute and unmute feature but I have a problem with the volume when I switch between the two states:
Say the music is playing at max volume and you reduce the volume to halfway while in the unmuted state. Then you mute the sound and then unmute it again. The audio that I hear after unmuting it is noticeably quieter than it was just before I muted it, even though the phone's media volume showed that volume was the same both times.
The opposite is true when playing at a low volume and you increase the volume while in unmuted state. In this case the volume after you unmute sounds louder.
Lastly, when the volume is set to 0 and then unmuted, any change to the volume produces no change to the loudness of the audio. The audio remains mute in this case until I press mute then unmute.
This makes me believe that the loudness of the volume when the music is unmuted has some effect on the audio when you change the volume but I'm not sure how.
The way that I have the volume set when the user unmutes is by using AudioManager and getStreamVolume for the Stream Music.
Here's the code:
Main Activity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
var mService: BackgroundSoundService? = null
var mIsBound: Boolean? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
//button to switch between muted and unmuted
binding.fab.setOnClickListener {
if (mService?.mute == true) {
val currentVolume = mService!!.getVolume()
mService?.mp?.setVolume(currentVolume, currentVolume)
mService?.setMuted(false)
} else if (mService?.mute == false) {
mService?.mp?.setVolume(0f, 0f)
mService?.setMuted(true)
}
}
}
private val serviceConnection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, iBinder: IBinder) {
val binder = iBinder as MyBinder
mService = binder.service
mIsBound = true
}
override fun onServiceDisconnected(arg0: ComponentName) {
mIsBound = false
}
}
private fun bindService() {
Intent(this, BackgroundSoundService::class.java).also { intent ->
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
}
}
private fun unbindService() {
Intent(this, BackgroundSoundService::class.java).also {
unbindService(serviceConnection)
}
}
override fun onStart() {
super.onStart()
bindService()
}
override fun onStop() {
super.onStop()
if (mIsBound == true) {
unbindService()
}
}
}
MediaPlayer Service
class BackgroundSoundService : Service() {
var mute = false
private val mBinder: IBinder = MyBinder()
inner class MyBinder : Binder() {
val service: BackgroundSoundService
get() = this@BackgroundSoundService
}
var mp: MediaPlayer? = null
override fun onBind(intent: Intent): IBinder {
return mBinder
}
override fun onUnbind(intent: Intent?): Boolean {
mp?.stop()
mp?.release()
return false
}
override fun onCreate() {
super.onCreate()
val currentVolume = getVolume()
mp = MediaPlayer.create(this, R.raw.song)
mp?.isLooping = true
mp?.setVolume(currentVolume, currentVolume)
mp?.start()
}
fun setMuted(boolean: Boolean) {
mute = boolean
}
fun getVolume(): Float {
val audio = getSystemService(Context.AUDIO_SERVICE) as AudioManager
return audio.getStreamVolume(AudioManager.STREAM_MUSIC) / 15f
}
}
Any help appreciated,
Thanks
I ended up getting it to work by changing the code in my getVolume function in my Service:
fun getVolume(): Float {
val audio = getSystemService(Context.AUDIO_SERVICE) as AudioManager
val currentVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC)/ 15f
//just added the following line
return (ln(15 - currentVolume) / ln(15.0)).toFloat()
}
Honestly, I don't understand why this works so if you know a way that makes more sense or can explain this to me that would be appreciated.
Thanks