Android Studio、MediaPlayer快进/快退无法正常工作



我正试图在音乐播放器应用程序中创建快进和快退按钮。目前,当我点击快进按钮时,无论当前位置在哪里,它都会搜索到歌曲中的相同位置。回放只会在0处重新启动歌曲。

在我看来,SONG_POSITION在这里总是0。请参阅前进和后退=5000ms。因此,0+seekForward始终==5000ms,无论当前位置如何,它都会将歌曲位置移动到5000ms。并且0-向后总是==-5000ms,-5000ms<持续时间,所以它在0开始歌曲。

快进:

fastForwardBtn!!.setOnClickListener {
refreshRecyclerView(false)
SONG_POSITION = getPosition(currentSong)
if (SONG_POSITION + seekForward <= mMediaPlayer!!.duration) {
mMediaPlayer!!.seekTo(SONG_POSITION + seekForward)
} else {
mMediaPlayer!!.seekTo(mMediaPlayer!!.duration)
}
}

回放:

rewindBtn!!.setOnClickListener {
refreshRecyclerView(false)
SONG_POSITION = getPosition(currentSong)
if (SONG_POSITION - seekBackward >= mMediaPlayer!!.duration) {
mMediaPlayer!!.seekTo(SONG_POSITION - seekBackward)
} else {
mMediaPlayer!!.seekTo(0)
}
}

完整的MainActivity,fwd/rwnd在handleEvents()中,大约下降了一半:

