package com.ydl.media.audio import android.content.Context import android.content.IntentFilter import android.media.AudioManager import android.os.Handler import android.os.Looper import com.tencent.bugly.Bugly.applicationContext import com.ydl.media.audio.enums.PlayModeEnum import com.ydl.media.audio.manager.AudioFocusManager import com.ydl.media.audio.manager.MediaSessionManager import com.ydl.media.audio.manager.NotifyManager import com.ydl.media.audio.model.Music import com.ydl.media.audio.receiver.NoisyAudioStreamReceiver import com.ydl.media.audio.utils.PlayProgressUtil import com.ydl.ydlcommon.utils.LogUtil import com.yidianling.common.tools.ToastUtil import tv.danmaku.ijk.media.player.IMediaPlayer import tv.danmaku.ijk.media.player.IjkMediaPlayer import java.io.IOException import java.util.* import kotlin.collections.ArrayList /** * Created by haorui on 2019-10-27 . * Des: */ class AudioPlayer private constructor() { private var context: Context? = null private var audioFocusManager: AudioFocusManager? = null var mediaPlayer: IMediaPlayer? = null private var handler: Handler? = null private var noisyReceiver: NoisyAudioStreamReceiver? = null private var noisyFilter: IntentFilter? = null private var musicList: MutableList<Music> = ArrayList() private val listeners = ArrayList<OnPlayerEventListener>() private var state = STATE_IDLE private val mPublishRunnable = object : Runnable { override fun run() { if (isPlaying) { val current = (mediaPlayer!!.currentPosition * 1.0).toFloat() val du = mediaPlayer!!.duration.toFloat() var percent = (current * 100 / du).toInt() //保存进度 if (autoSaveProgress) { PlayProgressUtil.saveProgress( context, playMusic!!.path, (if (percent == 99 || percent == 100) 0 else current.toInt()) ) } for (listener in listeners) { listener.onPublish(percent, current.toLong()) } } handler!!.postDelayed(this, TIME_UPDATE) } } val audioSessionId: Int get() = if (mediaPlayer != null)mediaPlayer!!.audioSessionId else 0 val audioPosition: Long get() = if (isPlaying || isPausing) { mediaPlayer!!.currentPosition.toLong() } else { 0 } val playMusic: Music? get() = if (musicList.isEmpty()) { null } else musicList[playPosition] val isPlaying: Boolean get() = state == STATE_PLAYING val isPausing: Boolean get() = state == STATE_PAUSE val isPreparing: Boolean get() = state == STATE_PREPARING val isIdle: Boolean get() = state == STATE_IDLE var playPosition: Int = 0 get() { if (field < 0 || field >= musicList.size) { field = 0 } return field } /** * 设置播放模式 * 默认为列表循环 */ var playMode = PlayModeEnum.LIST_LOOP /** * 是否自动保存播放进度 */ var autoSaveProgress = false /** * 是否显示通知栏 */ var isShowNotify = false private object SingletonHolder { val instance = AudioPlayer() } /** * 初始化播放器 */ fun init(context: Context) { this.context = context.applicationContext audioFocusManager = AudioFocusManager(context) mediaPlayer = IjkMediaPlayer() try { (mediaPlayer as IjkMediaPlayer).setOption( IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 1 ) } catch (e: Exception) { LogUtil.e(e.message) } mediaPlayer!!.setOnPreparedListener { mp -> if (isPreparing) { if (autoSaveProgress) { //自动播放 var time = PlayProgressUtil.getProgress(context, playMusic!!.path) if (time > 0) { startPlayer() seekTo(position = time.toLong()) } else { startPlayer() } } else { startPlayer() } } for (listener in listeners) { listener.onPrepared(mediaPlayer!!.duration) } } mediaPlayer!!.setOnBufferingUpdateListener { mp, percent -> for (listener in listeners) { listener.onBufferingUpdate(percent) } } mediaPlayer!!.setOnCompletionListener { if (autoSaveProgress) { PlayProgressUtil.saveProgress(applicationContext, playMusic!!.path, 0) } for (listener in listeners) { listener.onComplete() } if (playMode == PlayModeEnum.SINGLE) { stopPlayer() playMode = PlayModeEnum.LIST_LOOP return@setOnCompletionListener } next() } handler = Handler(Looper.getMainLooper()) noisyReceiver = NoisyAudioStreamReceiver() noisyFilter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY) } /** * 添加播放监听 */ fun addOnPlayEventListener(listener: OnPlayerEventListener) { if (!listeners.contains(listener)) { listeners.add(listener) } } /** * 移除播放监听 */ fun removeOnPlayEventListener(listener: OnPlayerEventListener) { listeners.remove(listener) } /** * 添加播放列表 */ fun addPlayList(music: ArrayList<Music>) { if (music.isEmpty()) { return } musicList.clear() musicList.addAll(music) playMode = PlayModeEnum.LIST_LOOP autoSaveProgress = false } /** * 单曲模式播放音乐 */ fun singlePlay(music: Music, isAutoSaveProgress: Boolean = false) { musicList.clear() musicList.add(music) playMode = PlayModeEnum.SINGLE autoSaveProgress = isAutoSaveProgress play(0) } /** * 单曲循环模式播放音乐 */ fun singleCirclePlay(music: Music) { musicList.clear() musicList.add(music) playMode = PlayModeEnum.SINGLE_LOOP autoSaveProgress = false play(0) } /** * 添加后自动播放 */ fun addAndPlay(music: Music) { var position = musicList.indexOf(music) if (position < 0) { musicList.add(music) position = musicList.size - 1 } play(position) } /** * 播放第一首 */ fun play() { play(0) } /** * 加载指定索引的音乐 */ fun play(position: Int) { var position = position if (musicList.isEmpty()) { return } if (position < 0) { position = musicList.size - 1 } else if (position >= musicList.size) { position = 0 } playPosition = position val music = playMusic try { mediaPlayer!!.reset() mediaPlayer!!.dataSource = music!!.path mediaPlayer!!.prepareAsync() state = STATE_PREPARING for (listener in listeners) { listener.onChange(music) } if (isShowNotify) { NotifyManager.get().showPlay(music) MediaSessionManager.get().updateMetaData(music) MediaSessionManager.get().updatePlaybackState() } } catch (e: IOException) { e.printStackTrace() ToastUtil.toastShort("当前歌曲无法播放") } } /** * 从列表里移除播放音乐 */ fun delete(position: Int) { val music = musicList!!.removeAt(position) if (playPosition > position) { playPosition -= 1 } else if (playPosition == position) { if (isPlaying || isPreparing) { playPosition -= 1 next() } else { stopPlayer() for (listener in listeners) { listener.onChange(playMusic!!) } } } } /** * 暂停或者播放音乐 */ fun playPause() { if (isPreparing) { stopPlayer() } else if (isPlaying) { pausePlayer() } else if (isPausing) { startPlayer() } else { play(playPosition) } } /** *开始播放 */ fun startPlayer() { if (!isPreparing && !isPausing) { return } if (audioFocusManager!!.requestAudioFocus()) { mediaPlayer!!.start() state = STATE_PLAYING handler!!.post(mPublishRunnable) if (isShowNotify) { NotifyManager.get().showPlay(playMusic) MediaSessionManager.get().updatePlaybackState() } context!!.registerReceiver(noisyReceiver, noisyFilter) for (listener in listeners) { listener.onPlayerStart() } } } /** * 暂停播放器 */ @JvmOverloads fun pausePlayer(abandonAudioFocus: Boolean = true) { if (!isPlaying) { return } mediaPlayer!!.pause() state = STATE_PAUSE handler!!.removeCallbacks(mPublishRunnable) if (isShowNotify) { NotifyManager.get().showPause(playMusic) MediaSessionManager.get().updatePlaybackState() } context!!.unregisterReceiver(noisyReceiver) if (abandonAudioFocus) { audioFocusManager!!.abandonAudioFocus() } for (listener in listeners) { listener.onPlayerPause() } } /** * 停止播放器 */ fun stopPlayer() { if (isIdle) { return } pausePlayer() musicList.clear() mediaPlayer!!.reset() state = STATE_IDLE } /** * 下一首 */ operator fun next() { if (musicList.isEmpty()) { return } var playPosition = when (playMode) { PlayModeEnum.SHUFFLE -> Random().nextInt(musicList.size) PlayModeEnum.SINGLE_LOOP -> playPosition PlayModeEnum.LIST_LOOP -> playPosition + 1 else -> playPosition + 1 } play(playPosition); } /** * 上一首 */ fun prev() { if (musicList.isEmpty()) { return } when (playMode) { PlayModeEnum.SHUFFLE -> play(Random().nextInt(musicList.size)) PlayModeEnum.SINGLE_LOOP -> play(playPosition) PlayModeEnum.LIST_LOOP -> play(playPosition - 1) else -> play(playPosition - 1) } } /** * 跳转到指定的时间位置 * @param percent 百分比 * @param position 时间点 */ fun seekTo(percent: Int = -1, position: Long = -1) { if (isPlaying || isPausing) { var currentPosition = 0L var currentPercent = 0 if (position != (-1).toLong()) { val current = (currentPosition * 1.0).toFloat() val du = mediaPlayer!!.duration.toFloat() currentPercent = (current * 100 / du).toInt() currentPosition = position } else { currentPosition = percent * mediaPlayer!!.duration / 100 } mediaPlayer!!.seekTo(currentPosition) MediaSessionManager.get().updatePlaybackState() if (autoSaveProgress) { PlayProgressUtil.saveProgress( context, musicList[playPosition].coverPath, currentPosition.toInt() ) } for (listener in listeners) { listener.onPublish(currentPercent, currentPosition) } } } /** * 获取播放列表 */ fun getMusicList(): List<Music>? { return musicList } /** * 获取音乐时长 */ fun getDuration(): Long { return mediaPlayer?.duration ?: 0 } companion object { private val STATE_IDLE = 0 private val STATE_PREPARING = 1 private val STATE_PLAYING = 2 private val STATE_PAUSE = 3 private val TIME_UPDATE = 300L fun get(): AudioPlayer { return SingletonHolder.instance } } }