安卓系统实现播放器变速功能

安卓开发,目前需要实现一个在安卓5.0系统下实现变速播放的功能。我们知道安卓播放器mediaPlayer实现变速播放功能的API是在安卓系统6.0以上推出的,所以在安卓5.0系统,安卓源码是没有实现变速播放的API,如果我们开发的时候,没有对系统进行判断,在6.0以上安卓系统开发出来的变速播放功能,安装到5.0系统时,调用没有的系统API,程序是会直接崩溃的。通过查看官网,我们了解到android官网的ExoPlayer所以我们有了如下解决方案:

// 设置音乐播放速度 
public static void changeplayerSpeed(float speed) { 
    if (mPlayer == null)  {
        return; 
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
        // API 23 (6.0)以上 ,通过设置Speed改变音乐的播放速率
        if (mPlayer.isPlaying()) {
            // 判断是否正在播放,未播放时,要在设置Speed后,暂停音乐播放
            mPlayer.setPlaybackParams(mPlayer.getPlaybackParams().setSpeed(speed)); 
        } else {
            mPlayer.setPlaybackParams(mPlayer.getPlaybackParams().setSpeed(speed)); 
            mPlayer.pause(); 
        } 
    } else {
        // 在Android6.0以前,需要另想办法处理,后续查到好的方法再补充
    }
}

那么问题来了:在安卓5.0系统,我们该如何实现变速播放的功能呢?
Google为了适配低版本推出了ExoPlayer播放器
具体如何使用网络上也有不少很好的教程:ExoPlayer简单使用。这里的变速播放具体实现代码如下:

 override fun setPlaySpeed(speed: Float) {
        val playbackParameters = PlaybackParameters(speed)
        player?.playbackParameters = playbackParameters
    }

如果需要实现一个播放器功能,我们可以抽取出一个播放器的接口,然后通过实现这个接口的方法来统一包装成一个播放器,接口如下:

/**
 * 播放器包装接口
 * @author guotianhui
 */
public interface IPlayerWapper {

    void prepareDataSource(String mediaSourece);

    void setPlaySpeed(float speed);

    void startPlay();

    void pause();

    void stop();

    void resumePlay();

    boolean isPlaying();

    long getPlayerPosition();

    void seekToPlayerPosition(long progress);

    void releasePlayer();
}

然后我们首先只要在App的build.grade文件里面配置如下代码:

 implementation 'com.google.android.exoplayer:exoplayer-core:2.9.6'

因为我们只是需要实现变速播放功能,所以只需要导入核心代码包就行。
播放器具体实现代码如下:

/**
 * 兼容安卓6.0以下系统的Exoplayer
 * @author guotianhui
 */
class DifferentSpeedPlayer: IPlayerWapper {

    private var player: ExoPlayer? = null


    private constructor()

    companion object {

        private var INSTANCE: DifferentSpeedPlayer? = null

        fun getSpeedPlayerInstance(): DifferentSpeedPlayer? {
            if(INSTANCE == null){
                synchronized(DifferentSpeedPlayer::class.java){
                    if(INSTANCE == null){
                        INSTANCE = DifferentSpeedPlayer()
                    }
                }
            }
            return INSTANCE
        }
    }
    override fun initPlayer(context: Context) {
        if (player == null) {
            player = ExoPlayerFactory.newSimpleInstance(context, DefaultRenderersFactory(context),
                                                        DefaultTrackSelector(), DefaultLoadControl())
        }
    }

    override fun prepareDataSource(mediaPath: String?,sourceDuration: Long) {
        if(ObjectUtils.isNotEmpty(mediaPath)) {
            val uri = Uri.parse(mediaPath)
            val mediaSource = buildMediaSource(uri,sourceDuration)
            player?.prepare(mediaSource, false, true)
        }
    }
    private fun buildMediaSource(uri: Uri,sourceDuration: Long): MediaSource {
        val sourceFactory = DefaultHttpDataSourceFactory("exoplayer-codelab")
        val mediaSource = ExtractorMediaSource.Factory(sourceFactory)
        val createMediaSource = mediaSource.createMediaSource(uri)

        createMediaSource.onSourceInfoRefreshed(sourceDuration,true)
      return createMediaSource
    }
    override fun setPlaySpeed(speed: Float) {
        val playbackParameters = PlaybackParameters(speed)
        player?.playbackParameters = playbackParameters
    }
    override fun startPlay() {
        player?.playWhenReady = true
        Log.e(">>>>>>>>>>>>>>","    player?.duration:"+    player?.duration)
    }

    override fun pause() {
        player?.playWhenReady = false
    }
    override fun resumePlay() {

    }

    override fun stop() {
        player?.playWhenReady = false
    }

    override fun isPlaying(): Boolean {
        return if(ObjectUtils.isNotEmpty(player)) {
            player?.isPlayingAd!!
        }else{
            false
        }
    }
    override fun isResumePlaying(): Boolean {
       return false
    }


    override fun getPlayerPosition(): Long {
        return (player?.contentPosition!! /1000)
    }

    override fun seekToPlayerPosition(progress: Long) {
        player?.seekTo(progress * 1000)
    }

    override fun releasePlayer() {
        if (player != null) {
            player?.release()
            player = null
        }
    }
}

查看Api发现,播放器的时间获取返回的都是毫秒值,需要自己除以1000得到的正确的播放时间。ExoPlayer的开源官网

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值