DllNotFoundException on Android - android

I'm trying to load shared libraries in Unity. It works on Windows/Editor but not on Android, whatever I do or use for libraries I always get the DllNotFoundException.
I am using lib.so files, those are for 32BIT ARM EABIS, so the cross platform compilation seems to succeed.
my lib.so files are in the Assets/Plugins/Android/libs/armeabis-v7a/ folder.
I tried different syntax for DllImport (assuming the lib is called Plugin, and the files Plugin.dll and libPlugin.so) :
[DllImport("Plugin")] => works for Windows only
[DllImport("libPlugin.so")] => obviously wont work for Windows, but doesn't work for Android either.
If I open the .apk with winrar, libs are in the libs/armeabis-v7a folder.
The smartphone I use for my tests is an OnPlus3 with a armv8 processor.
Anyone managed to sucessfuly load a shared native library on Android ? Any ideas about what I'm doing wrong ?
Thank you
EDIT:
plugin code can be found here : https://github.com/FFmpeg/FFmpeg
C# code can be found here : https://github.com/Ruslan-B/FFmpeg.AutoGen/blob/7e001dde3acaad70ed188b75e686f23574f81388/FFmpeg.AutoGen/FFmpegInvoke.cs
Adding FFmpegInvoke.cs in the Unity Project or generating the FFmpeg.Autogen.dll and adding it to the project gives the same result (dll just makes the Unity Project faster to build).

I noticed few things you are doing wrong:
my lib.so files are in the Asset/Plugins/libs/armeabis-v7a/ folder.
That should be at:
Assets/Plugins/Android/libs/armeabi-v7a
If you have the x86 architecture version of the plugin,you should place them at:
Assets/Plugins/Android/libs/x86
I tried different syntax for DllImport (assuming the lib is called
Plugin, and the files Plugin.dll and libPlugin.so) :
None of those are correct. If the plugin file name is "libPlugin.so", you should use "Plugin" as the name.
Do not include the lib prefix.
Do not include the ".so" postfix.
Again, if the plugin name is "libVideoPlayer.so", you have to use "VideoPlayer". The "lib" and ".so" are removed. Nothing else will work.
One final note for you, for Android C++ plugin, you do not need to export the plugin. For example, DLLExport __declspec(dllexport) is not necessary.
Although, you must put the function name inside "extern "C""

Related

Packaging external .so files into Android .apk files using Gradle

Recently, I ported my existing Android project from an ancient Gradle version to Gradle 6.6 and Android Studio's Gradle plugin 4.0.1. This project uses an external native library (.so file) that gets used in the Java code via JNI. This .so library has a dependency on libc++_shared.so because it is written in C++.
I realized that if I just copy the .so file into the corresponding platform folder (arm64-v8a, armeabi-v7a, x86, x86_64) within the jniLibs Gradle packages it "properly" into my .apk file.
By "properly" I mean that it automatically adds libc++_shared.so, which my library has a dependency on, as well as my own library to the .apk file. In addition, if I additionally set jniDebuggable to true in the build.gradle file it will also add the gdbserver library which is required to be able to attach the native code debugger.
Now, this is exactly what I want. The problem is that I cannot find any documentation that describes this behavior. The best source I could find is this but it does not mention anything about dependencies being packaged automatically. So, I don't know whether that is an officially supported way of doing things.
I suspect that there is a part of Android's Gradle based build process that automatically analyzes the files in the jniLibs folder and acts accordingly. It would be great to know a bit more to be aware what is really going on.
Does anyone have a reference that confirms my above observations or know which Gradle task (or whatever) accomplishes this? It would also be good to know in which Android Gradle plugin version this behavior was introduced.
Edit:
This answer to another SO question led me to the Android source file https://android.googlesource.com/platform/tools/build/+/master/builder/src/main/java/com/android/builder/internal/packaging/Packager.java
which seems to be the code that packages the .so files and gdbserver into the .apk file. But I have no explanation why libc++_shared.so gets packaged as well.

create a nativescript plugin for Android with compiled C files

