Android Studio is bundling stubbed library into the APK - android

I am using Android Studio to build a native C++ project. There is a dependency library (let's call it lib.so) which is required to be linked with the JNI library to resolve few of its symbols. However, I do not want this library to be bundled into the APK as this is a stubbed library and to be used only for the linking purpose. A proper lib.so with proper symbol definitions is already present on the Android device where I want to run the built APK.
I am importing the stubbed library lib.so to be linked with JNI library as:
add_library(lib SHARED IMPORTED)
set_target_properties(lib.so PROPERTIES IMPORTED_LOCATION "location_of_lib.so")
add_dependencies(native-jni lib})
target_link_libraries(native-jni lib)
This way the APK compilation is successful but the library is getting bundled into the APK.
I am using AS 4.0.1, NDK r19c, CMake 3.17. The same project used to work as expected, i.e. not bundle the library lib.so with the APK but somehow it started bundling it.
Any leads to debug this issue would be appreciated.

Try to use find_library for that. Put your prebuilt lib.so (bad name at least liba.so) to some path and add it to CMAKE_FIND_ROOT_PATH:
list(APPEND CMAKE_FIND_ROOT_PATH ${PREBUILT_LIBS_DIR}/${ANDROID_PLATFORM}/${ANDROID_ABI}/a)
example how it could look:
~/my-proj/prebuilt-libs/android-28/x86/a/lib/liba.so
Then find library and link it:
find_library(lib-a a)
target_link_libraries(native-jni lib-a)

Related

link dependent android ndk cmake project to main android ndk library project

I have 2 modules in this project: app and libdatacpp
libdatacpp is mainly a C++ project but uses some java code
app is mainly a java project, but uses some c++ code
When building the project, I get c++ linker errors for undefined functions from libdatacpp, because the app project doesn't link libDataCpp.o
In my cmake for app, I am linking against libDataCpp like this:
target_link_libraries(
native-lib
DataCpp)
I also link against the other project in the app module's build.gradle like this:
dependencies {
api project(':libdatacpp')
How can I get the app module to automatically link against my libdatacpp module?
If you intend to provide libdatacpp native library for other AndroidStudio projects through .aar, then you need to use prefab feature.
But if these native library is part of your own project, then I don't see the need to put it in the .aar, just put its stuff (sources and CMakeLists.txt) in a subfolder and add it to build by using add_subdirectory (datacpp) in your main CMake.

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.

Where does an Android app search for shared .so files to load?

To make this a little more complicated I'm loading a native library I've compiled with ndk and cmake into Unity which will be deployed on Android. This was all working fine until I wanted to link another shared library to the library I was building. Now my library fails to load and I believe it is because it can't find the new shared library. I can say that the new shared library works on its own because I'm using it in another NDK project.
I see that Unity copies the new .so library over to the apps install directory and puts it along with my original library in a /data/appname/lib/arm64 directory. I have also tried installing the library in /system/lib64 but no luck. I have compiled my library without the new shared library and it works, and then only modified cmake to add it back in and my library will no longer load. I have also objdump'd it to make sure it is x64 as well as exported the symbols in case it was corrupted. So I'm wondering, is there a way to find out where my library file is looking?
This is how I include the new shared library in my CmakeList.txt
add_library(libusb SHARED IMPORTED)
set_target_properties(libusb PROPERTIES IMPORTED_LOCATION D:/projects/arm64-v8a/libusb1.0.so)
where D:\projects\arm64-v8a is the location of the library file on my build machine. I wonder if this is screwing things up. But I use the same syntax in my Android studio Cmake project and I can access the library but I'm sure that's different somehow. Any help is always appreciated.
Thank you
The imported library may have its own dependencies, which must also be copied to your APK (or AAR). To check this, run objdump -p libusb1.so | findstr "NEEDED".
It will look in the lib/[platform-abi] directory of your app. But there is a list of steps for using prebuilt libraries:
https://developer.android.com/ndk/guides/prebuilts
Have you checked those?

Equivalent of 'compileOnly' in Android.mk

I have a pre-built java library as a compile time dependency for Android library project(AAR). So while building it in Android Studio, 'compileOnly' is used so that the same gets linked in runtime when deployed with an APK.
However, I should also write an equivalent Android.mk for the library project. I am not able to find any reference to include a prebuilt java library in Android.mk. Can someone help me on this part.
I tried using LOCAL_PREBUILT_JAVA_LIBRARIES attribute, but the system threw an error:
error: dont use LOCAL_PREBUILT_JAVA_LIBRARIES anymore LOCAL_PATH=xxx.
This kind of dependency linking may look strange. Let me give some insight into it also. Basically I am building an application that has one small part being developed by a third party. The setter interface APIs for the third party are shipped in by me in the form of a .jar file so that they use the same as a compile time dependency and build an AAR out of it.
Now the third party project is to be included in my project build(AOSP). This brings a dependency that their module should be compiled for the AAR to get generated and my project uses that AAR to generate the APK.
For the AAR to get compiled and built, I need to link the prebuilt java interface library that is shipped in by me(mentioned in the first step).
Need an equivalent of 'compileOnly' used in build.gradle.

How do I add a pre-compiled shared library with existing NDK project?

I had a project working fine with the normal gradle using two separate shared libraries. I was including the libraries with the following gradle commands:
sourceSets.main
{
jni.srcDirs = []// This means that ndk-build.cmd needs to be invoked from command line
jniLibs.srcDirs "src/main/libs" //include other libraries
}
I needed to begin compiling one of the two libraries, so I moved to experimental gradle. I got this to work fine for the library that I am building. But, when I go to add the pre-compiled shared library, I am getting a crash for java.lang.UnsatisfiedLinkError: No implementation found for my JNI method. I have not changed the package name or the shared library.
When I run
jar xvf app-release.apk
I see my shared library present in the list of files, so it is being picked up by the APK build. What could be the source of the UnsatisfiedLinkError if the library is in the APK? What are the steps to include a prebuilt .so file into an NDK project. The NDK project code does not call into the extra library, only the java code.
You should load your library manually from java code.
System.loadLibrary("yourlib");
Don't forget to handle exceptions, as loadLibrary can throw one. It's important, because exception message would show you the paths, where it tried to find your shared library. Also be sure, your library was added to your apk. Then, be sure you have your shared library compiled for different ABI, as armeabi library won't work on x86 phone.
Here you can find an example of adding library to your project with gradle-experimental plugin, so it would be added to your apk.

Categories

Resources