Search code examples
androidkotlinandroid-mediaplayer

MediaPlayer Volume is Not Consistent When Muting then Unmuting


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


Solution

  • 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