maui icon indicating copy to clipboard operation
maui copied to clipboard

[regression/8.0.0-preview.5.8529] Crash on scrolling collection view

Open MissedSte4k opened this issue 2 years ago • 13 comments
trafficstars

Description

App just crashes with Java.Lang.RuntimeException: 'Canvas: trying to use a recycled bitmap android.graphics.Bitmap@4b0165b' Seems like the same issue as before. This should be solved here, but in every 8.0.* revision it seems to still be crashing (and I've tried them all).

Here is the call stack. It always seems to be the same. The very odd thing in it is the reference to net7.0/JniEnvironment.g.cs. As the version I'm runing the app is .net8 ¯_(ツ)_/¯ image

Steps to Reproduce

  1. open my repository in github (it has some redundant parts from testing over issues, but does the job)
  2. run on android emulator
  3. wait for a minute until it crashes (try to stay on the top of the page, so new images appear and push over images down)

Expected behavior: images open up and older images are pushed down

Actual behavior: images open up and older images are pushed down, but after about a minute you experience a crash with Java.Lang.RuntimeException: 'Canvas: trying to use a recycled bitmap android.graphics.Bitmap@4b0165b

P.S. for anyone that might launch the app on windows and see the insane behavior of DataTemplates - I already reported it here, over a year back.

Link to public reproduction project repository

https://github.com/MissedSte4k/MAUI-Canvas-trying-to-use-a-recycled-bitmap-crash-sample

Version with bug

8.0.0-preview.5.8529

Is this a regression from previous behavior?

Yes, this used to work in .NET MAUI

Last version that worked well

8.0.0-preview.4.8333

Affected platforms

Android

Affected platform versions

No response

Did you find any workaround?

Nope. Tried everything referenced in issues that got solved in https://github.com/dotnet/maui/pull/12310, but to no avail.

Relevant log output

No response

MissedSte4k avatar Nov 17 '23 11:11 MissedSte4k

Same here :/ I had to wait with releasing of my app due to huge issues in .net7 These were fixed in .net8 but now I am stopped at this one :/ so I cannot release my app to my customers again... No workaround works for me.

Engisan avatar Dec 07 '23 16:12 Engisan

Verified this on Visual Studio Enterprise 17.9.0 Preview 1(8.0.3). Repro on Android 14.0-API34 and Windows 11, not repro on iOS 17.0 and MacCatalyst with below Project: TestImages.zip

XamlTest avatar Dec 08 '23 06:12 XamlTest

@samhouts: what is the status on this issue? We experiencing the same crashes and this is preventing us releasing an urgent update to our customers!

Update after looking at similar issues and try/error: Workaround in https://github.com/dotnet/maui/issues/13534 did the job for me. Setting a fix height on an image in this case was not that what I wanted, but it prevents from crashes and unsatisfied customers.

Hope this helps solving this issue again! BR Stefan

Stefan171086 avatar Jan 05 '24 20:01 Stefan171086

Same here,

we get the same crashes in our public app right now with couple of devices. We have a simple screen to collect photos with the device camera and place this images into a horizontal scrolling collection view.

We see the same error as above: Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualBooleanMethod(JniObjectReference , JniObjectReference , JniMethodInfo , JniArgumentValue* ) Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualBooleanMethod(String , IJavaPeerable , JniArgumentValue* ) Android.Views.ViewGroup.DrawChild(Canvas , View , Int64 ) Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer.DrawChild(Canvas canvas, View child, Int64 drawingTime) Android.Views.ViewGroup.n_DrawChild_Landroid_graphics_Canvas_Landroid_view_View_J(IntPtr jnienv, IntPtr native__this, IntPtr native_canvas, IntPtr native_child, Int64 drawingTime) Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLJ_Z(_JniMarshal_PPLLJ_Z callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, IntPtr p1, Int64 p2) com.microsoft.maui.PlatformContentViewGroup.dispatchDraw PlatformContentViewGroup.java:47 android.view.View.draw View.java:25151 androidx.recyclerview.widget.RecyclerView.drawChild RecyclerView.java:5499 android.view.ViewGroup.dispatchDraw ViewGroup.java:4534 androidx.recyclerview.widget.RecyclerView.draw RecyclerView.java:4898 android.view.View.updateDisplayListIfDirty View.java:24007 androidx.coordinatorlayout.widget.CoordinatorLayout.drawChild CoordinatorLayout.java:1312 android.view.ViewGroup.dispatchDraw ViewGroup.java:4534 androidx.drawerlayout.widget.DrawerLayout.drawChild DrawerLayout.java:1483 crc640ec207abc449b2ca.ShellFlyoutRenderer.n_drawChild(Native Method) crc640ec207abc449b2ca.ShellFlyoutRenderer.drawChild ShellFlyoutRenderer.java:57 android.view.ViewGroup.dispatchDraw ViewGroup.java:4534

stoff99 avatar Feb 13 '24 11:02 stoff99

@mauiTeam Is there any update about this? I released now 5 Android updates the last 7 days with workarounds but i still see this crash happen in app center. Also in the crash report i have to information where this happens. Is there anything how i can find out more to see better error logs in AppCenter for Android?

stoff99 avatar Feb 23 '24 08:02 stoff99

Same issue with .NET 8. I have a CollectionView with images, if you scroll the list the app will crash. I didn't find any workaround.

Simoo23 avatar Mar 21 '24 13:03 Simoo23

When I replace the default StreamImageSourceService with the following code. Scroll through the CollectionView quickly and the program never crash again.

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            })
            .ConfigureImageSources(services =>
            {
#if ANDROID
                services.RemoveAll<IImageSourceService<IStreamImageSource>>();
                services.RemoveAll<IImageSourceService<StreamImageSource>>();
                services.AddService<IStreamImageSource>(_ => new CustomStreamImageSourceService());
                services.AddService<StreamImageSource>(_ => new CustomStreamImageSourceService());
#endif
            });

