Including static library archives in Android Studio - android

Usually when including native libraries in Android, shared libraries are used and loaded at runtime via System.load().
In my case, I've got a static library (.a archive) compiled for Android which I want to access in Java-Code.
Is it even possible to access static libraries without the approach of linking it in a shared library and then loading the shared library?
I just found following question linking static library.
The answer is to link the static library into shared library then load the shared library.

Related

How to use *.a library in Android?

I want to use herumi / bls library in my application. I've successfully compiled libraries following his documentation and get a file armeabi-v7a/libbls384_256.a.
As I guess this is not the same with *.so library and I cannot use this library directly in JNI. I guess instead of this I have to create my own native code to import libbls384_256.a. Is it correct way?
There is no problem to use my own C++ code in my project and this part is already pretty described in different manuals. But I have no idea how to import libbls384_256.a to my native code using Android Studio, Gradle and JNI.
How to include *.a library in native code in Android?
Like you say, you should write a shared library that links against the prebuilt static library. The shared library should contain the exported functions that you want to call from Java, and these can in turn call functions in the static library.
If you're using nkdBuild you'd use the PREBUILT_STATIC_LIBRARY rule, and then add the library to the LOCAL_STATIC_LIBRARIES for your shared library. See https://developer.android.com/ndk/guides/prebuilts
If you're using CMake you'd do something like:
add_library(bls384_256 STATIC IMPORTED GLOBAL)
set_target_properties(bls384_256
PROPERTIES
IMPORTED_LOCATION the/path/to/libbls384_256.a
INTERFACE_INCLUDE_DIRECTORIES the/path/to/the/bls384_256/api/headers
)

Can you link static library directly in android application?

I am sorry maybe this is stupid what I am asking, but I have a question about linking static/shared libraries in android.
I am creating a new C++ Native android studio project. After build, I open the apk file, and inside lib the folder there are placed libraries libnative-lib.so for every ABI. Size of APK is 3.580 KB.
But if I change inside CMakeLists.txt to build the native lib like Static lib, so now I got this:
add_library(native-lib
STATIC
native-lib.cpp)
When APK is built, I can not find the static library (libnative-lib.a). There is no lib folder in the apk. Also, the size is 2.836 KB.
Can someone please explain(or give me link for more info about this) where is the library placed in the STATIC build?
And on run I got error if I link static:
No implementation found for java.lang.String com.example.myapplication.MainActivity.stringFromJNI()
You can't use native static libraries directly in Android apps.
Android user space is basically a Java (or more precisely Dalvik VM).
So all user-facing applications must be written in Java or Kotlin (which both compile to Dalvik bytecode).
Static C/C++ libraries must be link in to a C/C++ executable or dynamic library to be used. They can not be loaded directly by Linux or Android.
Since Android app does not have a C/C++ executable in it, the only way to use a static library with an Android app is to link it with a dynamic library (*.so) that can be loaded via Java Native Interface.
Since JNI uses the system loader to load the library, it can only load dynamic libraries, and of those, only ones that export functions with proper naming conventions so they can be matched to a Java class that will be used to call the native code.

Java.Lang.UnsatisfiedLinkError: 'No implementation found for

I'm trying to use OpenCv 4 on Xamarin.Android by Java Binding Template. These are the steps that i've done:
0) I've compiled opencv binaries through cmake and mingw64 to get .jar and .a
I've put the .jar and the static libraries (.a) in Jars forlder of Xamarin Java Binding Template and i've compiled the template.
1.a) .jar Build Action is EmbeddedJar
1.b) libs Build Action is EmbeddedNativeLibrary
I've added a reference to that template in my Xamarin.Android project: the opencv methods were recognized correctly!
But, when i try to execute:
Mat Source = Imgcodecs.Imread(ImagePath, Imgcodecs.ImreadGrayscale);
i get an error:
Java.Lang.UnsatisfiedLinkError: 'No implementation found for long org.opencv.imgcodecs.Imgcodecs.imread_0(java.lang.String, int) (tried Java_org_opencv_imgcodecs_Imgcodecs_imread_10 and Java_org_opencv_imgcodecs_Imgcodecs_imread_10__Ljava_lang_String_2I)'
I think that there could be a missmatch of method name, maybe due to a wrong java parsing.
I've also tried to use shared libries (.so) by loading them through JavaSystem.LoadLibrary("LibraryNameWithoutInitialLib"), but i have the same error :/
Do you know why?
You cannot link static libraries with Xamarin.Android as the Xamarin/Mono NDK-based runtime is a static main entry executable and does not dynamically get built per project. If you do not need to use a .jar/.aar high-level wrapper, then you will need to use runtime shared libraries and define DllImportAttribute entries for the exported functions that you need to call.
Xamarin.Android supports the use of native libraries via the standard PInvoke mechanism.
Using Native Libraries
Use C/C++ libraries with Xamarin
Note: There are numerous OpenCV C# wrappers / DllImport files in open source ( i.e. a github search away 😁)
Note: If you are using a 3rd-party .jar/.aar , make sure that they are using OpenCV shared libraries and thus not requiring a gradle script to link them into an NDK-based Android app.

Hiding symbols from gnustl_static when build with Android NDK

I am building an Android library that contains a native part written using STL that is hidden under Java wrapper. In NDK documentation in a section Static runtimes it is stated that I should use shared runtime to avoid problems with multiple static runtimes, but I want to try using gnustl_static with a flag -fvisibility=hidden set.
The question is, will it solve possible problems or a shared library is the only way out?
No, building with -fvisibility=hidden will not help with the problems created by linking multiple libraries to a static C++ runtime.
Unless you are building gnustl_static yourself, the -fvisibility=hidden flag only applies to your native code which depends on gnustl_static. It won't change how the symbols are exported from gnustl_static.
In addition, if you link two shared libraries–or a shared library and
an executable– against the same static runtime, the final binary image
of each shared library includes a copy of the runtime's code. Having
multiple instances of runtime code is problematic because of
duplication of certain global variables that the runtime uses or
provides internally.
However, linking against a static C++ runtime should work perfectly fine as long as you are only creating one shared library.
This problem does not apply to a project comprising a single shared
library. For example, you can link against stlport_static, and expect
your app to behave correctly. If your project requires several shared
library modules, we recommend that you use the shared library variant
of your C++ runtime.

Difference between static and shared libraries in Android's NDK?

I'm new to Android's NDK and I don't understand the differences between static and shared libraries. What are they, and when would I choose one type over the other?
The term shared library is not a perfect fit regarding Android's NDK, because in many cases the .so libraries aren't actually shared between applications. It's better to classify the libraries that the NDK builds as static and dynamic.
Every Android application is a Java application, and the only entry point for the NDK code is loading it as a dynamic library and call it trough JNI.
Static libraries are an archives of compiled object files. They get bundled in other libraries at build time. Unused portions of code from static libraries are stripped by the NDK to reduce total size.
Dynamic libraries are loaded at runtime from separate files. They can contain static libraries that they are dependent on or load more dynamic libraries.
So what you actually need for Android development is at least one shared library, that will be called from Java code, and linked with it's dependencies as static libraries preferably.
Native shared libraries: The NDK builds these libraries, or .so files, from your native source code.
Native static libraries: The NDK can also build static libraries, or .a files, which you can link against other libraries.
This is according to NDK Documentation
Static libs – all library binaries will be included as part of our executable during the linking process. Thus, we won’t need the libs anymore, but it’ll increase the size of our executable file.
Shared libs – the final executable only has references to the libs, not the code itself. It requires that the environment in which we run our executable has access to all the files of the libs used by our program.

Categories

Resources