Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SVG - Android] Failed to load SVG image - System.Xml.XmlException: Invalid character in the given encoding. #15866

Closed
agneszitte opened this issue Mar 12, 2024 · 17 comments
Labels
area/svg Categorizes an issue or PR as relevant to SVG rendering difficulty/medium 🤔 Categorizes an issue for which the difficulty level is reachable with a good understanding of WinUI kind/bug Something isn't working

Comments

@agneszitte
Copy link
Contributor

agneszitte commented Mar 12, 2024

Current behavior

Failed to load SVG image - System.Xml.XmlException: Invalid character in the given encoding happening when loading the MainPage of the sample app on Android.

[Choreographer] Skipped 54 frames!  The application may be doing too much work on its main thread.
[monodroid-assembly] open_from_bundles: failed to load assembly Svg.Model.dll
[monodroid-assembly] open_from_bundles: failed to load assembly ShimSkiaSharp.dll
Loaded assembly: /data/data/com.companyname.UnoSvgSample/files/.__override__/Svg.Model.dll [External]
Loaded assembly: /data/data/com.companyname.UnoSvgSample/files/.__override__/ShimSkiaSharp.dll [External]
[monodroid-assembly] open_from_bundles: failed to load assembly System.Runtime.InteropServices.RuntimeInformation.dll
Loaded assembly: /data/data/com.companyname.UnoSvgSample/files/.__override__/System.Runtime.InteropServices.RuntimeInformation.dll [External]
[monodroid-assembly] open_from_bundles: failed to load assembly Svg.Custom.dll
Loaded assembly: /data/data/com.companyname.UnoSvgSample/files/.__override__/Svg.Custom.dll [External]
[monodroid-assembly] open_from_bundles: failed to load assembly ExCSS.dll
Loaded assembly: /data/data/com.companyname.UnoSvgSample/files/.__override__/ExCSS.dll [External]
[DOTNET] fail: Uno.UI.Svg.SvgProvider[0]
[DOTNET]       Failed to load SVG image.
[DOTNET]       System.Xml.XmlException: Invalid character in the given encoding. Line 1, position 1.
[DOTNET]          at System.Xml.XmlTextReaderImpl.Throw(Exception e)
[DOTNET]          at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
[DOTNET]          at System.Xml.XmlTextReaderImpl.Throw(Int32 pos, String res)
[DOTNET]          at System.Xml.XmlTextReaderImpl.InvalidCharRecovery(Int32& bytesCount, Int32& charsCount)
[DOTNET]          at System.Xml.XmlTextReaderImpl.GetChars(Int32 maxCharsCount)
[DOTNET]          at System.Xml.XmlTextReaderImpl.ReadData()
[DOTNET]          at System.Xml.XmlTextReaderImpl.SwitchEncoding(Encoding newEncoding)
[DOTNET]          at System.Xml.XmlTextReaderImpl.SwitchEncodingToUTF8()
[DOTNET]          at System.Xml.XmlTextReaderImpl.ParseXmlDeclaration(Boolean isTextDecl)
[DOTNET]          at System.Xml.XmlTextReaderImpl.Read()
[DOTNET]          at System.Xml.XmlTextReader.Read()
[DOTNET]          at Svg.SvgTextReader.Read() in /_/externals/SVG/Source/SvgTextReader.cs:line 66
[DOTNET]          at Svg.SvgDocument.Create[SvgDocument](XmlReader reader) in /_/externals/SVG/Source/SvgDocument.cs:line 363
[DOTNET]          at Svg.SvgDocument.Open[SvgDocument](Stream stream, Dictionary`2 entities) in /_/externals/SVG/Source/SvgDocument.cs:line 299
[DOTNET]          at Svg.Model.SvgExtensions.Open(Stream stream) in /_/src/Svg.Model/SvgExtensions.IO.cs:line 329
[DOTNET]          at Svg.Skia.SKSvg.Load(Stream stream) in /_/src/Svg.Skia/SKSvg.Model.cs:line 63
[DOTNET]          at Uno.UI.Svg.SvgProvider.<>c__DisplayClass22_0.<LoadSvgAsync>b__0()

Expected behavior

The application should not throw an exception while using an SVG file for Image control like it is currently working on Windows, WASM, Skia, and iOS.

How to reproduce it (as minimally and precisely as possible)

  • Open the sample app attached here (UnoSvgSample.zip)
  • Build and launch the app for Android
  • Noticed the exception mentioned above in the output when the MainPage is displayed and that the SVG is not visible like on the other platforms

In MainPage.xaml

    <Image Source="ms-appx:///UnoSvgSample/Assets/unologo.svg"
           Height="80"
           Width="80" />

In UnoSvgSample.csproj

  <ItemGroup>
    <Content Include="Assets\unologo.svg" />
  </ItemGroup>
  <ItemGroup>
    <None Remove="Assets\unologo.svg" />
  </ItemGroup>

Workaround

N/A

Works on UWP/WinUI

Yes

Environment

Uno.UI / Uno.UI.WebAssembly / Uno.UI.Skia

NuGet package version(s)

Uno.WinUI : 5.1.87

Affected platforms

Android

IDE

Visual Studio 2022

IDE version

17.9.2

Relevant plugins

No response

Anything else we need to know?

No response

@agneszitte agneszitte added kind/bug Something isn't working triage/untriaged Indicates an issue requires triaging or verification difficulty/tbd Categorizes an issue for which the difficulty level needs to be defined. labels Mar 12, 2024
@agneszitte
Copy link
Contributor Author

cc @MartinZikmund

@Youssef1313 Youssef1313 added the area/svg Categorizes an issue or PR as relevant to SVG rendering label Mar 12, 2024
@MartinZikmund MartinZikmund added difficulty/medium 🤔 Categorizes an issue for which the difficulty level is reachable with a good understanding of WinUI and removed triage/untriaged Indicates an issue requires triaging or verification difficulty/tbd Categorizes an issue for which the difficulty level needs to be defined. labels Mar 13, 2024
@MartinZikmund
Copy link
Member

The encoding mentioned in the error might be the pointer to the problem. Is it this specific SVG that does not work? Or all SVGs throw?

@agneszitte
Copy link
Contributor Author

agneszitte commented Mar 13, 2024

The encoding mentioned in the error might be the pointer to the problem. Is it this specific SVG that does not work? Or all SVGs throw?

@MartinZikmund let me try with another more simple SVG (that does not use style or other additional specific data to see)

@agneszitte
Copy link
Contributor Author

agneszitte commented Mar 14, 2024

The encoding mentioned in the error might be the pointer to the problem. Is it this specific SVG that does not work? Or all SVGs throw?

@MartinZikmund let me try with another more simple SVG (that does not use style or other additional specific data to see)

@MartinZikmund I did more tests with multiple SVGs, and even for the simpler one that uses only one path data, I still get the same exception on Android (working well on the other platforms).

Here are the tests that I did + the sample solution attached here is ready for you so you can test it on your side
UnoSvgAndroidTests.zip

  <StackPanel>
    
    <!-- [TEST 1 - Exception for Android - Uno Platform Logo Colored Svg that uses style and linearGradient -->
    <Image Source="ms-appx:///UnoSvgAndroidTests/Assets/unologo.svg"
           Height="80"
           Width="80" />

    <!-- [TEST 2 - Exception for Android - Uno Platform Logo number 2 Colored Svg that uses style and linearGradient -->
    <Image Source="ms-appx:///UnoSvgAndroidTests/Assets/unologo2.svg"
           Height="80"
           Width="100" />

    <!-- [TEST 3 - Exception for Android - OpenSource Colored Svg that uses no style and no linearGradient, only multiple path data -->
    <Image Source="ms-appx:///UnoSvgAndroidTests/Assets/undraw_opensource.svg"
           Height="80"
           Width="80" />

    <!-- [TEST 4 - Exception for Android - OpenSource Solid filled Svg that uses no style and no linearGradient, only one path data -->
    <Image Source="ms-appx:///UnoSvgAndroidTests/Assets/flowbite_opensource.svg"
           Height="40"
           Width="40" />
    
  </StackPanel>

Note

Here is the Android emulator that I used for my tests
image

@MartinZikmund MartinZikmund self-assigned this Mar 15, 2024
@MartinZikmund
Copy link
Member

MartinZikmund commented Mar 16, 2024

@agneszitte @pictos So after quite a bit of debugging I finally have some answers 😂 . In the end Resizetizer is indeed causing the problem. If you build the sample above and extract the apk, you will find that all of the SVGs are included not only as .svg in the root assets folder:

image

But Resizetizer also generates png versions of them in drawable folders, even though at least two of them are explicitly "removed" in the .csproj:

image

This is unfortunately a big problem because our code does the following:

image

FindResourceIdFromPath unfortunately does not include the file extension in the name which means it just searches for a resource with name unosvgandroidtests_assets_flowbite_opensource for example, so the condition of the if passes and it tries to read the svg from the png file -> which makes it fail, even though it should use the Android Asset instead. I could theoretically invert the if to give precedence to the asset instead, but there still are other issues:

  1. We need to generate the Android resource names including their extension (I will take care of this)
  2. We must add a way for the user to explicitly ignore a file or even better a wildcard pattern (like Assets/Svg/**.svg) and avoid processing it completely so that those drawables that could conflict will not be generated (plus so the apk does not contain duplicates unnecessarily when the user actually wants a SVG file) @pictos

@agneszitte
Copy link
Contributor Author

agneszitte commented Mar 16, 2024

@agneszitte @pictos So after quite a bit of debugging I finally have some answers 😂 . In the end Resizetizer is indeed causing the problem.

@MartinZikmund, @pictos, @nickrandolph
In my head, if we are doing [Scenario 1] where we have a .svg in the path, Resizetizer should not be involved and should not generate any .png at all.

[Scenario 1]
Using a .svg in the path of the Image control
[unologo.svg file build action = Content]
<Image Source="ms-appx:///UnoSvgSample/Assets/unologo.svg" />
Following this doc: Using SVG images (platform.uno)

VS

[Scenario 2]
Using a .png in the path of the Image control that uses an .svg file underneath with Uno.Resizetizer (UnoImage)
[unologo.svg file build action = UnoImage]
<Image Source="ms-appx:///UnoSvgSample/Assets/unologo.png" />
Following this doc: https://platform.uno/docs/articles/external/uno.resizetizer/doc/using-uno-resizetizer.html?tabs=classlib%2CAndroid#unoimage

@nickrandolph
Copy link
Contributor

@agneszitte @MartinZikmund @pictos can we confirm what the normal behavior is for Resizetizer. My understanding is that if you have an SVG it will be automatically picked up as UnoImage. The SVG shouldn't be included in the package, instead the corresponding png files generated by resizetizer are. @pictos can you confirm this is the correct behaviour?

Assuming the above behaviour is correct, then we need to ensure that if someone changes the build action on an SVG to Content, then we respect this. We should not be generating PNG files (since it shouldn't be included as UnoImage) and the SVG should be packaged as the user would expect.

We shouldn't be using the way they reference the file to determine how the file is packages. However, it maybe that we can have an analyzer as part of Resizetizer that detects when user is referencing an SVG for a file that's being resizetized.

@pedrojesus-work
Copy link

Svgs used as UnoImage shouldn't be in the final app, created this issue to track progress on Resizetizer side:

@pedrojesus-work
Copy link

After some investigation that behavior (pack the svg on final app) only happens if the svg used by UnoImage are inside the Assets folder otherwise just the generated images are packaged on final app. It sets the svg file to AndroidAsset, which isn't done by Resizetizer.

The workaround that I found is to not add UnoImages inside Assets folder or subfolders, couldn't find a way to remove it during the build yet, maybe @jeromelaban has any idea on how to remove it?

Here's the binlog if anyone wants to take a look.

AssetSvgFile.zip

@nickrandolph
Copy link
Contributor

After some investigation that behavior (pack the svg on final app) only happens if the svg used by UnoImage are inside the Assets folder otherwise just the generated images are packaged on final app. It sets the svg file to AndroidAsset, which isn't done by Resizetizer.

The workaround that I found is to not add UnoImages inside Assets folder or subfolders, couldn't find a way to remove it during the build yet, maybe @jeromelaban has any idea on how to remove it?

Here's the binlog if anyone wants to take a look.

AssetSvgFile.zip

This would be a result of the template (probably in csproj of the application) including the svg as Content, as well as being included as UnoImage. This image shows the back.svg being included as both Content and UnoImage

image

@pedrojesus-work when you're attaching bin log, please don't use binlog generated by the Build Logging window in VS, as this is missing half the useful information required to diagnose most issues. In the following image there should be a Find in Files tab, which is useful for diagnosing the root cause of build related issues but is missing from the binlog generated by the Build Logging window
image

@jeromelaban
Copy link
Member

Resizetizer should clean the Content item group automatically if the SVGs should not be included in the final layout, as they've been added to UnoImages.

@agneszitte
Copy link
Contributor Author

agneszitte commented Apr 12, 2024

@jeromelaban, @pedrojesus-work (cc @MartinZikmund / @nickrandolph )
Can I have a little bit of a status for this issue, please
Fixes done in Resizetizer? If so, was it properly QA with latest packages?

@jeromelaban
Copy link
Member

jeromelaban commented Apr 12, 2024

@pedrojesus-work will know.

@pedrojesus-work
Copy link

pedrojesus-work commented Apr 12, 2024

I thought I closed this issue already... As I mentioned here the work and progress will be on Resizetizer project.

If so, was it properly QA with latest packages?

@agneszitte The latest package (dev) should be good to test it.

Any further updates, please use the linked issue

@agneszitte
Copy link
Contributor Author

agneszitte commented Apr 12, 2024

Thank @pedrojesus-work for the update, appreciated!
Next time don't hesitate to ask us to transfer the issues to another repo, best to do that when we can to avoid creating additional issues, please ;) Or it is because we also have this related PR @MartinZikmund #15891 ?

@Darsh0307 if you can help test with the latest version please

@unoplatform unoplatform deleted a comment from Darsh0307 Apr 15, 2024
@unoplatform unoplatform deleted a comment from Darsh0307 Apr 15, 2024
@MartinZikmund
Copy link
Member

the linked PR will be breaking, so it has to wait for a major release, But it is not crucial one right now anyway.

@unoplatform unoplatform deleted a comment from Darsh0307 May 2, 2024
@Darsh0307
Copy link
Contributor

Darsh0307 commented May 3, 2024

This issue is now fixed on all platforms, no more Failed to load SVG image - System.Xml.XmlException: Invalid character in the given encoding.

I created the sample app using the Blank template with Visual Studio Wizard.

Visual Studio Version: 
"Uno.Sdk": "5.2.108"
Uno templates:- 5.2.31
Uno VSIX :- 5.2.46.54

I tested the following platforms:

  • Windows - Packaged
  • Windows - Unpackaged
  • Android
  • iOS
  • MacCatalyst
  • WebAssembly (Chrome / Edge / Safari )
  • WebAssembly - IIS Express (Chrome / Edge / Safari )
  • Desktop (WSL)
  • Desktop (WSL2)

The zip file for the sample app I used for the tests:
SVGtRIAL.zip


While during my tests, I also noticed this other issue for Windows Package/Unpackaged: #16571

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/svg Categorizes an issue or PR as relevant to SVG rendering difficulty/medium 🤔 Categorizes an issue for which the difficulty level is reachable with a good understanding of WinUI kind/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

7 participants