#if DEBUG
		builder.Logging.AddDebug();
#endif

        return builder.Build();
    }

#if ANDROID

    public class CustomStreamImageSourceService : StreamImageSourceService
    {
        public override async Task<IImageSourceServiceResult?> LoadDrawableAsync(IImageSource imageSource, ImageView imageView, CancellationToken cancellationToken = default)
        {
            var result = await base.GetDrawableAsync(imageSource, imageView.Context!, cancellationToken);
            // if (result?.Value is BitmapDrawable drawable && drawable.Bitmap?.IsRecycled == true)
            // {
            //     drawable.Bitmap.IsRecycled always false.
            // }
            imageView.SetImageDrawable(result?.Value);
            return result;
        }
    }

#endif

}

It might be base.LoadDrawableAsync passes a recycled bitmap to imageView, causing the program to crash. The same may be required for both FileImageSource and UriImageSource. (Machine translation was used)

jing8956 avatar Apr 01 '24 16:04 jing8956

I'm getting this error when I have an Image on my CarouselView . This is a show stopper for me.

I'm using: Net 8 MAUI - Latest VS2022 == Version 17.9.5

	<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.14" />
	<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.14" />

image

plppp2001 avatar Apr 04 '24 21:04 plppp2001

I have the same issue with the latest VS version and .NET 8. image I'm receiving the images through an API call from a FileManager, and the image is located inside grid, it crashed the app very rarely. I can offer more info if needed.

switchyy avatar Apr 08 '24 14:04 switchyy

Chiming in here with my 2c worth of evidence. I'm getting same issue with dotnet 8.0 (8.0.3) and VS 2022 Version 17.9.5 (Android app)

2024-04-10 09:35:54.868 +08:00 [FTL] Java.Lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@fe28425
   at Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualBooleanMethod(JniObjectReference instance, JniObjectReference type, JniMethodInfo method, JniArgumentValue* args)
   at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualBooleanMethod(String encodedMember, IJavaPeerable self, JniArgumentValue* parameters)
   at Android.Views.ViewGroup.DrawChild(Canvas canvas, View child, Int64 drawingTime)
   at Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer.DrawChild(Canvas canvas, View child, Int64 drawingTime)
   at Android.Views.ViewGroup.n_DrawChild_Landroid_graphics_Canvas_Landroid_view_View_J(IntPtr jnienv, IntPtr native__this, IntPtr native_canvas, IntPtr native_child, Int64 drawingTime)
   at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLJ_Z(_JniMarshal_PPLLJ_Z callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, IntPtr p1, Int64 p2)

I'm rather glad I found my way to this issue, I thought I was doing something wrong.

lythix avatar Apr 10 '24 14:04 lythix

Confirmed that this regressed between 8.0.0-preview.4.8333 and 8.0.0-preview.5.8529. Before pre5, the scrolling performance was atrocious, so I assume this was a memory leak resolved by properly disposing of the images. However, that leads to this crash.

Not sure exactly what the culprit was, but https://github.com/dotnet/maui/pull/14933, https://github.com/dotnet/maui/pull/12011, and https://github.com/dotnet/maui/pull/14109 seem most sus.

