Using prebuilt shared library (.so) in new project Android - android

How I can do this without compile again the native code and all stuff?

It seems like you are probably doing jni to this library. If that is the case, the java package and class name needs to be encoded in the names of the jni functions, so you would have to do something such as:
Always keep the same name for the java package and class file which actually interfaces to the native library. This does not need to match the main package name for the APK. You may want to make this a sort of wrapper for the native library.
Or you could create a new native library using the new package name which is just a wrapper calling the original library by it's original function names. This will be a bit more complicated to set up than the previous idea.

Create libs/<arch> folder, and put the so file there. Eclipse or ant build system will automatically pick it up and package in apk file.
In place of <arch> use one of armeabi, armeabi-v7a, x86 or mips - depending on how .so file has been built.

Related

Bazel: prevent android_binary from creating new jni layer

I have an Android app that uses a java API that wraps a C native lib. I have this working: android_binary (name: "MyLibTest") depends on the API, which is built as android_library (name: "MyLibAndroid") with a dependency on the jni layer (cc_library, name: "mylib_jni"), which depends on the wrapped C lib (cc_library, name "mylib").
I want MyLibAndroid to be responsible for loading the native code using System.loadLibrary("mylib_jni"). The problem is that Bazel is creating a native library for my android_binary app, so instead I have to put System.loadLibrary("MyLibTest") in my app code.
Is there a way to tell Bazel to associate the native jni lib with the android_library rather than the android_binary?
The reason that bazel names the .so the same as the android_binary is that bazel links all the cc_library rules in the dependencies of the android_binary into a single .so file, so it doesn't really work to pick one of the names of the cc_library rules.
One way to handle this is to read the file named nativedeps that Bazel puts at the root of the apk. It will contain the name of the .so file that bazel linked, so you don't have to hardcode the name in your library code.

Qt, Qml and C++ based application porting to Android

I am porting Qt(C++) and qml based app to Android platform. I am not using Qt Creator because of the nature of the project.
I have done compiling the code using ndk and generated all the required .so files for my C++ components. Created the project in Android studios, included the jiniLibs(*.so) files, alos, used Qt provided Activity/Loader/Delegate classes and to write Android app. App loads the "main.so" and application get started. I can see the logs which tells me that its loaded. I have created QGuiApplication object and while creating QmlComponent, I am trying to pass main.qml into QmlComponent instance within main.so but I don't know how to specify the path of main.qml?
I tried qrc:/main.qml, assets:/main.qml but no luck.
NOTE: I placed my main.qml in assets folder. I am not even sure when to put that file while packaging.
Looking for suggestion, how do we specify assets/resource paths inside C++ code.
// QQmlEngine* m_pQmlEngine;
m_pQmlEngine->setBaseUrl("qrc:/qml/");
Qt Android helper classes copy all the assets at /data/data/org.qtproject.example.test/qt-reserved-files/ path but you need to make sure that assets information should be mapped in res/values/libs.xml which has a section

Android Unable to load '.so.1' file

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

How can I separate JNI part from the Android app?

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)

Problem loading pre-built library via Android NDK

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.

Categories

Resources