我使用的是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] 删除。
我来说两句