package com.duncan.repea.ui.view
import android.Manifest
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.Typeface
import android.media.MediaPlayer
import android.media.PlaybackParams
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.view.View
import android.view.WindowManager
import android.widget.SeekBar
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.duncan.repea.data.model.Song
import com.duncan.repea.data.model.SongDao
import com.duncan.repea.databinding.ModelBinding
import com.duncan.repea.ui.viewmodel.SongsViewModel
import com.duncan.repea.utilities.constants.Constants
import com.duncan.repea.utilities.constants.Constants.MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE
import com.duncan.repea.R
import info.camposha.pollux.PolluxAdapter
import kotlinx.android.synthetic.main.content_home.*
import java.util.ArrayList
class MainActivity : AppCompatActivity() {
private var hasFinished = false
private var currentSong: Song? = null
var mMediaPlayer: MediaPlayer? = null
var mHandler = Handler()
var adapter: PolluxAdapter<Song>? = null
private var sv: SongsViewModel? = null

var SONG_POSITION = 0
var seekForward = 5000
var seekBackward = 5000
var SONGS_CACHE = ArrayList<Song>()
var playbackParams = PlaybackParams()
private fun initializeViews() {
songsRV!!.layoutManager = LinearLayoutManager(this)
progressSPD.isEnabled = false
}
private fun getPosition(s: Song?): Int {
val pos = 0
for (song in SONGS_CACHE) {
if (s!!.id.equals(song.id, ignoreCase = true)) {
return SONGS_CACHE.indexOf(s)
}
}
return pos
}
private val player: MediaPlayer?
private get() {
if (mMediaPlayer == null) {
if (currentSong == null) {
currentSong = if (SONGS_CACHE.size > 0) {
SONGS_CACHE[0]
} else {
return null
}
}
mMediaPlayer = MediaPlayer.create(this, Uri.parse(currentSong!!.data))
}
return mMediaPlayer
}
private fun cleanUpMediaPlayer() {
if (mMediaPlayer != null) {
mMediaPlayer!!.release()
mMediaPlayer = null
}
}
private fun fetchAllSongs() {
sv!!.loadAllSongs(this).observe(this, Observer { requestCall: SongDao ->
val linkedHashSet = LinkedHashSet(requestCall.songs)
SONGS_CACHE.clear()
SONGS_CACHE.addAll(linkedHashSet)
SONGS_CACHE.sortWith(compareBy({ it.title }))
if (currentSong == null && SONGS_CACHE.size > 0) {
currentSong = SONGS_CACHE.get(0)
}
})
}
private fun checkPermissionsThenLoadSongs() {
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED
) {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(
this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE
)
show("Please allow external storage access")
} else {
fetchAllSongs()
}
}
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>,
grantedResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantedResults)
when (requestCode) {
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE -> {
if (grantedResults.size > 0
&& grantedResults[0] == PackageManager.PERMISSION_GRANTED
) {
fetchAllSongs()
// permission was granted, yay! Do the
// SONGS related task you need to do.
} else {
show("Please allow external storage access")
}
return
}
}
}
private fun playOrPause(song: Song) {
currentSong = song
if (player == null) {
show("Please add songs")
return
}
hasFinished = false
try {
songsRV.smoothScrollToPosition(getPosition(song))
} catch (e: Exception) {
}
if (player!!.isPlaying) {
sv!!.pause(player, this, song).observe(this, Observer { requestCall: SongDao ->
if (requestCall.status == Constants.STOPPED) {
progressSPD.isEnabled = false
song.isPlaying = false
refreshRecyclerView(song.isPlaying)
playBtn!!.setImageResource(R.drawable.ic_play)
waveLineView.stopAnim()
}
})
} else {
sv!!.play(player, this, song).observe(this, Observer { requestCall: SongDao ->
if (requestCall.status == Constants.PLAYING) {
progressSPD.isEnabled = true
song.isPlaying = true
SONG_POSITION = getPosition(song)
refreshRecyclerView(song.isPlaying)
playBtn!!.setImageResource(R.drawable.ic_pause)
waveLineView.startAnim()
updateSongProgress()
}
})
}
}
private fun handleEvents() {
playBtn!!.setOnClickListener {
if (currentSong != null) {
playOrPause(currentSong!!)
} else {
show("Please add songs")
}
}
nextBtn!!.setOnClickListener {
refreshRecyclerView(false)
SONG_POSITION = getPosition(currentSong) + 1
if (SONG_POSITION >= SONGS_CACHE.size) {
SONG_POSITION = 0
}
cleanUpMediaPlayer()
//keeps speedSeek at 100 when skipping
findViewById<TextView>(R.id.speedPercentage).text = "100"
progressSPD.progress = 100
val nextSong: Song = SONGS_CACHE.get(SONG_POSITION)
playOrPause(nextSong)
}
fastForwardBtn!!.setOnClickListener {
refreshRecyclerView(false)
SONG_POSITION = getPosition(currentSong)
if (SONG_POSITION + seekForward <= mMediaPlayer!!.duration) {
mMediaPlayer!!.seekTo(SONG_POSITION + seekForward)
} else {
mMediaPlayer!!.seekTo(mMediaPlayer!!.duration)
}
}
prevBtn!!.setOnClickListener {
refreshRecyclerView(false)
SONG_POSITION--
if (SONG_POSITION < 0) {
if (SONGS_CACHE.size > 0) {
SONG_POSITION = SONGS_CACHE.size - 1
} else {
SONG_POSITION = 0
}
}
//keeps speedSeek at 100 when skipping
findViewById<TextView>(R.id.speedPercentage).text = "100"
progressSPD.progress = 100
val prevSong: Song = SONGS_CACHE[SONG_POSITION]
cleanUpMediaPlayer()
playOrPause(prevSong)
}
rewindBtn!!.setOnClickListener {
refreshRecyclerView(false)
SONG_POSITION = getPosition(currentSong)
if (SONG_POSITION - seekBackward >= mMediaPlayer!!.duration) {
mMediaPlayer!!.seekTo(SONG_POSITION - seekBackward)
} else {
mMediaPlayer!!.seekTo(0)
}
}
progressSB!!.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) {
if (player == null) {
show("Please add songs")
return
}
mMediaPlayer!!.seekTo(
(sv!!.getTimeFromProgress(
seekBar.progress,
player!!.duration
))
)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onStopTrackingTouch(seekBar: SeekBar) {}
})
progressSPD!!.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) {
var speedPercentage = findViewById<TextView>(R.id.speedPercentage)
var progString = progress.toString()
speedPercentage.text = progString + "%"
var speed = (progress.toFloat()) / 100
mMediaPlayer!!.playbackParams = mMediaPlayer!!.playbackParams!!.setSpeed(speed)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onStopTrackingTouch(seekBar: SeekBar) {}
})
}

private fun refreshRecyclerView(playing: Boolean) {
if (currentSong != null && SONGS_CACHE.size > 0) {
currentSong!!.isPlaying = playing
val s = SONGS_CACHE.find { it.id == currentSong!!.id }
if (s != null) {
SONGS_CACHE[getPosition(s)] = currentSong!!
}
adapter!!.notifyDataSetChanged()
currentSongTV.text = currentSong!!.title
currentSongTV.marqueeRepeatLimit = -1
} else {
currentSongTV.text = "Repea"
}
}

