Using 3rd Party shared library on Android with NDK with Untiy3D - android

I am trying to make an Android Plugin which uses FMOD for Android, using the NDK (I need this to be native because I am also using a third party open-source C++ library that needs to interact with FMOD, which works fine).
I am able to compile everything with the NDK OK, but when I create my Unity project, I always get a DLLNotFoundException if I am using the FMOD shared lib.
Note that the shared library that I created works fine if I do not include any FMOD calls, so I am pretty sure that the Unity player cannot find the FMOD shared libs.
This is my plugins code:
extern "C" {
#endif
static int mycount = 0;
int FooTest(){
unsigned int version;
FMOD::System* system_;
//Init
FMOD_RESULT result = FMOD::System_Create(&system_);
if (result != FMOD_OK) return -1;
result = system_->getVersion(&version);
if (result != FMOD_OK) return -1;
if (version < FMOD_VERSION)
{
//printf("Error! You are using an old version of FMOD %08x. This program requires %08x\n", version, FMOD_VERSION);
return -1;
}
result = system_->init(32, FMOD_INIT_NORMAL, 0);
if (result != FMOD_OK) return -1;
return mycount++;
}
#ifdef __cplusplus
}
#endif
If I comment out all the FMOD stuff, the returned count is incremented and shown on screen. Whenever I build with the FMOD calls, I get the "DLLNotFoundException:FooTest"
I included the fmodex.so and fmodexL.so libraries both in my plugins/android directory and in the root of my project, and I have checked that they are present in the lib/armeabi folder of the generated APK.
If anyone is interested I can also post the Android makefiles I use to generate my shared library.

The .so libs must be included in the root directory of the project for them to be found.

Related

How to add/use GStreamer binary library with Qt C++ on Android?

