Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
219 views
in Technique[技术] by (71.8m points)

kotlin - Android mediaplayer on pause keep using resources, as GPU Renderer in Developer setting shown

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.

  1. 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?

  2. 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.

  3. 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.

[Video]

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...