//toast
private fun show(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
private fun setupRecycler(songs: ArrayList<Song>) {
adapter =
PolluxAdapter.with<Song, ModelBinding>(R.layout.model) { adapterPosition, song, mb ->
//val color = mMaterialColors[Random().nextInt(mMaterialColors.size)]
//binding.root.setBackgroundColor(color)
mb.titleTV.text = song.title
if (song.isPlaying && !hasFinished) {
mb.playBtn.setImageResource(R.drawable.ic_pause)
mb.titleTV.setTextColor(Color.rgb(203, 167, 255))
mb.titleTV.setTypeface(null, Typeface.BOLD_ITALIC)
} else {
mb.playBtn.setImageResource(R.drawable.ic_play)
mb.titleTV.setTextColor(Color.GRAY)
mb.titleTV.setTypeface(null, Typeface.NORMAL)
if (hasFinished) {
mb.playBtn.setImageResource(R.drawable.ic_play)
mb.titleTV.setTextColor(Color.GRAY)
mb.titleTV.setTypeface(null, Typeface.NORMAL)
} else {
if (currentSong != null && currentSong!!.id === song.id) {
mb.playBtn.setImageResource(R.drawable.ic_play)
mb.titleTV.setTextColor(Color.rgb(203, 167, 255))
mb.titleTV.setTypeface(null, Typeface.NORMAL)
}
}
}
mb.playBtn.setOnClickListener { view: View? ->
if (!song.isPlaying) {
if (SONG_POSITION != getPosition(song)) {
if (mMediaPlayer != null) {
mMediaPlayer!!.release()
mMediaPlayer = null
}
}
SONG_POSITION = getPosition(song)
if (currentSong != null) {
currentSong!!.isPlaying = false
adapter!!.notifyDataSetChanged()
}
currentSong = SONGS_CACHE.get(SONG_POSITION)
playOrPause(song)
show("Now Playing: " + song.title)
mb.playBtn.setImageResource(android.R.drawable.ic_media_pause)
mb.titleTV.setTextColor(Color.GREEN)
mb.titleTV.setTypeface(null, Typeface.ITALIC)
} else {
if (SONG_POSITION != getPosition(song)) {
if (mMediaPlayer != null) {
mMediaPlayer!!.release()
mMediaPlayer = null
}
}
SONG_POSITION = getPosition(song)
show("Stopped: " + song.title)
playOrPause(song)
mb.playBtn.setImageResource(android.R.drawable.ic_media_play)
mb.titleTV.setTextColor(Color.RED)
mb.titleTV.setTypeface(null, Typeface.ITALIC)
//adapter!!.notifyDataSetChanged()
}
}
}
songsRV.layoutManager = GridLayoutManager(this@MainActivity, 2)
adapter!!.addAll(songs)
songsRV!!.adapter = adapter
}

private fun updateSongProgress() {
mHandler.postDelayed(runnable, 1000)
}
private var runnable: Runnable = object : Runnable {
override fun run() {
if (!hasFinished) {
if (mMediaPlayer == null) {
return
}
val currentDuration = mMediaPlayer!!.currentPosition
val totalDuration = mMediaPlayer!!.duration
currentPosTV!!.text = sv!!.convertToTimerMode(currentDuration.toString())
progressSB!!.progress = sv!!.getSongProgress(totalDuration, currentDuration)
totalDurationTV!!.text = sv!!.convertToTimerMode(totalDuration.toString())
if (progressSB!!.progress >= 99 && !mMediaPlayer!!.isPlaying) {
playBtn!!.setImageResource(android.R.drawable.ic_media_play)
hasFinished = true
adapter!!.notifyDataSetChanged()
//                    show("Finished");
//Click Next to play next song
nextBtn!!.performClick()
} else {
hasFinished = false
}
mHandler.postDelayed(this, 1000)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//keeps screen from locking
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
sv = ViewModelProvider(this).get(SongsViewModel::class.java)
initializeViews()
handleEvents()
}
override fun onResume() {
super.onResume()
if (SONGS_CACHE.isEmpty()) {
checkPermissionsThenLoadSongs()
setupRecycler(SONGS_CACHE)
}
}
override fun onPause() {
super.onPause()
if (currentSong != null && currentSong!!.isPlaying) {
currentSong!!.isPlaying = false
playOrPause(currentSong!!)
}
cleanUpMediaPlayer()
}
override fun onStop() {
super.onStop()
SONGS_CACHE.clear()
cleanUpMediaPlayer()
}
override fun onDestroy() {
super.onDestroy()
waveLineView.release()
}
}

如有任何帮助,我们将不胜感激。

我不知道为什么不使用currentPosition()方法来获取当前播放歌曲的位置,而使用getPosition()尝试使用此。。

SONG_POSITION = mMediaPlayer!!.currentPosition

看看这里了解更多。。https://developer.android.com/reference/android/media/MediaPlayer#getCurrentPosition()

相关内容

  • 没有找到相关文章

最新更新