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

I got an exception when try to run on Android #1

Open
reinierkops opened this issue Jan 18, 2024 · 10 comments
Open

I got an exception when try to run on Android #1

reinierkops opened this issue Jan 18, 2024 · 10 comments

Comments

@reinierkops
Copy link

When running the sample project on a physical Android device, I got this error:

`System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'

[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
[mono-rt] ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
[mono-rt] ---> System.TypeInitializationException: The type initializer for 'RiveSharp.Factory' threw an exception.
[mono-rt] ---> System.DllNotFoundException: rive
[mono-rt] at RiveSharp.Factory..cctor() in D:\Projects\rive-maui\src\RiveSharp\Factory.cs:line 22
[mono-rt] --- End of inner exception stack trace ---
[mono-rt] at RiveSharp.Scene..ctor() in D:\Projects\rive-maui\src\RiveSharp\Scene.cs:line 28
[mono-rt] at RiveSharp.Views.RivePlayer..ctor() in D:\Projects\rive-maui\src\RiveSharp.Views.MAUI\RivePlayer.cs:line 169
[mono-rt] at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Constructor(Object obj, IntPtr* args)
[mono-rt] at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
[mono-rt] --- End of inner exception stack trace ---
[mono-rt] at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
[mono-rt] at System.RuntimeType.CreateInstanceMono(Boolean nonPublic, Boolean wrapExceptions)
[mono-rt] at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
[mono-rt] at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)
[mono-rt] at System.Activator.CreateInstance(Type type, Boolean nonPublic)
[mono-rt] at System.Activator.CreateInstance(Type type)
[mono-rt] at Microsoft.Maui.Controls.Xaml.CreateValuesVisitor.Visit(ElementNode node, INode parentNode) in D:\a_work\1\s\src\Controls\src\Xaml\CreateValuesVisitor.cs:line 102
[mono-rt] at Microsoft.Maui.Controls.Xaml.ElementNode.Accept(IXamlNodeVisitor visitor, INode parentNode) in D:\a_work\1\s\src\Controls\src\Xaml\XamlNode.cs:line 159
[mono-rt] at Microsoft.Maui.Controls.Xaml.ElementNode.Accept(IXamlNodeVisitor visitor, INode parentNode) in D:\a_work\1\s\src\Controls\src\Xaml\XamlNode.cs:line 155
[mono-rt] at Microsoft.Maui.Controls.Xaml.RootNode.Accept(IXamlNodeVisitor visitor, INode parentNode) in D:\a_work\1\s\src\Controls\src\Xaml\XamlNode.cs:line 212
[mono-rt] at Microsoft.Maui.Controls.Xaml.XamlLoader.Visit(RootNode rootnode, HydrationContext visitorContext, Boolean useDesignProperties) in D:\a_work\1\s\src\Controls\src\Xaml\XamlLoader.cs:line 207
[mono-rt] at Microsoft.Maui.Controls.Xaml.XamlLoader.Load(Object view, String xaml, Assembly rootAssembly, Boolean useDesignProperties) in D:\a_work\1\s\src\Controls\src\Xaml\XamlLoader.cs:line 78
[mono-rt] at Microsoft.Maui.Controls.Xaml.XamlLoader.Load(Object view, String xaml, Boolean useDesignProperties) in D:\a_work\1\s\src\Controls\src\Xaml\XamlLoader.cs:line 53
[mono-rt] at Microsoft.Maui.Controls.Xaml.XamlLoader.Load(Object view, Type callingType) in D:\a_work\1\s\src\Controls\src\Xaml\XamlLoader.cs:line 49
[mono-rt] at Microsoft.Maui.Controls.Xaml.Extensions.LoadFromXaml[MainPage](MainPage view, Type callingType) in D:\a_work\1\s\src\Controls\src\Xaml\ViewExtensions.cs:line 37
[mono-rt] at Viewer.MainPage.InitializeComponent() in D:\Projects\rive-maui\src\Viewer\Microsoft.Maui.Controls.SourceGen\Microsoft.Maui.Controls.SourceGen.CodeBehindGenerator\MainPage.xaml.sg.cs:line 22
[mono-rt] at Viewer.MainPage..ctor() in D:\Projects\rive-maui\src\Viewer\MainPage.xaml.cs:line 7
[mono-rt] at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Constructor(Object obj, IntPtr* args)
[mono-rt] at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
[mono-rt] --- End of inner exception stack trace ---
[mono-rt] at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
[mono-rt] at System.RuntimeType.CreateInstanceMono(Boolean nonPublic, Boolean wrapExceptions)
[mono-rt] at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
[mono-rt] at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)
[mono-rt] at System.Activator.CreateInstance(Type type, Boolean nonPublic)
[mono-rt] at System.Activator.CreateInstance(Type type)
[mono-rt] at Microsoft.Maui.Controls.ShellContent.<>c__DisplayClass19_0.<Microsoft.Maui.Controls.IShellContentController.GetOrCreateContent>b__0() in D:\a_work\1\s\src\Controls\src\Core\Shell\ShellContent.cs:line 76
[mono-rt] at Microsoft.Maui.Controls.ElementTemplate.CreateContent() in D:\a_work\1\s\src\Controls\src\Core\ElementTemplate.cs:line 86
[mono-rt] at Microsoft.Maui.Controls.Internals.DataTemplateExtensions.CreateContent(DataTemplate self, Object item, BindableObject container) in D:\a_work\1\s\src\Controls\src\Core\DataTemplateExtensions.cs:line 23
[mono-rt] at Microsoft.Maui.Controls.ShellContent.Microsoft.Maui.Controls.IShellContentController.GetOrCreateContent() in D:\a_work\1\s\src\Controls\src\Core\Shell\ShellContent.cs:line 81
[mono-rt] at Microsoft.Maui.Controls.Platform.Compatibility.ShellSectionRenderer.OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) in D:\a_work\1\s\src\Controls\src\Core\Compatibility\Handlers\Shell\Android\ShellSectionRenderer.cs:line 124
[mono-rt] at AndroidX.Fragment.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_(IntPtr jnienv, IntPtr native__this, IntPtr native_inflater, IntPtr native_container, IntPtr native_savedInstanceState) in C:\a_work\1\s\generated\androidx.fragment.fragment\obj\Release
et6.0-android\generated\src\AndroidX.Fragment.App.Fragment.cs:line 2031
[mono-rt] at Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPLLL_L(_JniMarshal_PPLLL_L callback, IntPtr jnienv, IntPtr klazz, IntPtr p0, IntPtr p1, IntPtr p2) in /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:line 367`