I'm trying to create a nativescript plugin, following the official documentation here
I created my .aar file and copied it into the platforms/android folder, which is working when I call my plugin class. The problem I'm facing is when I try to call a function that loads a native library, giving me a UnsatisfiedLinkError.
I've already seen these links 1 2 and tried all the options mentioned, but none of them seems to work. Since those links are two years old, I wonder if these methods are now deprecated.
My tns version is 4.1.2 and tns-android is 4.1.3.
I've tried adding the *.so files to the following folders:
platforms/android
platforms/android/libs
platforms/android/libs/armeabi
platforms/android/libs/jni
platforms/android/libs/jni/armeabi
platforms/android/armeabi
platforms/android/jni
platforms/android/jni/armeabi
platforms/android/jniLibs
platforms/android/jniLibs/armeabi
As you can see, I've tried all possible combinations based on the previous posts (my *.so files are for armeabi architecture)
Note that the only case that don't fail as the others is platforms/android/jniLibs/armeabi. While trying this one I got an error telling me that one of the .so files is repeated (merge conflict) when calling tns debug android, the other ones just fail on runtime when I call the function
I believe linker error is totally from your native library. Your call from plugin to native Java class is successful here, Java to C seems to be the issue.
Did you verify whether your native library (.so files) were compiled successfully, may be by importing them in a simple Android app? If it still fails, then it has nothing do with {N} runtime but may be something with NDK compilation.

Android Studio External Native Build Precompiled Headers

I'm porting a project from NDK build to Android Studio.
Currently the project has a precompiled header attached (with NDK build), which speeds up compilation time a lot.
I'm looking for a way to add precompiled header (.pch) to my external native build within Android Studio project. I'm using CMake.
I am in the same situation and I have found several user-made script to do that.
I would recommend this one:
https://github.com/larsch/cmake-precompiled-header
In order to make it work for the latest ndk-tools which uses clang, copy paste the content of this pull request:
https://gist.github.com/leeor/316168500765cf51ae97
into the PrecompiledHeader.cmake file (replace everything in this file, except if you want to keep GCC/ MSVC compatibility, then just you will have to merge the two files which shouldn't be hard).
It should work, except some special CMAKE_CXX_FLAGS that triggers an error in the export_all_flags function, and that I don't know how to fix yet. I'll keep you updated with my progress.

Building android app on Qt using additional library (Assimp)

Hi I am trying to port an OpenGL desktop app to android. I have no knowledge of android development so am depending on Qt Creator to package the app. As part of the setup, I have invoked 'make-standalone-toolchain' script in android ndk with following settings
--platform=android-21
--toolchain=arm-linux-androideabi-4.9
--system=linux-x86_64
Then I used android-cmake and passed it the path of my newly created standalone-toolchain, which created libassimp.so, libassimp.so.3, and libassimp.so.3.1.1(ln) inside my assimp directory tree.
I passed the libassimp.so path to Qt creator project build menu under 'additional libraries'. However, on deploying the app on android, it crashes with error:
dlopen("/data/app/org.qtproject.example.a3dqtquick-2/lib/arm/lib3dqtquick.so", RTLD_LAZY) failed: dlopen failed: could not load library "libassimp.so.3" needed by "lib3dqtquick.so"; caused by library "libassimp.so.3" not found
I can even see the libassimp.so (not libassimp.so.3) file inside the project build directory at
../android-build/libs/armeabi-v7a.
Not sure where to go from here, manually placing libassimp.so.3 at this location does not sort out the problem. Thanks for reading. I will add further info on your feedback . please forgive any info deficiency as this is my first experiment with android.
Following is the deployment-settings.json file
"description": "This file is generated by qmake to be read by androiddeployqt and should not be modified by hand.",
"qt": "/home/ubashir/programs/Qt/5.4/android_armv7",
"sdk": "/home/ubashir/programs/android-sdk-linux",
"sdkBuildToolsRevision": "21.1.2",
"ndk": "/home/ubashir/programs/android-ndk-r10d",
"toolchain-prefix": "arm-linux-androideabi",
"tool-prefix": "arm-linux-androideabi",
"toolchain-version": "4.9",
"ndk-host": "linux-x86_64",
"target-architecture": "armeabi-v7a",
"qml-root-path": "/home/ubashir/code/3dqtquick",
"application-binary": "/home/ubashir/code/3dqtquickAndroid/lib3dqtquick.so"
UPDATE:
I have now tried this.. replace all links to assimp.so.3.1.1 with copies of the latter so now my library libassimp.so.3 is a file instead of link to libassimp.so.3.1.1. I manually added libassimp.so.3 to my project subfolder android/libs/aremabi-v71 --- no good. I confirm that my build directory shows all libassimp files as I manually added them so presumably they are being deployed but the error remains :
failed: dlopen failed: could not load library "libassimp.so.3" needed by "lib3dqtquick.so".
As outlined here http://webmail.dev411.com/p/gg/android-ndk/1386vger6e/use-assimp-c-library-in-ndk-ld-error-obj-local-armeabi-v7a-libassimp-so-incompatible-target-for-use-with-vuforia
I even edited the link.txt file after running cmake on my assimp build directory for android, altering the entry -soname,libassimp.so.3 with -soname,libassimp.so but it still creates libassimp.so.3.1.1 with its two links , i.e., libassimp.so.3 and libassimp.so. So still stuck..
I ran into the same problem with a shared library I built with CMake for and Android project. I found a way to fix it. There might be a cleaner solution if you were more familiar with CMake.
Search through the CMakeLists.txt file(s) for "SOVERSION" and "SET_TARGET_PROPERTIES()"
In the SET_TARGET_PROPERTIES() routine comment out the lines for VERSION and SOVERSION as follows
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES # create *nix style library versions + symbolic links
DEFINE_SYMBOL DSO_EXPORTS
# VERSION ${PROJECT_VERSION}
# SOVERSION ${PROJECT_SOVERSION}
CLEAN_DIRECT_OUTPUT 1 # allow creating static and shared libs without conflicts
OUTPUT_NAME "${PROJECT_NAME}${PROJECT_DLLVERSION}" # avoid conflicts between library and binary target names
)
Then rerun the configure and generate steps in CMake and rebuild the target. This should give you a .so without any version numbers.
I'll suggest you to take a look at the solution I've found to my problem (that is very similar to yours):
libgdal.so android error: could not load library "libgdal.so.1"
Hope this helps.