Incidentally, I changed the Frame to a Border to see if it helped and with that, I see that the background color of the cell goes from white in pre4 to black in pre5, which seems to be related to https://github.com/dotnet/maui/pull/14933 and is probably another regression/behavior change.

samhouts avatar Apr 12 '24 22:04 samhouts

Oh, yep, the repro is using a DTS, so looks like https://github.com/dotnet/maui/pull/12011 is most likely. @Redth fyi

samhouts avatar Apr 12 '24 22:04 samhouts

I have seen this before. Not specifying the Height and Width request, in your ImageViews, (using URLs of uploaded pictures with 1000x1600 for example as source) that are contained in your CollectionView, lead to the following problems:

In Android: You get random runtime crashes, when you scroll down the collection view. In IOS: You get empty collection view the first time you enter the page. Collection view with only first item loaded the second time you enter the page. And full collection view when you enter 3rd time in the page.

Setting WidthRequest=100, HeightRequest=100 is quick way to check if this applies to you.

(Forgot to say that this IOS behavior does not repeat when you close and open the app (it seems caching is involved in making the problem resolve itself), only reinstall introduces it again. But on Android it is persistent.)

H-A-Hristov avatar May 08 '24 13:05 H-A-Hristov

Thanks for the reply!

Setting WidthRequest=100, HeightRequest=100 is quick way to check if this applies to you.

Meaning the crashing stops? I've wondered if perhaps I can set or bind the height/width request to a calculated value so it is provided (but still fills the available width/height but stops the crashes)

lythix avatar May 09 '24 08:05 lythix

Meaning the crashing stops? I've wondered if perhaps I can set or bind the height/width request to a calculated value so it is provided (but still fills the available width/height but stops the crashes)

Not only the android crashing. The weird behavior on IOS also. You open "details" page, that contains CollectionView, that has ItemTeplate of DataTemplate of Image. Nothing else. And on the Image you have set "MaximumWidthRequest" and "MaximumHeightRequest", with aspect set to Fit. Open details once - empty. Second - only one image showing. Third time - everything.

Set specific measurements and both problems are gone.

To make matter worse - on the device I develop with most of the time, this problem could not be reproduced. On one of the test devices, this problem was showing, but only if your list has set amount of items. 4 or 5 pages - no problem. And the key to find this out was another test device, that was throwing this exception (crashing, actually), the second you try to scroll.

I hope this saves you some time.

H-A-Hristov avatar May 09 '24 10:05 H-A-Hristov

Any news on this? This issue is still presenting with maui 8.0.40. I'm not using an itemTemplateSelector in my case, just a collectionview where every item of the list is a grid with an image and labels. Set fixed Width and Height is not working

Simoo23 avatar May 15 '24 15:05 Simoo23

When I replace the default StreamImageSourceService with the following code. Scroll through the CollectionView quickly and the program never crash again.

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            })
            .ConfigureImageSources(services =>
            {
#if ANDROID
                services.RemoveAll<IImageSourceService<IStreamImageSource>>();
                services.RemoveAll<IImageSourceService<StreamImageSource>>();
                services.AddService<IStreamImageSource>(_ => new CustomStreamImageSourceService());
                services.AddService<StreamImageSource>(_ => new CustomStreamImageSourceService());
#endif
            });

#if DEBUG
		builder.Logging.AddDebug();
#endif

        return builder.Build();
    }

#if ANDROID

    public class CustomStreamImageSourceService : StreamImageSourceService
    {
        public override async Task<IImageSourceServiceResult?> LoadDrawableAsync(IImageSource imageSource, ImageView imageView, CancellationToken cancellationToken = default)
        {
            var result = await base.GetDrawableAsync(imageSource, imageView.Context!, cancellationToken);
            // if (result?.Value is BitmapDrawable drawable && drawable.Bitmap?.IsRecycled == true)
            // {
            //     drawable.Bitmap.IsRecycled always false.
            // }
            imageView.SetImageDrawable(result?.Value);
            return result;
        }
    }

#endif

}

It might be base.LoadDrawableAsync passes a recycled bitmap to imageView, causing the program to crash. The same may be required for both FileImageSource and UriImageSource. (Machine translation was used)

From my tests this resolve the problem

Simoo23 avatar May 16 '24 16:05 Simoo23

I ran into this one again on my own app when I decided to remove the WidthRequest from my images. Setting an explicit WidthRequest and HeightRequest is certainly the workaround.

samhouts avatar May 27 '24 16:05 samhouts

