4
votes

I am testing my app on 5 devices: Samsung Galaxy core, Samsung S6 edge, Moto G4, Xiaomi Redmi note 4 and Xiaomi MiA1. Loading bitmaps works fine on them but on some other it throws java.lang.RuntimeException: Canvas: trying to draw too large. Can you help me find a solution?

Log:

Fatal Exception: java.lang.RuntimeException: Canvas: trying to draw too large(135788800bytes) bitmap. at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:229) at android.view.RecordingCanvas.drawBitmap(RecordingCanvas.java:97) at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:529) at android.widget.ImageView.onDraw(ImageView.java:1367) at android.view.View.draw(View.java:20338) at android.view.View.updateDisplayListIfDirty(View.java:19283) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.draw(View.java:20341) at android.view.View.updateDisplayListIfDirty(View.java:19283) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.updateDisplayListIfDirty(View.java:19274) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.updateDisplayListIfDirty(View.java:19274) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.updateDisplayListIfDirty(View.java:19274) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.updateDisplayListIfDirty(View.java:19274) at android.view.View.draw(View.java:20061) at android.view.ViewGroup.drawChild(ViewGroup.java:4421) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4207) at android.view.View.draw(View.java:20341) at com.android.internal.policy.DecorView.draw(DecorView.java:979) at android.view.View.updateDisplayListIfDirty(View.java:19283) at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:686) at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:692) at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:800) at android.view.ViewRootImpl.draw(ViewRootImpl.java:3447) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3234) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2769) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1738) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7745) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911) at android.view.Choreographer.doCallbacks(Choreographer.java:723) at android.view.Choreographer.doFrame(Choreographer.java:658) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6938) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

4
If you have any large image in your drawable folder, then compress the image and then it will run perfectly.Darshan Popat
too big image to draw. Phone can not allocated enough memory. Try yo use vector image or small size image, not high resolution.Jevgenij Kononov
135788800bytes / 1000 are 135788 kbytes / 1000 are 135 Mbytes, lets assume you have 4 bytes per pixel (ARGB), you have 135788800 / 4 = 33947200 and to assume a squared image: root of 33947200 = 5826. Are you really trying to draw an image with 5800x5800 pixels?WarrenFaith
actually,I found the solution the real culprit was splash screen image, my designer did some sloppy work and gave me wrong sized images for splash screen, So i tested it on emulator and app crashed in big devices like Pixel xl-2 and in My colleague's phone. image size was not proper and it was causing crash , he gave me new images for that and now everything works fine.Obito

4 Answers

2
votes

Try to compress your selected image before doing any action.

Here is the code that compress image with equal aspect ratio.

I converted Uri to bitmap

bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);

The i pass the bitmap, maxwidth, minWidth to resize().

resizeBitmap = resize(bitmap, bitmap.getWidth() / 2, bitmap.getHeight() / 2);

resize() method

private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) {
    if (maxHeight > 0 && maxWidth > 0) {
        int width = image.getWidth();
        int height = image.getHeight();
        float ratioBitmap = (float) width / (float) height;
        float ratioMax = (float) maxWidth / (float) maxHeight;

        int finalWidth = maxWidth;
        int finalHeight = maxHeight;
        if (ratioMax > ratioBitmap) {
            finalWidth = (int) ((float) maxHeight * ratioBitmap);
        } else {
            finalHeight = (int) ((float) maxWidth / ratioBitmap);
        }
        image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true);
        return image;
    } else {
        return image;
    }
}
1
votes

Even if you reduce the file size of your image by compressing it, the Bitmap shown on the phone will still take substantial amount of memory. Bitmap renders every pixel independently and therefore a 4048x3036 pixels image can take up to 48 Mb of memory

The solution would be to reduce the resolution while maintaining desirable detail quality.

Loading Large Bitmaps Efficiently

0
votes

You can use Picasso to resize your image:

Picasso.get().load(imageUri).resize(512,512).into(imageView);

In resize method, the 2 numbers are the target width and height of your image. Change them as you like (but don't put too large numbers!).

It worked for me.

0
votes

If your app is using Glide:

Glide.with(context).load(uri).into(imageView);