Building/finding shared libraries from Android source code

I wish to back port the Android RTP APIs introduced in version 3.1(Honeycomb) to earlier versions. I downloaded the source of version 4.0 and found that it these APIs had both java and native code. In order to build the native code with the NDK, certain shared libraries are required.
According the Android.mk file, these are libnativehelper, libcutils, libutils, and libmedia. Though the source of all of these are present in the source code, building them was difficult. Each required many other shared libraries. For eg, libmedia requires these shared libraries: libui, libcutils, libutils, libbinder, libsonivox, libicuuc, libexpat, libcamera_client, libstagefright_foundation, libgui and libdl.
So my question is, is there some way of obtaining the original 4 shared libs? Does it involve building the entire source?
Say I need to build a piece of native code which is going to use standard Android shared libraries such as libutils, libcutlis, libmedia. I would perform following steps:
Install AOSP repository with target version.
Add my source code to appropriate directories under ./frameworks/base. In your case it might be easier to create a separate folder and put proper Android.mk of course.
You might get compile errors if required functions from those standard shared libraries are not present in the previous version.
When you build the code as part of AOSP it will build required libraries and link them for you automatically.
P.S. To accomplish that you're better to use a Linux-based build host.
using cygwin terminal, build native part i.e. jni folder. To build using cygwin, goto jni folder using cygdrive command. Then type ndk-build. After successful completion, shared libraries i.e. .so files will be created in libs folder.
I can understand your problem, you can pull the libraries from /system/lib of device or emulator. But you need a system permission. But you can do it by installing application.
Otherwise build your source code on linux platfor. Building process is very easy, just using 2 or 3 command. First time it is needed long time to build. After that you need very short time to build, it will build only according to the timestamp of modified code.
Please have a look here

Categories

Resources