I am trying to use the .so external library in my Android project. It's not clear to me how can I access the classes in the library once it's loaded via System.load("path to lib")?
The library is already there, and it's already compiled for use on mobile devices.
The loading process does not cause errors.
Due to the specifics of the project, I cannot use .so files from the unpacked apk along the standard path - I need to connect it in the code via System.load("path to lib").
Please, tell me, what is the syntax for referring to classes in a loaded library?
Create method in one of the your class like below
public static native String methodName();
Now you can access classes in cpp file using below syntax
Java_your_package_name_classname_methodName(JNIEnv *env, jclass clazz) {
return something
}
Get your something by calling methodName. Thats it.
for more information refer https://developer.android.com/studio/projects/add-native-code
Android can load arbitrary .so libraries via System.load() that is correct (if the architecture is correct). But that a library can be loaded does not mean you can use it from within your app.
Android bases on Java and Java uses a special system for calling methods in native libraries/.so files: Java Native Interface (JNI).
Based on the Java method name and it's parameters JNI defines the function name and it's parameters in the .so file and exactly this way you have to implement this function. JNI also provides helper functions for converting typical Java types into C types and the other way around.
What does that mean for you:
Assuming the library is not prepared for JNI and you have the source code of the used library you can add the necessary JNI functions yourself.
Otherwise you don't have the source code of the used .so library and the library does not provide the required JNI functions you have to develop your own .so library that acts as a bridge from Java-JNI to the exported functions of the .so file you want to call.
Related
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.
I've been developing a library to use in my project, and while it is working locally, I would like to share it and use it as an external dependency.
How do I wrap my library so that built AAR contains both *.so native library and generated *.java classes (generated by Kotlin compiler) ? Because there are two-way interactions in my library: Kotlin external functions defined in C++, and some C++ code calling Kotlin classes and methods.
So, my questions are:
How to correctly package Kotlin + JNI android library ?
How to upload said package to Bintray so users (and myself) could use it as a dependency ?
(Note: I've seen tutorials and examples, but they were either Kotlin/Android or Java/Jni/Android)
If you want to package .so with your application, note that you can always put it inside JAR file. Then, you can unpack it, and load it using System.load.
You can find sample here: https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo031
Note
Remember that packaging .so inside application is a risky thing. As you deal with native code, you have to be 100% sure that all native dependencies are there. You have to pay attention to architecture as well.
I need to change pitch and time stretching of an audio. For this I am using prebuild static library. Currently I am having libZtxAndroid.a static library and corresponding header file which contains function declaration. But I don't know how to load this library in my android studio app and call native function from java code. I explored many links and tried to load this library. But all attempts are failed. This is the one link which I have tried last time https://tariqzubairy.wordpress.com/2012/03/12/use-of-prebuild-static-library-compiled-with-android-toolchain/
Also I am using FFMPEG shared library and MP4Parser (https://github.com/sannies/mp4parser) library in this app for adding water mark to video and merging audio respectively. Can any one help from basics.
How to load static library?
Where I need to place that static library?
Where I need to create jni folder (folder structure)?
How to call function available in that static library with the help of header file from java code?
You need to do several things:
Compile a dynamic library. This is a .so file in Android.
You can do this with the android ndk.
There is a directory in every android project, I am saying from the top of my head, but I think it is in a jni subdirectory where you must put your library.
You should wrap your library in JNI. Place them as the advice in this other question: JNI folder in Android Studio
If you have something like this in android:
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
where Java_comp_example_hellojni_HelloJni is your project name, you have to do from Java, assuming the name of your lib is libmylib.so:
public class HelloJni {
static {
System.LoadLibrary('mylib');
}
public native stringFromJni();
}
Note that the native library name does not need the lib prefix and the .so suffix. Note also that you do not need any header file from C++, you just load the library from Java and declare a native function. The library should be already compiled and in the right directory before the Java project uses it.
Be careful at loading: if you use the shared version of the standard library, you will also need to add it to your static { section in Java for loading it, before your library.
I'm trying to integrate this specific library to my Android project, and the library is written in C/C++. I've miraculously gotten ndk-build to give me the needed .so file.
However, looking at it, there's a sample in the project, and they use a mysterious .jar with the API bindings of the .c/c++ files.
How do i either
create this special .jar file that has the API, based on the .so?
OR
directly add a method to the main c++ file and then call it from Java?
I've tried to re-wrap things using JNI, but it definitely doesn't seem to work. i keep getting UnsatisfiedLinkError.
A lot of the documentation online uses jni as the tutorial. i'm happy with just a few links to tutorials on JNA.
JNA provides a stub native library, libjnidispatch.so for a variety of platforms. You can build this library yourself, or extract one of the pre-built binaries from the project's lib/native/<platform>.jar packages.
You include libjnidispatch.so in your Android project the way you would any other JNI library. This is required; you cannot rely on JNA to dynamically unpack and use its native library automatically like on other platforms. The JNA project includes details for doing so (as well as instructions for building libjnidispatch.so yourself).
You then use jna.jar as you would any other Java jar file, and write your own (Java) mappings to match the native library you're trying to access. There's also a jna-min.jar which omits all the native platform libraries that are normally bundled in jna.jar.
Do go to project properties and build paths and remove JNA 4.0 and related classes.
This will work!
I am writing an Android application. I am implementing some of the app in C++ using JNI. Is there a way to actually separate completely the JNI (C++) code from the Java Android code? Like creating a JNI project or something ? Because my C++ code will become a little library that I will use in another app. I tried to create a C++ project but I can't compile with ndk-build.
In actuality, the tie-in between the Java and native code is fairly loose, in that it is done by the names of the methods at runtime.
The NDK is just a special environment and libraries for a C compiler. A suitable dynamic library file must be produced, but this can be done using the ndk script, using an ndk generated "stand alone tool chain" or even done before (or after, see later) the java project build, done on another machine, etc.
Normally the .so dynamic library gets copied into the appropriate place in the application project tree such that it will end up packaged in the .apk and installed on the device where it can be automatically found by the System.loadLibrary() method. But you could just insert it into the otherwise finished .apk (which is a zip file with special alignment and jarsigner signatures). But even the .pak is not actually not the only way to deliver it to the device (though it is the only recommended way)- a library can also be stored in a place such as the app's private folder and loaded using System.load() which takes a full pathname instead of a library name.
hotverspicy does have a point that the java code needs a native method "declaration" for what is implemented in the jni library, and that this needs to match the actual package name as encoded in the name of the native function implementation. However, that package name does not have to be the same as the rest of the java code - it could be something generic for the re-usable C/C++ library, which would require only one brief matching java class file in the matching java package name.
But in addition to Neevek's idea of using one native lib to interface to another, it is also likely possible to use an object factory mechanism to hook up arbitrary native functions at runtime, given just one association set up at compile time - see the relevant answer to C/C++ Reflection and JNI - A method for invoking native code which hasn't been written yet
If you use JNI in your C++ code, then it's bound to Android, and it must be an Android project with properly defined Android.mk, Application.mk(optional).
If you don't use JNI API in your code, say you want to create a generic library, you can just write your C++ code, compile it, test it as usual, no ndk-build is needed. When you finish coding with the library, build the code as a static library, and when you want to use this static library in your Android project, write some JNI wrappers around functionalities in the static library that you want to use, link against the static library in your Android.mk, something like this:
include $(CLEAR_VARS)
LOCAL_MODULE := libgeneric
LOCAL_SRC_FILES := prebuilt/libgeneric.a
include $(PREBUILT_STATIC_LIBRARY)