Android: 播放视频和图片时出现OutOfMemoryError

Android: OutOfMemoryError when playing videos and images

我正在编写一个 Android 应用程序,它可以播放图像(显示 10 秒)和视频。为此,我使用了带有 VideoView 和 ImageView 的布局。布局 XML 下面:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:background="#0099cc"
tools:context="nahtlos.de.lackmannvideo.VideoActivity">

<VideoView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:keepScreenOn="true"
    android:id="@+id/mediaView" />

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:keepScreenOn="true"
    android:id="@+id/imageView" />

</RelativeLayout>

但是,我在设备上打开一个文件夹并循环播放媒体。因此 mediaList 包含目录文件的路径。我为此任务使用了一个单独的线程。请看下面的代码:

public class MediaControlThread extends Thread  {
  public static List<String> mediaList = new ArrayList<String>();
  private VideoView mediaView;
  private ImageView imageView;
  MyPhotoActivity activity;
  private int currentVideo = 0;

  public MediaControlThread(MyPhotoActivity activity, VideoView mediaView, ImageView imageView) {
    this.mediaView = mediaView;
    this.imageView = imageView;
    this.activity = activity;
}

  @Override
  public void run() {
    try {
        while(mediaList.size() == 0) {
           Thread.sleep(1000);
        }
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    playMedia(mediaList.get(0));
  }

  private void completePlaying() {
    currentVideo++;
    if (currentVideo > mediaList.size() - 1) {
        currentVideo = 0;
    }
    final MediaControlThread me = this;
    activity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            imageView.setVisibility(View.INVISIBLE);
            mediaView.setVisibility(View.INVISIBLE);
        }
    });
    Thread waitThread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    waitThread.start();
    try {
        waitThread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    playMedia(mediaList.get(currentVideo));
  }

  private void playMedia(final String mediaPath) {
    try {
        if (checkFileForImage(mediaPath)) {
            final MediaControlThread me = this;
            final Bitmap bm = BitmapFactory.decodeFile(mediaPath);
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    me.imageView.setVisibility(View.VISIBLE);
                    me.imageView.setImageBitmap(bm);
                }
            });
            Thread waitThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(AppSettings.secondsToShowPicture * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            waitThread.start();
            waitThread.join();
            if(bm != null) {
                bm.recycle();
            }
            completePlaying();
        } else {
            final MediaControlThread me = this;
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    me.mediaView.setVisibility(View.VISIBLE);
                    me.mediaView.setVideoPath(mediaPath);
                    me.mediaView.start();
                }
            });
            if(!mediaView.isPlaying()) {
                while (!mediaView.isPlaying()) {
                    Thread.sleep(100);
                }
            }
            while(mediaView.isPlaying()) {
                Thread.sleep(100);
            }
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    me.mediaView.stopPlayback();
                    me.mediaView.suspend();
                    me.mediaView.destroyDrawingCache();
                }
            });
            completePlaying();
        }
      } catch (IllegalArgumentException e) {
        Log.d("MyMediaPlayerControl", e.getMessage());
      } catch (IllegalStateException e) {
        Log.d("MyMediaPlayerControl", e.getMessage());
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
  }

  private boolean checkFileForImage(String fileName) {
    String file = fileName.toLowerCase();
    return file.endsWith(".jpg") ||
            file.endsWith(".img") ||
            file.endsWith(".bmp") ||
            file.endsWith(".jpeg") ||
            file.endsWith(".ico") ||
            file.endsWith(".tif");
  }
}

一开始一切正常,但大约 5 分钟后我收到 OutOfMemoryException:

    10-23 14:20:46.417 379-379/xxx E/IMGSRV: :0: PVRDRMOpen: TP3, ret = 50
10-23 14:20:46.427 379-379/xxx E/IMGSRV: :0: PVRDRMOpen: TP3, ret = 53
10-23 14:20:46.427 379-379/xxx E/IMGSRV: :0: PVRDRMOpen: TP3, ret = 54
10-23 14:20:46.427 379-379/xxx E/IMGSRV: :0: PVRDRMOpen: TP3, ret = 54
10-23 14:20:46.437 379-379/xxx E/IMGSRV: :0: PVRDRMOpen: TP3, ret = 54
10-23 14:20:46.447 379-379/xxx E/IMGSRV: :0: PVRDRMOpen: TP3, ret = 56
10-23 14:24:23.687 379-716/xxx E/dalvikvm-heap: Out of memory on a 36000016-byte allocation.
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime: FATAL EXCEPTION: Thread-532
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime: Process: xxx, PID: 379
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime: java.lang.OutOfMemoryError
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:613)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:589)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:369)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:395)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:87)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.completePlaying(MediaControlThread.java:80)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:     at xxx.MediaControlThread.playMedia(MediaControlThread.java:137)
10-23 14:24:23.787 379-716/xxx E/AndroidRuntime:    at xxx.MediaControlThread.comple

谁能给个线索???几天来我一直在努力实现这个图像和视频查看器!谢谢!

找到问题了!使用 SurfaceView 无法同时查看视频和图像。另请参阅此 post:

That is, unfortunately, the expected behavior. Due to a quirk in Android, once you've drawn on a Surface with Canvas you can't do anything else. [...]