1

I'm writing an Android app, which plays both images (shown for 10 sec) and videos. I used a layout with a VideoView and an ImageView for that. Layout XML below:

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

However, I open a folder on device and play the media in a loop. Therefore the mediaList contains the paths to files of the directory. I use an separate thread for this task. See the code below:

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");
  }
}

Everything works fine for the beginning, but after about 5 minutes I get an 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

Can anybody give a clue??? I'm trying to implement this image AND video viewer for days! Thank you!

D. Müller
  • 3,336
  • 4
  • 36
  • 84
  • 1
    If the issue is due the large size of the data input, then you can used android:largeheap="true" in manifest file under Application tag. Check if this helps you. – Ravneet Singh Oct 23 '15 at 12:38
  • I'll have a try. I have about 50 images (25 of them 4000x2250px and 25 of them with 1600x1200px) and 25 videos (5MB each). The whole folder takes about 130MB. Is this too much??? – D. Müller Oct 23 '15 at 12:41
  • yes, this will solve your issue – Ravneet Singh Oct 23 '15 at 12:42
  • using like this – Ravneet Singh Oct 23 '15 at 12:47
  • 1
    Don't load the full bitmap, it's probably not needed, scale it down first: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html – Ken Wolf Oct 23 '15 at 12:53
  • The android:largeHeap flag didn't solve the problem for me, I still get an OutOfMemoryException after about 6 minutes... – D. Müller Oct 23 '15 at 13:09
  • I found another solution now (with SurfaceView and VideoView), which fits better to my intent. But the information about the down-scaling of images was very helpful. Together with the largeHeap setting everything works fine in my new project. Thank you! – D. Müller Oct 27 '15 at 21:27

1 Answers1

0

Found the problem! There's no possible solution for viewing both, videos and images, with a SurfaceView. See also this post:

Android SurfaceView: Show Video after Images

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. [...]

Community
  • 1
  • 1
D. Müller
  • 3,336
  • 4
  • 36
  • 84