Load the .so file in Xamarin.Android
I’m trying to convert a Java class to C# in Xamarin.Android.
The original Java class looked like this:
private native boolean OpenDeviceCtx(Object obj);
public native boolean CloseDevice();
public native boolean GetDiodesStatus(byte[] bArr);
public native boolean GetFrame(byte[] bArr);
public native boolean GetImage(int i, byte[] bArr);
public native boolean GetImage2(int i, byte[] bArr);
public native boolean GetImageByVariableDose(int i, byte[] bArr);
public native boolean GetImageSize();
public native boolean GetInterfaces(byte[] bArr);
public native String GetVersionInfo();
public native boolean IsFingerPresent();
public native boolean OpenDevice();
public native boolean OpenDeviceOnInterface(int i);
public native boolean Restore7Bytes(byte[] bArr);
public native boolean RestoreSecret7Bytes(byte[] bArr, byte[] bArr2);
public native boolean Save7Bytes(byte[] bArr);
public native boolean SaveSecret7Bytes(byte[] bArr, byte[] bArr2);
public native boolean SetDiodesStatus(int i, int i2);
public native boolean SetGlobalSyncDir(String str);
public native boolean SetLogOptions(int i, int i2);
public native boolean SetNewAuthorizationCode(byte[] bArr);
public native boolean SetOptions(int i, int i2);
static {
System.loadLibrary("usb-1.0");
System.loadLibrary("ftrScanAPI");
System.loadLibrary("ftrScanApiAndroidJni");
}
I think this “native” approach is a method in the .so library. Am I right?
So in order to load these libraries into my Xamarin.Android project, I tried to do just that:
[DllImport("usb-1.0")]
public static extern int GetUSB();
[DllImport("ftrScanAPI")]
public static extern int GetScanAPI();
[DllImport("ftrScanApiAndroidJni")]
public static extern int GetScanAPIAndroidJNI();
And created a folder structure in my project, such as: project/lib/arm/files.so
When I run this project, I get a lot of errors :
DllImport attempting to load: 'usb-1.0'.
DllImport error loading library '/storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0': 'dlopen failed: library "/data/app/ RDScanFingerprint.RDScanFingerprint-1/lib/arm//storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0" not found'.
DllImport error loading library '/storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0.so': 'dlopen failed: library "/data/app/ RDScanFingerprint.RDScanFingerprint-1/lib/arm//storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0.so" not found'.
DllImport error loading library '/system/lib/libusb-1.0': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm//system/lib/libusb-1.0" not found'.
DllImport error loading library '/system/lib/libusb-1.0.so': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm//system/lib/libusb-1.0.so" not found'.
DllImport error loading library 'libusb-1.0': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/libusb-1.0" not found'.
DllImport error loading library 'libusb-1.0.so': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/libusb-1.0.so" not found'.
DllImport error loading library 'usb-1.0': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/usb-1.0" not found'.
DllImport error loading library '/storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0': 'dlopen failed: library "/data/app/ RDScanFingerprint.RDScanFingerprint-1/lib/arm//storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0" not found'.
DllImport error loading library '/storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0.so': 'dlopen failed: library "/data/app/ RDScanFingerprint.RDScanFingerprint-1/lib/arm//storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0.so" not found'.
DllImport error loading library '/system/lib/libusb-1.0': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm//system/lib/libusb-1.0" not found'.
DllImport error loading library '/system/lib/libusb-1.0.so': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm//system/lib/libusb-1.0.so" not found'.
DllImport error loading library 'libusb-1.0': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/libusb-1.0" not found'.
DllImport error loading library 'libusb-1.0.so': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/libusb-1.0.so" not found'.
DllImport error loading library 'libusb-1.0': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/libusb-1.0" not found'.
DllImport unable to load library 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/libusb-1.0" not found'.
DllImport attempting to load: 'usb-1.0'.
DllImport error loading library '/storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0': 'dlopen failed: library "/data/app/ RDScanFingerprint.RDScanFingerprint-1/lib/arm//storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0" not found'.
DllImport error loading library '/storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0.so': 'dlopen failed: library "/data/app/ RDScanFingerprint.RDScanFingerprint-1/lib/arm//storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0.so" not found'.
DllImport error loading library '/system/lib/libusb-1.0': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm//system/lib/libusb-1.0" not found'.
DllImport error loading library '/system/lib/libusb-1.0.so': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm//system/lib/libusb-1.0.so" not found'.
DllImport error loading library 'libusb-1.0': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/libusb-1.0" not found'.
DllImport error loading library 'libusb-1.0.so': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/libusb-1.0.so" not found'.
DllImport error loading library 'usb-1.0': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/usb-1.0" not found'.
DllImport error loading library '/storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0': 'dlopen failed: library "/data/app/ RDScanFingerprint.RDScanFingerprint-1/lib/arm//storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0" not found'.
DllImport error loading library '/storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0.so': 'dlopen failed: library "/data/app/ RDScanFingerprint.RDScanFingerprint-1/lib/arm//storage/emulated/0/Android/data/RDScanFingerprint.RDScanFingerprint/files/.__override__/libusb-1.0.so" not found'.
DllImport error loading library '/system/lib/libusb-1.0': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm//system/lib/libusb-1.0" not found'.
DllImport error loading library '/system/lib/libusb-1.0.so': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm//system/lib/libusb-1.0.so" not found'.
DllImport error loading library 'libusb-1.0': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/libusb-1.0" not found'.
DllImport error loading library 'libusb-1.0.so': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/libusb-1.0.so" not found'.
DllImport error loading library 'libusb-1.0': 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/libusb-1.0" not found'.
DllImport unable to load library 'dlopen failed: library "/data/app/RDScanFingerprint.RDScanFingerprint-1/lib/arm/libusb-1.0" not found'.
Know what I’m doing wrong?
Solution
If you are
using Visual Studio and you are porting some JNI-Java code that is already running on Android to Xamarin, follow these steps:
- Place your .so file under the “lib” folder of your Xamarin project, for example:
Make sure your .so file has “Build Action” set to “Android Native Library”
In C#-Xamarin, you can load your libraries in the following ways
try { JavaSystem.LoadLibrary("SDL2"); JavaSystem.LoadLibrary("glib-2.0"); JavaSystem.LoadLibrary("gthread-2.0"); JavaSystem.LoadLibrary("fluidsynth"); JavaSystem.LoadLibrary("sdl_mixer"); JavaSystem.LoadLibrary("initmixer"); } catch (UnsatisfiedLinkError e) { return e.Message; }
Local methods in C# must be declared as follows:
[DllImport("initmixer", EntryPoint = "Java_sf2Tools_FluidsynthJNI_loadSong")] public static extern int loadSong(IntPtr env, IntPtr thiz, IntPtr songPath, int miliseconds); [DllImport("initmixer", EntryPoint = "Java_sf2Tools_FluidsynthJNI_isPlaying")] public static extern int isPlaying(); [DllImport("initmixer", EntryPoint = "Java_sf2Tools_FluidsynthJNI_pauseAudio")] public static extern void pauseAudio(); [DllImport("initmixer", EntryPoint = "Java_sf2Tools_FluidsynthJNI_resumeAudio")] public static extern void resumeAudio(); [DllImport("initmixer", EntryPoint = "Java_sf2Tools_FluidsynthJNI_stopAudio")] public static extern void stopAudio(); [DllImport("initmixer", EntryPoint = "Java_sf2Tools_FluidsynthJNI_setSoundfonts")] public static extern void setSoundfonts(IntPtr env, IntPtr thiz, IntPtr js);
In the EntryPoint field, you must have the function names exactly as they are in your C/C++ code, usually Java_your_package_name_YourClassName_YourMethodName.
For example, here is my raw C++ code:
void Java_sf2Tools_FluidsynthJNI_setSoundfonts(JNIEnv * env, jobject this, jstring js)
{
Some code
}
void Java_sf2Tools_FluidsynthJNI_pauseAudio(JNIEnv * env, jobject this)
{
Some code
}
void Java_sf2Tools_FluidsynthJNI_resumeAudio(JNIEnv * env, jobject this)
{
Some code
}
int Java_sf2Tools_FluidsynthJNI_isPlaying(JNIEnv * env, jobject this)
{
Some code
}
void Java_sf2Tools_FluidsynthJNI_stopAudio(JNIEnv * env, jobject this)
{
Some code
}
int Java_sf2Tools_FluidsynthJNI_loadSong(JNIEnv * env, jobject this, jstring songPath)
{
Some code
}
Or check the usual warnings given to Android Studio to know the full name of your native function:
- In C# Xamarin, sometimes you can’t skip arguments executed in Java, for example: JNIEnv * env or jobject this, you should use IntPtr as the vartype for this parameter. For example, to call the loadSong function, I used the following parameters.
C/C++
void Java_sf2Tools_FluidsynthJNI_setSoundfonts(JNIEnv * env, jobject this, jstring js)
C# Xamarin
fluidsynth.setSoundfonts(JNIEnv.Handle, System.IntPtr.Zero, new Java.Lang.String(getCFGPathFiltered()). Handle);
- Note that C++ parameters that start with “j”, for example: jstring, jint, you cannot use C# string on jstring, for example, you should use :
jstring -> new Java.Lang.String(“sampleString”). Handle -> System.IntPtr
jint -> new Java.Lang.Integer(4). Handle -> System.IntPtr