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. [...]
我正在编写一个 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. [...]