@samhouts I've observed that WidthRequest technique works only under certain circumstances. I create a sample app to repro the issue. App has a simple timer that periodically updates Image.Source. On my real devices (Galaxy A52s, Galaxy S22), it crashes with an update period of 70ms. There are 2 buttons to increase/decrease the delay.

Interestingly, if Image.WidthRequest is 500, then it crashes. If I change WidthRequest to 400 or lower, then it doesn't crash.

MauiAppRecycledBitmap.zip

viktorszekeress avatar Jun 12 '24 08:06 viktorszekeress

@viktorszekeress Did you try if this workaround work for you?

For me it seems to work

When I replace the default StreamImageSourceService with the following code. Scroll through the CollectionView quickly and the program never crash again.

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            })
            .ConfigureImageSources(services =>
            {
#if ANDROID
                services.RemoveAll<IImageSourceService<IStreamImageSource>>();
                services.RemoveAll<IImageSourceService<StreamImageSource>>();
                services.AddService<IStreamImageSource>(_ => new CustomStreamImageSourceService());
                services.AddService<StreamImageSource>(_ => new CustomStreamImageSourceService());
#endif
            });

#if DEBUG
		builder.Logging.AddDebug();
#endif

        return builder.Build();
    }

#if ANDROID

    public class CustomStreamImageSourceService : StreamImageSourceService
    {
        public override async Task<IImageSourceServiceResult?> LoadDrawableAsync(IImageSource imageSource, ImageView imageView, CancellationToken cancellationToken = default)
        {
            var result = await base.GetDrawableAsync(imageSource, imageView.Context!, cancellationToken);
            // if (result?.Value is BitmapDrawable drawable && drawable.Bitmap?.IsRecycled == true)
            // {
            //     drawable.Bitmap.IsRecycled always false.
            // }
            imageView.SetImageDrawable(result?.Value);
            return result;
        }
    }

#endif

}

It might be base.LoadDrawableAsync passes a recycled bitmap to imageView, causing the program to crash. The same may be required for both FileImageSource and UriImageSource. (Machine translation was used)

Simoo23 avatar Jun 12 '24 08:06 Simoo23

@Simoo23 I tried that and it does indeed solve the original problem - application doesn't crash now. The new problem is that RAM usage skyrockets for me to 2+GB. I have a CollectionView with potentially 200+ images (loaded on demand).

I also noticed decreased performance with this solution.

What I eventually did is that instead of converting byte[] to ImageSource I convert byte[] to Image - meaning it creates whole new Image for each byte[]. This does also increase RAM usage a bit (100 MB), but from my testing it settles down after a while and seems to behave stable.

viktorszekeress avatar Jun 12 '24 09:06 viktorszekeress

@viktorszekeress I'll try to check the Ram usage too.

But how do you convert byte[] to Image and bind to Image component in MVVM without using ImageSource?

Simoo23 avatar Jun 12 '24 10:06 Simoo23

@Simoo23 Instead of using Image in XAML and binding ImageSource, I use ContentView and I bind Content to byte[].

viktorszekeress avatar Jun 12 '24 10:06 viktorszekeress

@Simoo23 Instead of using Image in XAML and binding ImageSource, I use ContentView and I bind Content to byte[].

Does this work flawlessly on both iOS and ANdroid?

Also, what if we need to bind the image from an HTTP URI link? Any ideas there?

plppp2001 avatar Jun 12 '24 21:06 plppp2001

Does this work flawlessly on both iOS and ANdroid?

I haven't tested it on iOS. The question is, do we need this workaround there?

Also, what if we need to bind the image from an HTTP URI link? Any ideas there?

It's just a matter of converter (parameter) and how you construct the image.

viktorszekeress avatar Jun 13 '24 05:06 viktorszekeress

Is not possibile to increase the priority of this bug? I think that this is a basic feature as we are talking of a simple list of images and this bug is opened from Nov 17, 2023. We have some workarounds but they all have problems

Simoo23 avatar Jun 17 '24 09:06 Simoo23

Interestingly, if Image.WidthRequest is 500, then it crashes. If I change WidthRequest to 400 or lower, then it doesn't crash.

Are you sure about this? I cannot say about "width", but I am using "HeightRequest" of 500 and above, without this issue manifesting.

H-A-Hristov avatar Jun 24 '24 07:06 H-A-Hristov

Are you sure about this? I cannot say about "width", but I am using "HeightRequest" of 500 and above, without this issue manifesting.

I'm sure. Obviously, it depends on other circumstances, like: original size of the image, aspect ratio, available area... Just try out the sample I provided.

viktorszekeress avatar Jun 24 '24 07:06 viktorszekeress