Windows is running fine (after manualy copy the rive.dll to the AnyCPU folder (which I get an error on):
image

@hansmbakker
Copy link

hansmbakker commented Mar 15, 2024

Android will need its own library file I guess.

I tried including the .so files from the Android library (https://repo1.maven.org/maven2/app/rive/rive-android/9.2.2/rive-android-9.2.2.aar) using the AndroidNativeLibrary build action (note: librive-android.so would need to be renamed to rive.so), but that doesn't work since that binary misses RiveSharpInterop.cpp.

I asked the Rive developers to publish a nuget package that supports more platforms than only win10.

@hansmbakker
Copy link

hansmbakker commented Mar 15, 2024

What I tried further:

  1. Install the Mobile development using c++ workload and Clang / LLVM components in Visual Studio
  2. restore submodule
  3. download and put premake5.exe in native folder
  4. run .\premake5.exe --os=android vs2022 from the native folder

    ⚠️ by default it will generate a project using Clang, and I don't know if that will work. It is possible to select different compilers using CLI parameters but I didn't try that since the rive-sharp says that Clang/LLVM features are being used.

  5. Optional: there is an updated file upstream at https://github.com/rive-app/rive-sharp/blob/main/native/RiveSharpInterop.cpp
  6. When trying to use Clang, I believe you need to modify 37-41 to be (clang doesn't use __declspec(dllexport)):
    #ifdef WINDOWS
    #define RIVE_DLL(RET) extern "C" __declspec(dllexport) RET __cdecl
    #else // WASM / ANDROID
    #define RIVE_DLL(RET) extern "C" __attribute__((visibility("default"))) RET __cdecl
    #endif
  7. open RiveSharpSample.sln
  8. disable all TargetFrameworks except net8.0-android for these projects to deal with the point that the rive project now won't build a Windows dll anymore:
  • RiveSharp.Views.MAUI
  • Viewer
  • StateMachineInputs

When trying to build the rive project in this solution, I now get these errors:

Build started at 00:55...
1>------ Build started: Project: rive, Configuration: Debug x64 ------
1>ANDROID_HOME=C:\Program Files (x86)\Android\android-sdk
1>ANDROID_SDK_ROOT=C:\Program Files (x86)\Android\android-sdk
1>ANT_HOME=
1>JAVA_HOME=C:\Program Files\Android\jdk\jdk-8.0.302.8-hotspot\jdk8u302-b08
1>NDK_ROOT=C:\\Microsoft\AndroidNDK\android-ndk-r23c
1>ld: error: obj/x64/Debug\animation_state.o: unable to find library from dependent library specifier: msvcrtd
1>ld: error: obj/x64/Debug\animation_state.o: unable to find library from dependent library specifier: oldnames
1>ld: error: obj/x64/Debug\animation_state_instance.o: unable to find library from dependent library specifier: msvcrtd
1>ld: error: obj/x64/Debug\animation_state_instance.o: unable to find library from dependent library specifier: oldnames
1>ld: error: obj/x64/Debug\blend_animation.o: unable to find library from dependent library specifier: msvcrtd
1>ld: error: obj/x64/Debug\blend_animation.o: unable to find library from dependent library specifier: oldnames
1>ld: error: obj/x64/Debug\blend_animation_1d.o: unable to find library from dependent library specifier: msvcrtd
1>ld: error: obj/x64/Debug\blend_animation_1d.o: unable to find library from dependent library specifier: oldnames
1>ld: error: obj/x64/Debug\blend_animation_direct.o: unable to find library from dependent library specifier: msvcrtd
1>ld: error: obj/x64/Debug\blend_animation_direct.o: unable to find library from dependent library specifier: oldnames
1>ld: error: obj/x64/Debug\blend_state.o: unable to find library from dependent library specifier: msvcrtd
1>ld: error: obj/x64/Debug\blend_state.o: unable to find library from dependent library specifier: oldnames
1>ld: error: obj/x64/Debug\blend_state_1d.o: unable to find library from dependent library specifier: msvcrtd
1>ld: error: obj/x64/Debug\blend_state_1d.o: unable to find library from dependent library specifier: oldnames
1>ld: error: obj/x64/Debug\blend_state_1d_instance.o: unable to find library from dependent library specifier: msvcrtd
1>ld: error: obj/x64/Debug\blend_state_1d_instance.o: unable to find library from dependent library specifier: oldnames
1>ld: error: obj/x64/Debug\blend_state_direct.o: unable to find library from dependent library specifier: msvcrtd
1>ld: error: obj/x64/Debug\blend_state_direct.o: unable to find library from dependent library specifier: oldnames
1>ld: error: obj/x64/Debug\blend_state_direct_instance.o: unable to find library from dependent library specifier: msvcrtd
1>ld: error: obj/x64/Debug\blend_state_direct_instance.o: unable to find library from dependent library specifier: oldnames
1>ld: error: too many errors emitted, stopping now (use -error-limit=0 to see all errors)
1>clang: error: linker command failed with exit code 1 (use -v to see invocation)
1>C:\Program Files\Microsoft Visual Studio\2022\Preview\MSBuild\Microsoft\VC\v170\Application Type\Android\3.0\Android.Common.targets(125,5): error MSB6006: "clang.exe" exited with code 1.
1>Done building project "rive.vcxproj" -- FAILED.

I was surprised to see it was asking for these msvcrtd and oldnames libraries and was not sure where to get them from. I thought it was more part of Microsoft's c++ build system and was not sure why clang would need them.

Please note - c++ and its ecosystem and different compilers are not my experience area, probably somebody else can better investigate this.

The readme from rive-sharp says that llvm/clang is the required compiler though.

@matmork
Copy link

matmork commented Apr 6, 2024

For iOS and Android I suggest creating a binding project for the runtimes of each platform
https://learn.microsoft.com/en-us/xamarin/ios/platform/binding-swift/walkthrough
https://learn.microsoft.com/en-us/xamarin/android/platform/binding-java-library/binding-an-aar

Here is a very basic starting point
https://github.com/Matmork/Rive-Maui

Note: Only iOS is showing the animation. Android is pretty close, some problems adding/displaying view. Maybe you can figure it out.

ios.mp4

@hansmbakker
Copy link

@matmork cool that you're experimenting with this!

I saw you only included the Rive AAR for android and I believe that had dependencies on other libraries like Volley (not sure why it would need to call REST APIs though).
Did you get any missing dependencies errors or were those other errors?

@matmork
Copy link

matmork commented Apr 6, 2024

You are right, there were some missing dependencies. Added them to Rive.Android. Guess it needs Volley for fetching .riv files from url.

It's building and running, but I can't confirm if it's working or not. As mentioned I am having some problems adding a view/updating the content inside Maui's ContentViewHandler. I even tried just adding a red box, but nothing is showing.. I don't have the most experience with Android so I am pretty sure I am missing something. Or another approach is needed. See RiveViewHandler.cs PlatformView.AddView()

@matmork
Copy link

matmork commented Apr 7, 2024

Changed to a ViewRenderer instead of ContentViewHandler. Can confirm its working

android.mp4

@hansmbakker
Copy link

@matmork wow, well done!

If you want to discuss further - let's create a discussion or issue at https://github.com/Matmork/Rive-Maui - to keep this issue related to the code in https://github.com/jsuarezruiz/rive-maui?

@matmork
Copy link

matmork commented Apr 7, 2024

Sounds good. Would like to create a PR to add the bindings here but I am unsure how to structure the solution.
There is still work to be done like exposing apis for events, state machine, dartboard etc. But it's a start!

@hansmbakker
Copy link

Would like to create a PR to add the bindings here

Currently the RivePlayer class in this repo directly inherits from SKCanvasView instead of just defining an API with bindable properties and methods, and putting the logic in handlers (as described in https://learn.microsoft.com/en-us/dotnet/maui/user-interface/handlers/create?view=net-maui-8.0).

If you want to have these two codebases merged, then there needs to be

  • a common class like RivePlayer or your RiveView as an entry point, that does not mandate a certain implementation (currently it mandates SKCanvasView)
  • probably some platform-independent classes for the State machine input
  • the platform-specific code for the various implementations

From a technical point I'm wondering what approach would have a better performance and smaller filesize - directly embedding the compiled C library, or binding the Android / iOS libraries with their own references?
However, I think the Flutter library also builds upon the Android / iOS libraries instead of building its own from the C-code.

I tried compiling the C library, and as an outsider not used to the C ecosystem and that premake5 build system I found it a huge barrier :-/

@matmork
Copy link

matmork commented Apr 8, 2024

Seeing the two approaches are so different I agree it's best to keep them separate. Performance and file size is probably better by embedding. Flutter is built upon skia/impeller so maybe they are hooking into that but I see the rive-react-native is also just wrapping the native runtimes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants