1

When I first run my Xamarin.forms Android application after installation, it opens a page that contains a Avertissement _5.png image that is 89.2 KB in size.

<Grid HorizontalOptions="StartAndExpand" VerticalOptions="StartAndExpand">
                <Image x:Name="Advert" 
                       Opacity="0.7" 
                       IsVisible="false" 
                       Aspect="Fill"
                       Source="Avertissement_5.png"/>
                    <Label x:Name="AdvertText1"
                       IsVisible="false"
                       FontSize="Medium"
                       TextColor="White"
                       FontAttributes="Italic"
                       Text="Vous n'avez aucune liste !"
                       VerticalOptions="Center"
                       HorizontalOptions="Center"
                       Margin=" 0,-30,0,0"/>
                    <Label x:Name="AdvertText2"
                       IsVisible="false"
                       FontSize="Medium"
                       TextColor="White"
                       FontAttributes="Italic"
                       Text="Tapez sur le bouton + pour en ajouter une..."
                       VerticalOptions="Center"
                       HorizontalOptions="Center"
                       Margin=" 0,30,0,0"/>
            </Grid>

This image is placed in the Resources / drawable folder. On some phones (mainly Samsung brand), the application crashes when viewing this page with the following error:

FATAL EXCEPTION: main Process: com.ApriSoft.memocourses, PID: 5826 java.lang.RuntimeException: Canvas: trying to draw too large(165514752bytes) 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.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 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.support.v4.widget.DrawerLayout.drawChild(DrawerLayout.java:1426) 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.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(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

I don't understand this error regarding the size of a bitmap file of 165514752 bytes, when I don't have any bitmap files in my Resources / drawable folder, and this error only occurs on some phones. Thank you very much for your help because my app cannot be used on some phones.

Marcel Delhaye
  • 93
  • 1
  • 10
  • A "bitmap" is what an image file becomes, in memory. If the phone uses 4 bytes per pixel, then that is an image with 165514752/4 = about 40 million pixels in it. That would be about 6000 pixels x 7000 pixels. What are the dimensions, in pixels, of your png file? If the image does have that many pixels, use photoshop or other software to shrink it, so it has fewer pixels. (The size of the file on disk does not matter.) – ToolmakerSteve Jul 24 '21 at 19:05
  • The size of my png file is 92 KB. I didn’t figure out how to calculate the size of this file in pixels. But the most important question is: why does this image display correctly on most phones except a few? – Marcel Delhaye Jul 26 '21 at 13:58
  • You could try to move it to `drawable-xxhdpi` folder. – Leo Zhu Jul 27 '21 at 02:52
  • @Leo : When I move the png file to the mipmap-xxhdpi folder, it doesn't show. Should we modify the xaml code according to this modification? Thank you for your response. – Marcel Delhaye Jul 27 '21 at 14:48
  • @ToolmakerSteve : My file size in pixels is 1842 * 2496 = 4597632 pixels. I forgot to say that when the page loads I show another image (with the same size), but which is hidden by the first one. In total, that makes 9,195,264: we are far from 40 million... – Marcel Delhaye Jul 27 '21 at 15:13
  • Good that's what I needed to know. I've added an answer. – ToolmakerSteve Jul 27 '21 at 19:09

1 Answers1

1

165514752 bytes / 4597632 pixels = 36 bytes per pixel.

That Samsung phone must have screen (pixel) Density=3; its expanding the image 3x, which costs 3 x 3 x 4 bytes / pixel = 36 bytes/pixel.

Fortunately there is a fix: create a drawable-nodpi folder in Resources. Move the image there.

As explained in this SO post:

drawable-nodpi will bypass scaling and drawable will use the default scaling

Be sure to REMOVE the original image from folder drawable. That forces it to look in the "alternative" drawable folders.


This should help image load performance on any Android phone that does that pre-scaling of images (to match screen Density).

ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196
  • 1
    After making the changes you told me (creating a 'drawable-nodpi' folder in Resources and moving the png files), everything seems to be working fine: I no longer have an error in the pre-launch report of the Google Play console. I have been looking for a solution for several weeks, and you gave it to me. Thank you very much for your help ! – Marcel Delhaye Jul 29 '21 at 13:27