juliansteenbakker / mobile_scanner

A universal scanner for Flutter based on MLKit. Uses CameraX on Android and AVFoundation on iOS.
BSD 3-Clause "New" or "Revised" License
898 stars 517 forks source link

Constraints in LayoutBuilder sometimes zero #574

Open frankvollebregt opened 1 year ago

frankvollebregt commented 1 year ago

I was experiencing crashes on a Samsung Galaxy S21 running Android 13 (sometimes the system would report that the app is buggy, other times it would just crash outright). I did not experience this on a number of other devices including a Pixel 7, Pixel 2, Samsung Tab S5e, Samsung S9+. This stacktrace is printed to the console:

Original Stacktrace ``` E/AndroidRuntime(16076): java.lang.IllegalArgumentException: Cannot round NaN value. E/AndroidRuntime(16076): at o4.c.a(Unknown Source:15) E/AndroidRuntime(16076): at o4.a.a(Unknown Source:0) E/AndroidRuntime(16076): at i3.q.t(Unknown Source:124) E/AndroidRuntime(16076): at i3.q.p(Unknown Source:112) E/AndroidRuntime(16076): at i3.q.c(Unknown Source:0) E/AndroidRuntime(16076): at i3.p.b(Unknown Source:8) E/AndroidRuntime(16076): at k2.z.run(Unknown Source:25) E/AndroidRuntime(16076): at android.os.Handler.handleCallback(Handler.java:942) E/AndroidRuntime(16076): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime(16076): at android.os.Looper.loopOnce(Looper.java:226) E/AndroidRuntime(16076): at android.os.Looper.loop(Looper.java:313) E/AndroidRuntime(16076): at android.app.ActivityThread.main(ActivityThread.java:8757) E/AndroidRuntime(16076): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(16076): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571) E/AndroidRuntime(16076): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067) ```

Which is obfuscated so not terribly helpful. Luckily, the google play console pointed me to the culprit: this line in MobileScanner.kt, which would turn out to become NaN when being rounded. After doing some more debugging, it turns out to be a result of the Size of the constraints in the layout builder being set to 0.0. Then, while calculating the window, there is a division by this size resulting in the NaN value.

A possible solution to this error: setting the size to a minimum of 1 would prevent the error, but this would only work if the LayoutBuilder automatically rebuilds when its constraints change (that is, once the actual Widget is rendered, it is recalculated), and I'm not sure how that works.

Let me know your thoughts. Thanks :)

frankvollebregt commented 1 year ago

After testing a bit with the "solution" I proposed above, it seems like the 1x1 size is never updated once the actual Widget is displayed, and as a result I'm not able to scan codes during that "run".

My MobileScanner is located in a CustomPaint (for the overlay) in a Stack in a SafeArea in the Scaffold.body.

navaronbracke commented 8 months ago

Interesting find. AFAIK some devices only report an initial display size after the first frame, but I don't think that this could be the issue. What if we just return "false" for that check if the incoming sizes are zero ?

frankvollebregt commented 8 months ago

That sounds like a simple enough solution, and also logically sound: If the window size is 0, there is no way for the code to be inside it.

I'm not sure if there have been any changes in the plugin since I reported this bug that would influence how this is handled (neither do I know from the top of my head how I work around this currently... I'm using ^4.0.1 of the plugin, so I somehow must be taking this into account I guess. I'll get back to you about that)