I am trying to integrate mediaplayer api in my android app to play music files from local storage on device.
Problem -
When I launch my app for the first time, I see GPU renderer in developer option runs for few seconds and stop. It happens because the just started and started all the relevant services and processes. Which is fine because nothing else is happening in the app but as soon as I start playing music I can see GPU renderer also starts plotting which is fine, because app is doing something and using device resources to play the song. The problem arises when I pause the player, GPU render still plotting even though player is paused. I can't share my original code but I created another stand alone music app to check if the problem persists with the same music player code and yes, the problem persists.
I tested other music player app such as VLC to see GPU renderer behavior. I see GPU renderer runs once for few second and stop afterwards and VLC keep playing the video or the music which was surprising to me, why?
Also, when I pause the video or music in VLC GPU renderer runs again for few seconds and stop and remain idle until next interaction.
My app doesn't behave similarly, I can't figure out why it keep using resources even after pausing the music in the player.
I am trying to squeeze performance as much as I can because my original app is doing more stuff than just playing music.
[]
Here is my code --
private lateinit var binding:ActivityMainBinding
private var mediaPlayer: MediaPlayer?=null
private var musicList = arrayListOf<Song>()
private var musicAdapter: MusicAdapter? = null
private var currSong:Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
musicAdapter = MusicAdapter(this,musicList)
binding.musicListView.adapter = musicAdapter
binding.musicListView.layoutManager = LinearLayoutManager(this)
musicAdapter!!.setOnItemClickListener(object : OnRVItemClickListener {
override fun OnItemClick(pos: Int) {
if (pos == currSong && mediaPlayer != null) {
/* play pause same song*/
playPause()
} else {
/* start a new song from the list*/
playContentUri(musicList.get(pos).uri, musicList.get(pos).title)
playerUI(true, R.drawable.ic_pause_circle_outline_24px)
}
currSong = pos
}
})
binding.playerAudio.playpausePlayer.setOnClickListener {
playPause()
}
loadSongs()
}
private fun playerUI(state: Boolean, playerIcon: Int){
binding.playerAudio.playpausePlayer.setImageResource(playerIcon)
binding.playerAudio.songname.isSelected = state
}
private fun playPause(){
if (mediaPlayer!!.isPlaying) {
mediaPlayer!!.pause()
playerUI(false, R.drawable.ic_play_circle_outline_24px)
}else{
mediaPlayer!!.start()
playerUI(true, R.drawable.ic_pause_circle_outline_24px)
}
}
/* ----------Media player methods---------- */
fun playContentUri(uri: String, songName: String) {
mediaPlayer?.stop()
mediaPlayer?.reset()
try {
mediaPlayer = MediaPlayer().apply {
setDataSource(uri)
prepare()
binding.playerAudio.songname.text = songName
playerUI(true, R.drawable.ic_pause_circle_outline_24px)
}
mediaPlayer!!.start()
initSeekbar()
mediaPlayer!!.setOnCompletionListener {
playerUI(false, R.drawable.ic_play_circle_outline_24px)
}
} catch (e: IOException) {
mediaPlayer = null
mediaPlayer?.release()
}
}
override fun onPause() {
super.onPause()
stopSound()
playerUI(false, R.drawable.ic_play_circle_outline_24px)
}
private fun stopSound() {
if (mediaPlayer != null) {
mediaPlayer!!.stop()
mediaPlayer!!.release()
mediaPlayer = null
}
}
private fun initSeekbar(){
binding.playerAudio.seekbarPlayer.max = mediaPlayer!!.duration
val handler = Handler(Looper.myLooper()!!)
handler.postDelayed(object : Runnable {
override fun run() {
try {
playerUIValue( mediaPlayer!!.currentPosition,millisecondsToTime(mediaPlayer!!.currentPosition.toLong()))
handler.postDelayed(this, 1000)
} catch (e: Exception) {
playerUI(false, R.drawable.ic_play_circle_outline_24px)
playerUIValue(0,"00:00")
handler.removeCallbacks(this)
}
}
}, 0)
}
private fun playerUIValue(seekProgress:Int, seektime:String){
binding.playerAudio.seekbarPlayer.progress = seekProgress
binding.playerAudio.playertime.text = seektime
}
private fun millisecondsToTime(milliseconds: Long): String {
val minutes = milliseconds / 1000 / 60
val seconds = milliseconds / 1000 % 60
val secondsStr = seconds.toString()
val secs: String
secs = if (secondsStr.length >= 2) {
secondsStr.substring(0, 2)
} else {
"0$secondsStr"
}
return "$minutes:$secs"
}
/*---------------------------*/
private fun loadSongs() {
CoroutineScope(Dispatchers.IO).launch {
getSongs()
}
}
private suspend fun refreshData() {
withContext(Dispatchers.Main){
runOnUiThread(Runnable {
musicAdapter!!.notifyDataSetChanged()
})
}
}
private suspend fun getSongs() {
musicList.clear()
val songCursor: Cursor? = contentResolver.query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
null,
MediaStore.Audio.Media.IS_MUSIC,
null,
null
)
while (songCursor != null && songCursor.moveToNext()) {
val songTitle =
songCursor.getString(songCursor.getColumnIndex(MediaStore.Audio.Media.TITLE))
val songDuration =
songCursor.getLong(songCursor.getColumnIndex(MediaStore.Audio.Media.DURATION))
val songArtist =
songCursor.getString(songCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST))
val songCover =
songCursor.getString(songCursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ID))
val songUri = songCursor.getString(songCursor.getColumnIndex(MediaStore.Audio.Media.DATA))
println("SongURL " + songUri)
val music = Song(
songCover,
songTitle,
songUri,
songArtist,
songDuration,
false
)
musicList.add(music)
}
refreshData()
}
question from:
https://stackoverflow.com/questions/65893135/android-mediaplayer-on-pause-keep-using-resources-as-gpu-renderer-in-developer 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…