You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
FFmpegAndroid/app/src/main/java/com/frank/ffmpeg/activity/AudioPlayActivity.kt

199 lines
7.2 KiB

package com.frank.ffmpeg.activity
import android.annotation.SuppressLint
import android.media.MediaPlayer
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.text.TextUtils
import android.util.Log
import android.widget.ImageView
import android.widget.SeekBar
import android.widget.TextView
import com.frank.ffmpeg.R
import com.frank.ffmpeg.handler.FFmpegHandler
import com.frank.ffmpeg.handler.FFmpegHandler.MSG_FINISH
import com.frank.ffmpeg.listener.OnLrcListener
import com.frank.ffmpeg.model.AudioBean
import com.frank.ffmpeg.model.MediaBean
import com.frank.ffmpeg.util.FFmpegUtil
import com.frank.ffmpeg.util.TimeUtil
import com.frank.ffmpeg.model.LrcLine
import com.frank.ffmpeg.tool.LrcLineTool
import com.frank.ffmpeg.tool.LrcParser
import com.frank.ffmpeg.util.ThreadPoolUtil
import com.frank.ffmpeg.view.LrcView
import java.io.File
class AudioPlayActivity : AppCompatActivity() {
companion object {
private val TAG = AudioPlayActivity::class.java.simpleName
private const val MSG_TIME = 123
private const val MSG_DURATION = 234
}
private var path: String? = null
private var txtTitle: TextView? = null
private var txtArtist: TextView? = null
private var txtTime: TextView? = null
private var txtDuration: TextView? = null
private var audioBar: SeekBar? = null
private var lrcView: LrcView? = null
private lateinit var audioPlayer:MediaPlayer
private val mHandler: Handler = @SuppressLint("HandlerLeak")
object : Handler() {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
when (msg?.what) {
MSG_TIME -> {
audioBar?.progress = audioPlayer.currentPosition
txtTime?.text = TimeUtil.getVideoTime(audioPlayer.currentPosition.toLong())
sendEmptyMessageDelayed(MSG_TIME, 1000)
lrcView?.seekToTime(audioPlayer.currentPosition.toLong())
}
MSG_DURATION -> {
val duration = msg.obj as Int
txtDuration?.text = TimeUtil.getVideoTime(duration.toLong())
audioBar?.max = duration
}
MSG_FINISH -> {
if (msg.obj == null) return
val result = msg.obj as MediaBean
val audioBean = result.audioBean
txtTitle?.text = audioBean?.title
txtArtist?.text = audioBean?.artist
val lyrics = audioBean?.lyrics
if (lyrics != null) {
val lrcList = arrayListOf<LrcLine>()
for (i in lyrics.indices) {
Log.e(TAG, "lyrics=_=" + lyrics[i])
val line = LrcLineTool.getLrcLine(lyrics[i])
if (line != null) lrcList.addAll(line)
}
LrcLineTool.sortLyrics(lrcList)
lrcView?.setLrc(lrcList)
} else if (audioBean?.lrcLineList != null) {
lrcView?.setLrc(audioBean.lrcLineList!!)
}
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_audio_play)
initView()
initAudioPlayer()
initLrc()
}
private fun initView() {
txtTitle = findViewById(R.id.txt_title)
txtArtist = findViewById(R.id.txt_artist)
txtTime = findViewById(R.id.txt_time)
txtDuration = findViewById(R.id.txt_duration)
lrcView = findViewById(R.id.list_lyrics)
val btnPlay: ImageView = findViewById(R.id.img_play)
btnPlay.setOnClickListener {
if (isPlaying()) {
audioPlayer.pause()
btnPlay.setImageResource(R.drawable.ic_play)
} else {
audioPlayer.start()
btnPlay.setImageResource(R.drawable.ic_pause)
}
}
audioBar = findViewById(R.id.audio_bar)
audioBar?.setOnSeekBarChangeListener(object :SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
if (!fromUser) return
audioBar?.progress = progress
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
val progress = audioBar?.progress ?: 0
audioPlayer.seekTo(progress)
lrcView?.seekToTime(progress.toLong())
}
})
lrcView?.setListener(object :OnLrcListener {
override fun onLrcSeek(position: Int, lrcLine: LrcLine) {
audioPlayer.seekTo(lrcLine.startTime.toInt())
Log.e(TAG, "lrc position=$position--time=${lrcLine.startTime}")
}
})
}
private fun initAudioPlayer() {
path = intent.data?.path
Log.e(TAG, "path=$path")
if (TextUtils.isEmpty(path)) return
audioPlayer = MediaPlayer()
audioPlayer.setDataSource(path)
audioPlayer.prepareAsync()
audioPlayer.setOnPreparedListener {
Log.e(TAG, "onPrepared...")
audioPlayer.start()
val duration = audioPlayer.duration
mHandler.obtainMessage(MSG_TIME).sendToTarget()
mHandler.obtainMessage(MSG_DURATION, duration).sendToTarget()
}
}
private fun initLrc() {
if (path.isNullOrEmpty()) return
var lrcPath: String? = null
if (path!!.contains(".")) {
lrcPath = path!!.substring(0, path!!.lastIndexOf(".")) + ".lrc"
Log.e(TAG, "lrcPath=$lrcPath")
}
if (!lrcPath.isNullOrEmpty() && File(lrcPath).exists()) {
// should parsing in work thread
ThreadPoolUtil.executeSingleThreadPool(Runnable {
val lrcParser = LrcParser()
val lrcInfo = lrcParser.readLrc(lrcPath)
Log.e(TAG, "title=${lrcInfo?.title},album=${lrcInfo?.album},artist=${lrcInfo?.artist}")
val mediaBean = MediaBean()
val audioBean = AudioBean()
audioBean.title = lrcInfo?.title
audioBean.album = lrcInfo?.album
audioBean.artist = lrcInfo?.artist
audioBean.lrcLineList = lrcInfo?.lrcLineList
mediaBean.audioBean = audioBean
mHandler.obtainMessage(MSG_FINISH, mediaBean).sendToTarget()
})
} else {
val ffmpegHandler = FFmpegHandler(mHandler)
val commandLine = FFmpegUtil.probeFormat(path)
ffmpegHandler.executeFFprobeCmd(commandLine)
}
}
private fun isPlaying() :Boolean {
return audioPlayer.isPlaying
}
override fun onStop() {
super.onStop()
try {
mHandler.removeCallbacksAndMessages(null)
audioPlayer.stop()
audioPlayer.release()
} catch (e: Exception) {
Log.e(TAG, "release player err=$e")
}
}
}