如何在Android MediaPlayer中进行内存管理?

最有趣的

我使用的是Android 4.4.4版本。我的应用程序使用MediaPlayer

我在设备中获取了媒体列表,每个媒体都放入了mutableListOf中Next在媒体播放的for循环中。

但是,一段时间后就死了。

10-18 12:58:29.599 1466-1466/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.hanmedia.android, PID: 1466
    java.lang.OutOfMemoryError
        at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
        at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:594)
        at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:429)
        at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:840)
        at android.content.res.Resources.loadDrawable(Resources.java:2110)
        at android.content.res.Resources.getDrawable(Resources.java:700)
        at android.graphics.drawable.AnimationDrawable.inflate(AnimationDrawable.java:282)
        at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:937)
        at android.graphics.drawable.Drawable.createFromXml(Drawable.java:877)
        at android.content.res.Resources.loadDrawable(Resources.java:2092)
        at android.content.res.TypedArray.getDrawable(TypedArray.java:602)
        at android.widget.ProgressBar.<init>(ProgressBar.java:294)
        at android.widget.ProgressBar.<init>(ProgressBar.java:246)
        at android.widget.AbsSeekBar.<init>(AbsSeekBar.java:69)
        at android.widget.SeekBar.<init>(SeekBar.java:83)
        at androidx.appcompat.widget.AppCompatSeekBar.<init>(AppCompatSeekBar.java:50)
        at androidx.appcompat.widget.AppCompatSeekBar.<init>(AppCompatSeekBar.java:45)
        at androidx.appcompat.app.AppCompatViewInflater.createSeekBar(AppCompatViewInflater.java:256)
        at androidx.appcompat.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:163)
        at androidx.appcompat.app.AppCompatDelegateImpl.createView(AppCompatDelegateImpl.java:1551)
        at androidx.appcompat.app.AppCompatDelegateImpl.onCreateView(AppCompatDelegateImpl.java:1602)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:684)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:758)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
        at android.widget.MediaController.makeControllerView(MediaController.java:244)
        at android.widget.MediaController.setAnchorView(MediaController.java:232)
        at android.widget.VideoView.attachMediaController(VideoView.java:380)
        at android.widget.VideoView.openVideo(VideoView.java:349)
        at android.widget.VideoView.access$2100(VideoView.java:71)
        at android.widget.VideoView$7.surfaceCreated(VideoView.java:607)
        at android.view.SurfaceView.updateWindow(SurfaceView.java:572)
        at android.view.SurfaceView.access$000(SurfaceView.java:86)
        at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:175)
        at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:847)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1876)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1001)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5680)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
        at android.view.Choreographer.doCallbacks(Choreographer.java:574)
        at android.view.Choreographer.doFrame(Choreographer.java:544)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5001)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:815)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:631)
        at dalvik.system.NativeStart.main(Native Method)

我猜MediaPlayer使用很多内存。并且Android不能在播放每种媒体时清除缓冲区。如何清除此代码中的缓冲区?

// class NormalFragment : Fragment() Code

// Type is mutableListOf<MediaItemPlayer>
val playerList = device.mediaLinks
                .filter { link ->
                    link.mediaLinkType == type &&
                            nowKr.time < link.expire
                }
                .sortedBy {
                    it.position
                }
                .let { links ->
                    val playerList = mutableListOf<MediaItemPlayer>()
                    links.forEachIndexed { index, _ ->
                        links[index].waitTime = device.pictureSlideTime.toLong()
                        links[index].sound = sound
                        it.runOnUiThread {
                            val player = MediaItemPlayer(it, links[index])
                            view.addView(player.view)
                            playerList.add(player)
                        }
                    }
                    playerList
                }.toList()

// And then loop each video
playerList.forEachIndexed { index, mediaItemPlayer ->

                    val listener = if (index != (playerList.count() - 1)) {
                        object : PlayerEventListener {
                            override fun next() {
                                it.runOnUiThread {
                                    logger.i("[${type}] $index")
                                    val playIndex = (index + 1) % playerList.size
                                    val prepareIndex = (index + 2) % playerList.size

                                    playerList[playIndex].run {
                                        setVolume(getSound(type))
                                        start()
                                    }

                                    playerList[prepareIndex].run{
                                        prepare()
                                    }

                                }
                            }
// MediaItemPlayer class
// class MediaItemPlayer(private val context : Context, private val mediaLink : DeviceWithMediaLink)

private var repeatCount = 0
    private var ready : Boolean = false
    private var startFlag = false
    private var startIgnoreFlag = false
    private var prepareFlag = false

    private lateinit var player : MediaPlayer
    private lateinit var nextListener: PlayerEventListener

fun start(){
        if(ready) {
            logger.i("ready [${mediaLink.mediaLinkType}]${mediaLink.media.originalName}")
            when (mediaLink.media.mediaType) {
                MediaType.TEXT, MediaType.PICTURE -> {
                    val delayTime = mediaLink.waitTime * (mediaLink.repeatCount + 1)
                    logger.i("[${mediaLink.mediaLinkType}] delay $delayTime")
                    view.postDelayed({
                        goNext()
                    }, delayTime)
                }
                MediaType.VIDEO -> {
                    logger.i("[${mediaLink.mediaLinkType}] Video start")
                    if(prepareFlag){
                        player.start()
                    }else{
                        view.postDelayed({
                            if(!prepareFlag) {
                                logger.e("[${mediaLink.mediaLinkType}] not prepare")
                                startIgnoreFlag = true
                                logger.e("[${mediaLink.mediaLinkType}] start ignore and play next video")
                                nextListener.next()
                            }
                        }, 2000)
                        startFlag = true
                    }
                }
            }
            context.runOnUiThread {
                view.visibility = View.VISIBLE
            }
        }else{
            logger.i("not ready [${mediaLink.mediaLinkType}]${mediaLink.media.originalName}")
            goNext()
        }
    }

    private fun goNext(){
        nextListener.next()
        context.runOnUiThread {
            view.visibility = View.GONE
        }
    }
阿伦·辛格

我认为问题是您正在创建MediaPlayer的多个实例,这导致OutOfMemoryError异常。另外,完成播放后,请不要忘记释放MediaPlayer实例。根据MediaPlayer文档:

还建议一旦不再使用MediaPlayer对象,则立即调用release(),以便可以立即释放与MediaPlayer对象关联的内部播放器引擎使用的资源。资源可能包括单件资源,例如硬件加速组件,而未能调用release()可能导致MediaPlayer对象的后续实例退回到软件实现或完全失败。一旦MediaPlayer对象处于End状态,就不能再使用它了,也无法将其恢复为其他状态。

使用后在MediaItemPlayer中添加方法以释放MediaPlayer:

    private fun releaseMediaPlayer(){
       if (player.isPlaying()) {
           player.stop();
       }
       player.reset();
       player.release();
       player = null;
}

播放完媒体文件后,从NormalFragment调用releaseMediaPlayer。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章