App crashes on startup due to rounded button with image using current AI2 version

Hi,

I found an issue with one of my Apps that only started with the current App Inventor but not with whatever version that was running on March 2023 (that was when the last working .apk was built).

I found the issue and solved it for my App and it is probably phone related. However, since previous version of App Inventor was able to build working .apk maybe it is a combination of phone-AI2 problem. Here is what I know in case someone is struggling with something similar.

As the title says, the problem is that when the App is opened it doesn't show anything before it crashes. The cellphone is a Redmi 9 (MIUI 13.0.2.0). The same .apk works fine in a Redmi Note 9 tablet. I downloaded the AI2Offline with the version nb189b (Sep22) and the built app worked fine in my phone and all devices I tried.

After playing around a lot I found a minimalistic way to trigger the issue:

  • Create new project
  • Add a button
  • Upload a large image (2239 x 335 px. I don't know the threshold but 600x300 wont trigger the issue)
  • Use the image for the button
  • Select Rounded as a shape for the button

The project should look something like this (project .aia here
bugRoundedButtonImage.aia (1.5 KB)
):

I was able to replicate it using the Companion and USB connection and I can upload and set for the button the big image, but as soon as I change the shape to rounded Companion chases as the App does.

The solution for my case was just to reduce the size of the image of the button.

I hope this helps anyone.

PD: Here is the report of the crash generated by my phone.

java.lang.RuntimeException: Canvas: trying to draw too large(171555024bytes) bitmap.
	at android.graphics.RecordingCanvas.throwIfCannotDraw(RecordingCanvas.java:266)
	at android.graphics.BaseRecordingCanvas.drawBitmap(BaseRecordingCanvas.java:94)
	at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:549)
	at android.view.View.getDrawableRenderNode(View.java:23503)
	at android.view.View.drawBackground(View.java:23401)
	at android.view.View.draw(View.java:23133)
	at android.view.View.updateDisplayListIfDirty(View.java:21975)
	at android.view.View.draw(View.java:22859)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4602)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4360)
	at android.view.View.updateDisplayListIfDirty(View.java:21964)
	at android.view.View.draw(View.java:22859)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4602)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4360)
	at android.view.View.draw(View.java:23157)
	at android.view.View.updateDisplayListIfDirty(View.java:21975)
	at android.view.View.draw(View.java:22859)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4602)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4360)
	at com.google.appinventor.components.runtime.ScaledFrameLayout.dispatchDraw(ScaledFrameLayout.java:63)
	at android.view.View.updateDisplayListIfDirty(View.java:21964)
	at android.view.View.draw(View.java:22859)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4602)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4360)
	at android.view.View.updateDisplayListIfDirty(View.java:21964)
	at android.view.View.draw(View.java:22859)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4602)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4360)
	at android.view.View.updateDisplayListIfDirty(View.java:21964)
	at android.view.View.draw(View.java:22859)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4602)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4360)
	at android.view.View.updateDisplayListIfDirty(View.java:21964)
	at android.view.View.draw(View.java:22859)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4602)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4360)
	at android.view.View.updateDisplayListIfDirty(View.java:21964)
	at android.view.View.draw(View.java:22859)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4602)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4360)
	at android.view.View.updateDisplayListIfDirty(View.java:21964)
	at android.view.View.draw(View.java:22859)
	at android.view.ViewGroup.drawChild(ViewGroup.java:4602)
	at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4360)
	at android.view.View.draw(View.java:23157)
	at com.android.internal.policy.DecorView.draw(DecorView.java:890)
	at android.view.View.updateDisplayListIfDirty(View.java:21975)
	at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:534)
	at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:542)
	at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:625)
	at android.view.ViewRootImpl.draw(ViewRootImpl.java:4863)
	at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4569)
	at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3662)
	at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2389)
	at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9369)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1137)
	at android.view.Choreographer.doCallbacks(Choreographer.java:920)
	at android.view.Choreographer.doFrame(Choreographer.java:834)
	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1119)
	at android.os.Handler.handleCallback(Handler.java:938)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:210)
	at android.os.Looper.loop(Looper.java:299)
	at android.app.ActivityThread.main(ActivityThread.java:8280)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:576)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1073)

Same result if button shape is set to rectangular or oval, with default, no crash.

because you don't changed size after applying image and your image size is equal to current button size

Try resizing your image down to around 512 x 74 pixels using an image resizing software, reupload the image, and try again.

Fact is, as the OP went to pains to point out, it is a bug, with several ways to workaround it.

added: FAQ Section: Limits

2 Likes

Compression is not really the issue here so much. Based on the stack trace, the uncompressed image is 171555024 bytes (that's almost 171 MB for those keeping score at home), or an image roughly 6500 pixels to the side if it is square. The texture buffer memory for graphics chips will vary from device to device so the outcomes will vary depending on the hardware capabilities. At best, what we might be able to do is catch the exception in the draw method (preventing the crash) and report it via an error handler, but unfortunately without knowing which view is at fault there would be no way to correct this in a compiled app at runtime.

2 Likes