Android应用程序抛出OutOfMemoryError异常

3

我正在制作一款Android应用程序,可以将服务器上的视频流传输到Android手机。 我已经成功地实现了图像流,并且在15秒后应用程序崩溃。 我设法追踪到了OutOfMemoryError错误。 在将位图传递给接口以将其传递到线程以显示它之后,我尝试回收位图,但是出现了“无法重复使用已回收的位图”错误。 我不确定如何修复此错误,甚至不确定是否重新调整大小会解决问题。

                    int read_count = 1;
                    long start_time = System.currentTimeMillis();
                    long timeout = 10000;
                    boolean timed_out = false;

                    byte[] data = new byte[size + 1];
                    while (read_count < size && !timed_out)
                    {
                        int len = in.read(data, read_count, size - read_count);
                        read_count += len;
                        timed_out = (System.currentTimeMillis() - start_time) >= timeout;
                    }
                    data[0] = (byte)0x89;

                    if (read_count == size)
                    {
                        final boolean is_left = (side == 0);
                        final byte[] tmp = data;
                        Bitmap Image_data = null;
                        System.out.println(tmp.length);
                        if (Listener != null)
                        {
                            Image_data = BitmapFactory.decodeByteArray(tmp, 0, tmp.length);

                            Listener.OnNewImageListenerBitmap(Image_data, is_left);

                          // this is where i tried recycling it//
                        }

                    }

我成功追踪到内存错误是由于这行代码“byte[] data = new byte[size + 1];”,但经过研究我得出的印象是由于位图引起的。
有其他人遇到这个问题并成功解决了吗?如果有任何帮助,那就太棒了:D
谢谢
LOGCAT输出:

02-10 15:22:15.488  32097-32122/com.google.vrtoolkit.cardboard.samples.treasurehunt I/System.out﹕ 373348
02-10 15:22:16.655  32097-32122/com.google.vrtoolkit.cardboard.samples.treasurehunt I/System.out﹕ 373348
02-10 15:22:17.371  32097-32122/com.google.vrtoolkit.cardboard.samples.treasurehunt I/System.out﹕ 373348
02-10 15:22:18.827  32097-32122/com.google.vrtoolkit.cardboard.samples.treasurehunt I/System.out﹕ 373348
02-10 15:22:29.167  32097-32122/com.google.vrtoolkit.cardboard.samples.treasurehunt I/art﹕ Alloc sticky concurrent mark sweep GC freed 37627(1380KB) AllocSpace objects, 0(0B) LOS objects, 6% free, 114MB/122MB, paused 905us total 7.018ms
02-10 15:22:29.178  32097-32122/com.google.vrtoolkit.cardboard.samples.treasurehunt I/art﹕ Alloc partial concurrent mark sweep GC freed 110(3KB) AllocSpace objects, 2(92MB) LOS objects, 40% free, 22MB/36MB, paused 1.112ms total 11.404ms
02-10 15:22:29.202  32097-32122/com.google.vrtoolkit.cardboard.samples.treasurehunt I/art﹕ Alloc concurrent mark sweep GC freed 141(17KB) AllocSpace objects, 0(0B) LOS objects, 40% free, 22MB/36MB, paused 825us total 23.893ms
02-10 15:22:29.202  32097-32122/com.google.vrtoolkit.cardboard.samples.treasurehunt I/art﹕ Forcing collection of SoftReferences for 1GB allocation
02-10 15:22:29.223  32097-32122/com.google.vrtoolkit.cardboard.samples.treasurehunt I/art﹕ Alloc concurrent mark sweep GC freed 67(2520B) AllocSpace objects, 0(0B) LOS objects, 39% free, 22MB/36MB, paused 2.473ms total 18.440ms
02-10 15:22:29.223  32097-32122/com.google.vrtoolkit.cardboard.samples.treasurehunt E/art﹕ Throwing OutOfMemoryError "Failed to allocate a 1801149826 byte allocation with 15419532 free bytes and 233MB until OOM"
02-10 15:22:29.223  32097-32122/com.google.vrtoolkit.cardboard.samples.treasurehunt E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-1308
    Process: com.google.vrtoolkit.cardboard.samples.treasurehunt, PID: 32097
    java.lang.OutOfMemoryError: Failed to allocate a 1801149826 byte allocation with 15419532 free bytes and 233MB until OOM
            at Socket.ClientThread.run(ClientThread.java:130)
02-10 15:22:29.833  32097-32121/com.google.vrtoolkit.cardboard.samples.treasurehunt I/MainActivity﹕ onRendererShutdown
02-10 15:22:32.793  32097-32122/com.google.vrtoolkit.cardboard.samples.treasurehunt I/Process﹕ Sending signal. PID: 32097 SIG: 9


我尝试查看并使用该解决方案,但在我的情况下它没有起作用。 - user3774031
1个回答

6
在Android 5上遇到了类似的问题。将您的图像移动到/drawable-nodpi而不是/drawable文件夹中。
编辑:我认为这与使用当前设备DPI自动缩放图像有关。例如,如果您只在/drawable-mdpi文件夹中有大的图像,但您的设备是xxxhdpi,则Android会使用mdpi中可用的图像,并尝试将其缩放以匹配xxxhdpi,这可能占用过多内存。但是,/drawable-nodpi文件夹中的图像不会被缩放,它们被直接使用。

问题已经被解决,对我来说很有帮助。+1。 - Arun
谢谢,它对我也起作用了。你能解释一下它是如何工作的吗? - Anil Chandra Varma Dandu
如果你是正确的,那么这意味着drawable/目录中的图像也被缩放了,对吗?但在这种情况下,Android如何计算比例因子(因为那里没有密度参与)? - Mickäel A.
是的,“drawable/”是有缩放的。引用自此处:drawable/中的资源是默认的可绘制资源。系统假定默认资源是针对基准屏幕大小和密度设计的,即普通屏幕大小和中密度。因此,系统会根据需要将默认密度资源放大到高密度屏幕上,并缩小到低密度屏幕上。 - Borzh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接