I have installed SkiaSharp by adding SkiaSharp.dll and libSkiaSharp.dll from this page’s prepackaged zip to my Assets/Plugin folder and the following line to csc.rsp:
-r:Assets\Plugins\SkiaSharp.dll
This works in Unity Editor on Windows. I can access the SkiaSharp functions/classes. However, when I build to Android and try to run the same functions I get:
2022/12/04 21:01:00.790 19171 19202 Debug Unity Failed to load native plugin: Unable to lookup library path for 'SkiaSharp'.
2022/12/04 21:01:00.798 19171 19202 Error Unity DllNotFoundException: libSkiaSharp assembly:<unknown assembly> type:<unknown type> member:(null)
2022/12/04 21:01:00.798 19171 19202 Error Unity at (wrapper managed-to-native) SkiaSharp.SkiaApi.sk_memorystream_new()
2022/12/04 21:01:00.798 19171 19202 Error Unity at SkiaSharp.SKMemoryStream..ctor () [0x00000] in <d8a986c3a3a54171980f8dabea28fb18>:0
2022/12/04 21:01:00.798 19171 19202 Error Unity at SkiaSharp.SKMemoryStream..ctor (System.Byte[] data) [0x00000] in <d8a986c3a3a54171980f8dabea28fb18>:0
2022/12/04 21:01:00.798 19171 19202 Error Unity at SkiaSharp.SKBitmap.Decode (System.Byte[] buffer) [0x00011] in <d8a986c3a3a54171980f8dabea28fb18>:0
I am not familiar with adding third party plugins like this. Is there any trick to making this work or is SkiaSharp likely incompatible with Android?
Usually you have to have slightly different interop calls (eg, not __Internal but rather the name of the AAB file (which is what I use with Android)).
I’m not sure how it would connect with a DLL however, and it might be different with Mono vs IL2CPP, but nowadays to publish on google play you need IL2CPP anyway.
I can however show you sample code from my KurtMaster2D game which builds for Android and all targets, and hopefully that along with the docs might give you an idea? The interop call declarations look like so:
using System.Runtime.InteropServices;
public static partial class dispatcher1
{
#if UNITY_IOS || UNITY_WEBGL
[DllImport ("__Internal")]
private static extern System.IntPtr dispatcher1_entrypoint1( int opcode1, int arg1);
[DllImport ("__Internal")]
private static extern System.IntPtr dispatcher1_entrypoint2( int opcode2, string arg2);
[DllImport ("__Internal")]
private static extern System.IntPtr dispatcher1_getkpworkbuf();
[DllImport ("__Internal")]
private static extern void dispatcher1_rendercolor(
System.IntPtr pixels, int span, int flags);
#elif UNITY_ANDROID
[DllImport ("vanilib")]
private static extern System.IntPtr dispatcher1_entrypoint1(int opcode1, int arg1);
[DllImport ("vanilib")]
private static extern System.IntPtr dispatcher1_entrypoint2( int opcode2, string arg2);
[DllImport ("vanilib")]
private static extern System.IntPtr dispatcher1_getkpworkbuf ();
[DllImport ("vanilib")]
private static extern void dispatcher1_rendercolor ( System.IntPtr pixels, int span, int flags);
#elif UNITY_STANDALONE_WIN
[DllImport ("libtest1")]
private static extern System.IntPtr dispatcher1_entrypoint1( int opcode1, int arg1);
[DllImport ("libtest1")]
private static extern System.IntPtr dispatcher1_entrypoint2( int opcode2, string arg2);
[DllImport ("libtest1")]
private static extern System.IntPtr dispatcher1_getkpworkbuf();
[DllImport ("libtest1")]
private static extern void dispatcher1_rendercolor( System.IntPtr pixels, int span, int flags);
#elif UNITY_STANDALONE_OSX
[DllImport ("bundletest1")]
private static extern System.IntPtr dispatcher1_entrypoint1( int opcode1, int arg1);
[DllImport ("bundletest1")]
private static extern System.IntPtr dispatcher1_entrypoint2( int opcode2, string arg2);
[DllImport ("bundletest1")]
private static extern System.IntPtr dispatcher1_getkpworkbuf();
[DllImport ("bundletest1")]
private static extern void dispatcher1_rendercolor( System.IntPtr pixels, int span, int flags);
#else
private static System.IntPtr dispatcher1_entrypoint1( int opcode1, int arg1) { return (System.IntPtr)0; }
private static System.IntPtr dispatcher1_entrypoint2( int opcode2, string arg2) { return (System.IntPtr)0; }
private static System.IntPtr dispatcher1_getkpworkbuf() { return (System.IntPtr)0;}
private static void dispatcher1_rendercolor( System.IntPtr pixels, int span, int flags) { }
#endif
}
Thanks, Kurt. I think the problem is the SkiaSharp files from that website were from 2017 and Android support was likely added after. Therefore I need to build new SkiaSharp dll’s. I cloned the github in Visual Studio 2022:
Then I right clicked the SkiaSharp project and through properties set the target build platform to dotnet2.1 which is what I want.
When I build, I get SkiaSharp.dll but no libSkiaSharp.dll. Trying to use SkiaSharp.dll by itself in Unity gives an error looking for libSkiaSharp.dll. As I understand SkiaSharp.dll is the C# code and libSkiaSharp.dll is the C++ code if that makes sense.
But I can’t figure out how to build the libSkiaSharp.dll. The only reference I see is in the project it says:
You will definitely want to start with their forums.
If it is C#, it must be compatible with the C# level Unity supports
If it is C, you might get around building a DLL and instead drop files into Unity in the Plugins/Android folder, which might work, but is generally NOT for the faint of heart.
As I said for my stuff, I built my C/C++ code into an AAR (Android Archive) for integration with Unity, as the interop code above does. It is vanilib-release.aar, which is where the DLLImport decorator name comes from.
BUT… I also could have dropped the C files into Unity directly, which I do nowadays for WebGL on that project.