I am attempting to use Gstreamer library on multiple platforms with my Qt project (for audio only). I already have it working on macOS with the binary files available online by just adding the framework to my .pro file:
LIBS += -F$$PWD/macOS/libs/ -framework GStreamer
INCLUDEPATH += $$PWD/macOS/libs/GStreamer.framework/Versions/1.0/Headers
DEPENDPATH += $$PWD/macOS/libs/GStreamer.framework/Versions/1.0/include
But now I want to use the binaries available at the same page for android. But because it is not "bundled" in a framework like on OS X I can't add it as easily. Furthermore the official explanations are made for a gradle build (which I don't know anything and don't use in Qt creator) and for use in Java. But, because I want to directly use the C API in Qt C++ I don't need JNI, and would like to directly use the library in my app like on OSX.
Thus, I tried to add the library like I would do it on any other linux, but recursively, since there is a multitude of library and header folders:
contains(ANDROID_TARGET_ARCH,arm64-v8a) {
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
GSTREAMER_INCLUDE_FILES = $$files($$PWD/android/libs/gstreamer/arm64/include/*, true)
for(FILE, GSTREAMER_INCLUDE_FILES) {
BASEDIR = $$dirname(FILE)
if(!contains(INCLUDEPATH, $$BASEDIR)){
INCLUDEPATH += $$BASEDIR
}
}
GSTREAMER_DEPEND_FILES = $$files($$PWD/android/libs/gstreamer/arm64/include/*, true)
for(FILE, GSTREAMER_INCLUDE_FILES) {
BASEDIR_DEP = $$dirname(FILE)
if(!contains(DEPENDPATH, $$BASEDIR_DEP)){
DEPENDPATH += $$BASEDIR_DEP
}
}
GSTREAMER_LIB_FILES = $$files($$PWD/android/libs/gstreamer/arm64/lib/*.a, true)
for(FILE, GSTREAMER_LIB_FILES) {
BASENAME = $$basename(FILE)
LIBS += -l$$replace(BASENAME,\.a,)
}
}
But when I try the include
#include <gst/gst.h>
, it doesn't work and output 37 errors on unknown members of the global namespace related to time management like :
/Users/user/Library/Android/sdk/ndk/19.2.5345600/sources/cxx-stl/llvm-libc++/include/ctime:70:9: error: no member named 'asctime' in the global namespace
using ::asctime;
~~^
I really don't know how to use gstreamer and bundle it for android from the available official binaries and don't want to use any wrapper like qt-gstreamer (which isn't maintained by the way) or JNI.
Thanks for any help or input !

DllImport - DllNotFoundException with android .so

It's the first time I try to create a library c++ for Android/iOS.
I'm using Visual Studio 2015 - Xamarin.
First I created a project : Visual C++ -> Cross Platform -> Shared Library. In the hared library, I created 2 files.
SayHello.h :
#pragma once
#include <string.h>
class SayHello {
public:
SayHello();
~SayHello();
static char* Hello();
};
SayHello.cpp :
#include "SayHello.h"
extern "C"
{
SayHello::SayHello(){}
SayHello::~SayHello(){}
char * SayHello::Hello()
{
return "Hello !";
}
}
Then I generated a file libSayHello.so and created a project Android with xamarin to try to call the function hello.
There is my MainActivity.cs :
[DllImport("libSayHello.so")]
static extern String Hello();
protected override void OnCreate(Bundle bundle)
{
// I paste only my added code :
String hello = Hello();
Toast.MakeText(this.ApplicationContext, hello, ToastLength.Long);
}
I did all steps in this tutorial, but I have an exception :
System.DllNotFoundException: libSayHello.so
I searched for this, but I must be so noob cause I did not find anything. How should I use my libSayHello.so ?
EDIT:
There is my libSayHello.so seen with 7zip:
And my project :
I think this will be the best sample for you.
This all works according to the following scheme:
Android supports 7 CPU architectures.
But Xamarin supports 5 of them. So in the settings of your Xamarin.Android project check which architectures you will support:
[Xamarin.Droid.project]->[Properties]->[Android Options]->[Advanced]->[Supported architectures]
Check which archs are necessary for your project. According to this your shared library should be compiled for these archs. And you should put your shared libraries in Xamarin.Droid.project's folder lib:
To see them in Solution Explorer you should mention them in your Xamarin.Android project's .CSPROJ.
Add there next item groups:
<ItemGroup>
<AndroidNativeLibrary Include="lib\{ARCH}\libCLib.so">
<Abi>{ARCH}</Abi>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</AndroidNativeLibrary>
</ItemGroup>
{ARCH} could be next: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64.
Now you can put DllImport in your code:
[DllImport("libCLib", EntryPoint = "clib_add")]
public static extern int Add(int left, int right);
I think you have to tell about entry point, because i had runtime errors without this statement System.EntryPointNotFoundException.
And don't forget to add next in your code:
using System.Runtime.InteropServices;
Confirm the library is put in "/lib/{arch}/" folder.
Try [DllImport("SayHello")]. the engine may add "lib" and ".so" automatically.

Import a .so lib in Unity that is created on Visual Studio 2015

I have to write a dynamic shared library for android (.so) and use it in Unity. I tried using the .so file that is exported from Android Studio when coding with JNI but Unity can't read the library.
using UnityEngine;
using System.Runtime.InteropServices;
public class ShareApp : MonoBehaviour {
int cntr=0;
#if UNITY_ANDROID
[DllImport("SharedObject2")]
private static extern int getFrameNumber();
#endif
...
}
the error message Unity returns is:
DllNotFoundException: SharedObject2
while the name of the library in unity's Assets/Plugins is libSharedObject2.so.
I tried building the library with Visual Studio 2015, using the cross platform Dynamic shared library (Android) option for a new project. Results are the same. The .so file is built but unity fails to read it.
The .cpp file I use to built the .so file contains just this:
extern "C"
{
int getFrameNumber()
{
return 5;
}
}
Can anyone please point me to a direction?

Android NDK - JNI - HAL

On Android NDK project we need to access bluetooth using a HAL interface. Our intention is to do something like this:
#include <hardware/hardware.h>
#include <hardware/bluetooth.h>
....
void load_Module(....)
{
hw_module_t* module;
hw_device_t* device;
bdt_log("Loading HAL lib + extensions");
err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0){
err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
if (err == 0) {
bt_device = (bluetooth_device_t *)device;
sBtInterface = bt_device->get_bluetooth_interface();
}
}
}
Everybody seems to do the same (in google example code). There appears to be a problem when we try to compile:
#include <hardware/hardware.h> no such file
We properly added a permission to manifest and properly added libraries at Android.mk
Do we need to add something more? Is there a working project that I can refer to?
You're trying to use libhardware on Android NDK project. libhardware is a part of Android framework, not a part of NDK.
https://github.com/android/platform_hardware_libhardware
So your project doesn't have true binary compatibility of Android if you can build your project with libhardware. It would work on some devices, some versions, but no guarantee.
From my experience, I believe you can build your code on AOSP. You need to modify Android.mk for AOSP not NDK.

Build an android apk from Unity3d project working with C/C++ dll

I made a Unity3d project working with C/C++ Dll.
So first I made the dll in Visual studio.
// mydll.cpp
#define EXPORT_API __declspec(dllexport)
extern "C" {
int EXPORT_API add(int a, int b)
{
return a+b;
}
}
And I added this dll into my Unity3D project and called
// C# script in Unity3D
public class TestDll : MonoBehaviour {
[DllImport("mydll")]
private static extern int add (int a, int b);
void Start() {
int a = add (100, 200);
}
}
This code works well and I got the correct result in Unity3D editor.
So I built this project to android platform and got an apk.
I installed and run this apk on my android device but the app doesn't work.
The app didn't run the Dll function.
Whats the matter? I tried to find out the solution in Google and here, but didn't get anything, yet.
Please help me.
Thanks.
Your dll must be in Plugins folder for Windows, it can work for Editor too. for Android you must replace in Plugins/Android folder. Build and write me ok
LearnCocos2D's comment is accurate.
To get Unity to DllImport() a shared library on Android, you must use an NDK compiler and specify a compile config for your target Android platform. Moreover, Unity requires you to specify the architecture of the Android platform in the build settings, eg.. "arm v7" vs "arm64".
As an aside, in Unity 2019.4 - selecting "Load on Startup" in the inspector page of my .so elicits a "DLLNotFoundException".
Overview of this: https://docs.unity3d.com/2019.4/Documentation/Manual/AndroidNativePlugins.html
NDK's CMake guide for getting you started on compiling correctly: https://developer.android.com/ndk/guides/cmake

Categories

Resources