安卓拓展 MediaPlayer 实现淡入淡出效果

安卓拓展 MediaPlayer 实现淡入淡出效果

@Moriafly 未经允许,严禁搬运抄袭

在椒盐音乐开发中有需求,播放暂停需要实现淡入淡出效果,就是在暂停时慢慢减弱音量而在播放时缓慢增加音量。

MediaPlayer 是 android.meida 下的类,拓展性比不上 ExoPlayer,但是对于这样的淡入淡出效果还是很好实现的。

为什么选择拓展 MediaPlayer 而不是在业务代码中拓展嗯?其实还是因为播放器的播放暂停(按照唯一来源设计)应该只有一处实现调用 MediaPlayer 的 start() 和 pause() ,那就是在媒体会话的回调中(MediaSession),例子:

mediaSessionCallback = object : MediaSessionCompat.Callback() {

	override fun onPlay() {
        mediaPlayer.start()
    }

    override fun onPause() {
        mediaPlayer.pause()
    }
}

而在 onPlay() 和 onPause() 中往往不仅仅是调用播放器的播放暂停,还有如音频焦点管理、耳机拔出噪音广播注册等等。而音频淡入淡出效果设计差值器、播放器状态管理(比如点击暂停,不应该是直接暂停而是当声音慢慢到 0 才暂停音乐,这个过程也是出于 isPlaying 暂停)等等。

话不多说,既然要拓展,那就写个之类继承自 MediaPlayer 。

class AudioPlayer(): MediaPlayer() {

}

setVolume 逻辑改变

我们知道 setVolume(left, right) 是更改左右声道音量大小,而我们的淡入淡出也需要通过这个,但是可能其他时候我们可能也需要调整音量大小,这个多为音效中的“左右声道平衡”。那么这样如果用户需求左右声道音量不一致的话,我们的淡入淡出需要考虑的事情就十分的多:

需要通过百分比计算减少的音量;
用户先前设置的左右声道平衡的数值的记录和保存;
等等。

所以我们可以将其分开,让淡入淡出完全占用 setVolume 的使用权。而左右声道平衡另外考虑。

左右声道平衡的另外考虑
/** 左声道 */
var leftChannel: Float = 1F

/** 右声道 */
var rightChannel: Float = 1F

@OverridePrivate
override fun setVolume(leftVolume: Float, rightVolume: Float) {
    super.setVolume(
    	leftVolume * leftChannel,
        rightVolume * rightChannel
    )
}

淡入淡出的差值变化(以暂停举例)

private var volume = 1F

private var isPauseSmoothing: Boolean = false

private val pauseSmoothValueAnimator = ValueAnimator.ofFloat(1F, 0F).apply {
	duration = 500L
    interpolator = LinearInterpolator()
    addUpdateListener {
        volume = it.animatedValue as Float
        try {
            // 此时可能 MediaPlayer 状态发生了改变,所以用 try catch 包裹,一旦发生错误,立马取消
            setVolume(volume, volume)
        } catch (e: Exception) {
            it.cancel()
        }
    }
    addListener(object : Animator.AnimatorListener {
        override fun onAnimationStart(animation: Animator?) { }

        override fun onAnimationEnd(animation: Animator?) {
            this@AudioPlayer.setVolume(0F, 0F)
            this@AudioPlayer.pause()
            isPauseSmoothing = false
        }

        override fun onAnimationCancel(animation: Animator?) {
            isPauseSmoothing = false
        }

        override fun onAnimationRepeat(animation: Animator?) { }
    })
}

那么我们可以写个缓慢暂停函数

fun pauseSmooth() {
    isPauseSmoothing = true
    pauseSmoothValueAnimator.start()
}

注意记得重写 isPlaying 和 reset 函数

override fun isPlaying(): Boolean {
    if (isPauseSmoothing) {
        return false
    }
    return super.isPlaying()
}

override fun reset() {
    startSmoothValueAnimator.cancel()
    super.reset()
}

播放也是同理。

这样差不多就完成了,实测效果很棒,还可以设置淡入淡出时长,通过设置 ValueAnimator 的 duration 数值。

完整代码

已经发布在 Github 。
链接:https://github.com/Moriafly/SaltPlayerSource/blob/main/source_code/player/AudioPlayer.kt

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值