I am attempting to add a third-party library to my Android app. It utilizes a .jar file and a .so file. This is a pre-built .so file (i.e. not built specifically for the Android app) - which I know will provide me with plenty of problems down the road. I do NOT have access to the source files for the .jar or .so files!
I am attempting to dynamically load the library via a call to System.loadLibrary("foo");. Currently, when attempting to run the app, it crashes with the UnsatisfiedLinkError: Library foo not found. I have the .so file in both the libs/ and the libs/armeabi file in my project.
Am I chasing after a ghost here? I am trying to determine if what I'm after is even feasible. I have no native code that I'm referencing - all my function calls are to the .jar file that is, as I understand it, backed by the .so file. I have not run the Android.mk file as I'm not compiling anything - the .so file is already provided. I could really use some advice as to what direction to proceed from here.
It's possible that the base name given to System.loadLibrary() is expanding to a file (or path) name different than that of the actual prebuilt library. Logcat should show you exactly what it is trying to load. You could also use System.load() with a full path/file name instead of System.loadLibrary() - though you really should get it working with the later.
While I think it would generate a different error message, it's also possible that the .so is not android compatible - it must not only be for a compatible processor type and abi, but not depend on any dynamic libraries (such as a non-bionic libc) not installed on the device.
Related
If android installed at below path:
/system/product/priv-app/mynative/app-debug.apk
And this apk contains a jni library:
app-debug/lib/arm64-v8a/libnative-lib.so
Where is the path android to load the library libnative-lib.so? I search device and never find that so file.
The answer might be: "it never was on the filesystem to begin with".
Modern Android build infrastructure sets extractNativeLibraries=false by default. This keeps the .so in the APK instead of having a copy linger on your device.
EDIT: I did some source digging, the Android runtime linker can open libraries directly from zip files if the filename contains !/. I think this would just show up as another mapping of the APK in /proc/pid/maps, but I did not investigate beyond that (eg how relocation is done in this case or what namespaces have to do with it).
Issue
Built APK looks wrong and prevents my application from loading its native library because it cannot find a dependency when calling dlopen(): dlopen failed: library "libboost_filesystem.so.1.68.0" not found.
jniLibs content
My jniLibs directory, for the target platform, contains the following files:
libboost_filesystem.so.1.68.0 is the "real" shared object.
libboost_filesystem.so is a symlink to libboost_filesystem.so.1.68.0
APK Content
After building, the APK contains a libboost_filesystem.so which now is the binary object (not a symlink).
It seems like Android build system followed the symlink, grabbed content of the "pointed-to" file, but used the name of the symlink instead.
I have tried to remove the symlink from the jniLibs folder, but doing that it seems that the xxx.so.VERSION files are then ignored.
Question
How can I embed my "full name" shared object into the jniLibs without the Android build system messing with it ?
No you can't. You should avoid versioning the so file. See https://stackoverflow.com/a/45058227/192373 for instructions.
It's also quite natural that Android does not support this technique, because your native libraries belong to your APK and no version conflict can occur.
Consider linking boost filesystem statically to avoid extra lookup.
Hi I am working on a Android native application.
There is 'abc.so' files which depend on some 'xyz.so.1' file. All of the required files are available in the project structure before building, but the '.so.1' are not a part of the generated .apk file (I checked the apk file by unpacking).
This is causing in a "'java.lang.UnsatisfiedLinkError' Couldnt load 'abc.so.1' from loader dalvik" when trying to run the application.
I dont want to push the .so.1 file as the phone is not rooted and runs on a production build. How do I include the .so.1 files as a part of the APK?
Thank you.
I think you havent got the concept of loading native libraries to Java through JNI.
First you define the native methods in java and do the corresponding implementation in the native and compile it (you have to register the native methods by either 1) following a naming convention 2) registering the native methods in jni_onload...i think you must have done this, if not check http://www.ntu.edu.sg/home/ehchua/programming/android/android_ndk.html)
Next, you have to load the library before any call can be made to native. This has to be done once. You can do it in an activity by defining:
static{
System.loadLibrary("mylib.so");
}
Note while compiling the library you will have got the library name as libXYZ.so, but when loading the library in java the "lib" should be omitted ,just system.loadlibrary(XYZ.so)
If you are using NDK the library would have been already copied to Java project > libs > armeabi folder , if not you have to copy your lib.so there
Now if you have multiple shared libraries , you should load the least dependent lib.so first , followed by second etc i.e.
Static {
System.loadLibrary(independent_lib.so); // should depend on only android libs
System.loadLibrary(next_dependent_lib1.so); //can depend on android libs and independent_lib.so
System.loadLibrary(next_dependent_lib2.so); //can depend on android libs,independent_lib.so,next_dependent_lib1.so
.....
....
..
}
If you jumble up, the VM will not be able to link the libraries and throw a unsatisfied link error.
Lastly, all this .so s will be part of your apk and it will be pushed to the system libs only runtime. Unless its a rooted phone you cannot extract the .so. If you follow the above method you will not need to push any .so to the system. Only build on eclipse/cygwin and run
Hope this helps,
Regards,
Shrish
[RESOLVED]
Finally the problem was that my external lib use external jars. And the content of thoses jars also have to be in the extension jar. For example:
extension.jar have ton contain all the compiled classes of:
externallib.jar
externallib_referencing_external_lib.jar
[/RESOLVED]
First, I've been looking throught this topics
AIR 3 Native Extensions for Android - Can I/How to include 3rd party libraries?
How to include additional Jar in Android Native Extension for Adobe Air Mobile
I got a similar problem. But not exactly the same. And the solution didn't worked for me :(.
First of all, I don't have any visible error.
-I can easily talk between java and action script.
-The gateway is set without problems.
My problem comes when, from my java-side-part of the extension, I try to call a 3rd party library. This library is (and I think this is where I do something wrong) linked to my project as an external lib, in .jar format.
So when I make a call to 3rd party library, it just doesn't print anything. Neither on the adobe part or on the java part. The logs that are before my call are printed but not the ones after.
I tried different solutions that are:
-Taking all compiled class files of my external lib and add it inside the main native extension jar [link1]
same result (no errors)
-including the 3rd party jar inside the ANE by adding a dependence file that require the .jar [link2]
with this method i got this error that I don't get
aapt tool failed:ERROR: input directory '--auto-add-overlay' does not exist
My third party library also include's itself some external .jars so do I need to include every jars inside the same packaged jar?
I can see that a lot of people are dealing with issues like that so my question would be:
What is the best way to include 3rd party library inside android AIR Native Extension ?.
For information, here is what I do to create the ANE
adt -package -target ane AirInfinitGameANE\AirInfinitGame.ane AirInfinitGameASLib\src\extension.xml -swc AirInfinitGameANE\AirInfinitGameASLib.swc -platform Android-ARM -C AirInfinitGameLib .
AirInfinitGameASLib: just the folder with the actionScript part and the config xml file
AirInfinitGameANE: folder in the one that will be the native extension
AirInfinitGameLib: the eclipse java project. I need to put in that folder the airInfinitgamelib.jar(extension jar) and the library.swf (from the swc file) in order to beeing able to compile the ANE.
Here it is ! Thanks a lot for thoses who'll read me.
I'm currently trying to find a solution to have an AIR native extension including a C - library for Android that is using JNI.
So far, I tried to pack the .so lib into a jar, which then is packaged into the ane.
As I learned here, I have to unpack the .so from the .jar first in order to access it.
The code found there seems to be working for a regular android project, unfortunatly when doing this for a .jar which is then packaged into an .ane, it seems to lose scope, resulting in a
FileNotFoundException: File path/to/my/lib was not found inside JAR
I already double and triple checked all paths and the contents of my jar. It's all there and spelled correctly.
Q1: How do I get access to the .so from actionscript?
Q2: Is there any other way to package/address the .so besides the regular extension-jar into the ane?
Q3: I really don't know much about the inner working of the .ane mechanism. Is it also possible to skip the .jar-wrapping and use the .so directly from actionscript?
As always, many thanks for any input.
It becomes a bad habit of me to answer my own questions, but anyway...
Sometimes the docs can help. Here in the adobe docs I finally found the solution.
Simply copying the .so to the libs/armeabi-v7a folder in my ane package directory includes the lib into the ane, so I can use the .so from inside the java code of my extension.
Sorry for bothering.