Linking cross-platform library to native android application - android

The problem:
I have a native Android application that is compiled for x86 and arm, armv7a.
The app also links to a pre-shared library.
That pre-shared library is also compiled for x86, arm, and armv7a. So there are 3 lib.so files.
What must I do in the Android.mk/Application.mk to link to the appropriate *.so file given the architecture it is being compiled for?
That is, when the build system is compiling for arm, it should link to the libs/armeabi/lib.so.
Likewise, when the Build system is compiling for x86, it should use the libs/x86/lib.so file.
I believe the alternative might be a more complex build script but I'm shooting for the simple solution first, if it exists.
Thanks!
The answer
Unfortunately my query skills were not very good and shortly after posting, I found the question and answer already on SO:
How can i Link prebuilt shared Library to Android NDK project?
To summarize:
Prebuilt shared libraries, compiled for different platforms, should all be named the same and go under the jni/${ARCH}/ directory.
That is, the structure should appear as so:
jni/x86/libtest.so
jni/armeabi/libtest.so
jni/armeabi-v7a/libtest.so

You should use the $(TARGET_ARCH_ABI) flag, for example:
include $(CLEAR_VARS)
LOCAL_MODULE := mylib-prebuilt
LOCAL_SRC_FILES := ../path_to_prebuilt_folder/libs/$(TARGET_ARCH_ABI)/libmylib.so
include $(PREBUILT_SHARED_LIBRARY)

Related

Native library not found on android build?

I am getting this error: unable to lookup library path for, native render plugin support disabled when I run my app on android. I think I am building the shared libraries incorrectly.
I am looking to build the source files from this repo. I'll say my build process and perhaps someone can spot a step I'm missing or doing incorrect.
Following this guide, I came up with this:
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libhydrogen
LOCAL_SRC_FILES := ..\hydrogen.c
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_PLATFORM := android-16
APP_OPTIM := release
APP_MODULES := libhydrogen
Next I:
Placed these files in the jni folder.
Called ndk-build.
Copied the .so files from the \libs folder and placed them in their respective folders in Unity (i.e. Hydrogen\Plugins\Android\arm64-v8a).
Made sure their platforms and CPU architectures were correct.
Built my app.
Here is the c# wrapper I am using.
Calling Hydrogen.Library.Initialize(); is then giving me this error.
Here is the full logcat related to this error.
And in the case my build process manages to be correct, and the .so files are fine; what else might cause this to happen?
Edit: I am trying to build for armeabi-v7a and `x86. Here are the .so file details, maybe there is something there that is not right? I am unfamiliar with c and since I haven't heard of anyone building this library for android, I wonder: could there be anything within the c source file that is incompatible with the NDK build process?
Native libraries are loaded by the native linker of the system, in your case, the linux dynamic linker: ld.so (it changes names sometimes, so I used that name, as you can check the man page in the documentation with that name).
For that to happen, in general, you need to provide a LD_LIBRARY_PATH environment variable to the java virtual machine, so it can effectively dlopen(3) it.
Think how different can be your development system to your target one.... and you'll easily get to that.
It was a bug with Unity! For some reason when switching the project's target platform some of my files would get corrupted. Strangely, it only seems to happen in this one project, but in any case the (temporary) solution is to re-import the plugin folder whenever I switch platforms.

Call shared library (.so) methods within Android Studios C files

I'm struggling with this for several days now. At the moment i'm just testing it with a simple C++ project (1 .h & 1 .cpp file) and a minimalistic App including the ndk helloJNI sample code (which worked perfect easily):
Target
Import existing C/C++ files (project) to Android Studio
Approach
After trying out some of the (dozens) of different possibilities, i think/thought the following steps would be the best solution for my purpose:
Create the shared library (Calculator.so) from Visual Studios 2015 "Create shared library for Android" (or something) [successful]
Create jniLibs folder in src/main/ with its subfolders (x86 the relevant one in my case)
Add the Android.mk file in src/main/jniLibs which has to be placed there (?)
Include statement: System.loadLibrary("Calculator") without "lib" and ".so" in MainActivity
The library is listed in Android Studio in its folder jniLibs as like the Android.mk. Moreover if i build the apk, the library is successfully packed (verified by unzipping) and i dont get any errors.
BUT: how can i call the methods in the library? I tried the different solutions offered in other threads, but i think i missed something in my .mk or my steps described above.
Tried
Different #include <myLib> statements in native-lib.cpp, like s
Different Android.mk settings (but i'm new to make files so not even tutorials helped me much with my specific problem ::) )
Other locations for the libCalculator.so like in the subfolder x86
and many others - simply not reminding atm (wasntme)
Your help is highly appreciated!
Android.mk
LOCAL_PATH := $(call my-dir)
APP_ABI := x86
# library info
include $(CLEAR_VARS)
LOCAL_MODULE := Calculator
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/Calculator.so
LOCAL_EXPORT_C_INCLUDES := ..../Visual Studio 2015/Projects/SO_Library/SO_Library
include $(BUILD_SHARED_LIBRARY)
There are lots of things, you can do in Android NDK. For example, Camera hardware is one of the heaviest hardware in Android OS. Detecting faces, things, giving effects and for thousands of features NDK is the best.
Some helps for your steps:
You can built and prebuilt shared(.so) and static(.a) libraries in Android Studio also. Not need Visual Studio.
Don't create jniLibs folder in main folder. When you build your project via gradle, it already creates this folder and put your target libraries. If you want prebuilt any libraries, put these libraries in main/jni/libs folder and prebuilt then with Android.mk.
Don't add the Android.mk file in jnilibs folder. Create this file in main/jni folder. Also Application.mk file.
Call your libraries, in any activity, where you need, in static method. Like this:
static { System.loadLibrary("my_library") }
Without "lib" and ".so" extensions.
When you want to call your native methods, just use "native" keyword. For example:
private native int nGetNumberFromNativeSide();
Just call this method, where you want, and get result. But for ndk building in gradle side, look at this answer. For building library in Android.mk, these sample lines maybe help you:
include $(CLEAR_VARS)
ifneq (,$(filter $(TARGET_ARCH_ABI), armeabi-v7a x86 arm64-v8a x86_64))
LOCAL_MODULE := my_library
LOCAL_SRC_FILES := $(LOCAL_SRC_LOCATION)/native1.cpp native2.cpp
include $(BUILD_SHARED_LIBRARY)
You can put name anything you want, but dont add lib and .so extensions. Ndk is already doing it.
I have already gave Android.mk example.
When you build Android.mk file, it locates your libraries appropriate folder. Like main/libs/x86/libmy_library.so.
I guess this answer will help you. If you have more questions, add to comment, i'll edit my answer and add answers.

How to update OpenSSL version in CSipSimple?

I am using CSipSimple code for my application. But unfortunately, Google Playstore has raised a warning:
You are using a vulnerable version of OpenSSL
I want to update the OpenSSL version from existing code.
Here is some reference which I have followed. CSipSimple-OpenSSL
But I am stuck at step 5 there are no such command
m: command not found
Am I following incorrect steps? If any one have already done with this, then please help me or provide some steps/link.
Any help would be really appreciated
In case someone encounters the problem of using vulnerable version of OpenSSL in one of the native libraries, I add some more details and instructions for the #Nonos solution. This tutorial is for CSipSimple but building OpenSSL static libraries is a more generic solution.
I recommend the second solution as adding a static OpenSSL library is more simple solution.
Preconditions: Android NDK need to be configured first.
First of all, download the OpenSSL compatible version (> 1.0.2f/1.0.1r).
Download two scripts from this link. In case someone wonders what they do: They build the OpenSSL library for every android build (armeabi, x86, mips, etc...)
Modify setenv-android-mod.sh -> line 18 with the ndk version
Modify setenv-android-mod.sh -> line 40 with the Android API version
Modify build-all-arch.sh -> line 7 with the folder name of the OpenSSL library (in my case it was openssl-1.0.1t)
After successful build, inside the folder dist the libraries will be present
Put those folders inside csipsimple/CSipSimple-trunk/CSipSimple/jni/openssl/lib
Put header files from openssl-1.0.1{version}/include to csipsimple/CSipSimple-trunk/CSipSimple/jni/openssl/include. Be aware, that some of the header files are symlinks to other files.
Compile CSipSimple. Be aware, that OpenSSL and CSipSimple must be compiled with the same Android API version.
Should build successfully after making steps.
mm is for make module, this is available within the Android source project build, so you will need to set up a build environment, within the modules provided is the OpenSSL on Android platform (from which the readme file you're referencing is taken) . Setting up a build environment will take at least a day or two by itself so I wouldn't recommend it unless you already have it for a different reason.. Additionally, Android dropped support for OpenSSL in their latest release and are using BoringSSL. To my knowledge, the best way to achieve what you want here, is to cross compile and build OpenSSL from source following the guidelines on the open ssl wiki, creating .a files and statically referencing them in your app. This is also the recommended way in order to avoid referencing system libraries on N and later versions.
EDIT: To add the libraries to my project as prebuilt static libraries, I created an openssl folder under my jni directory containing lib/ (which contain the .a files for the architectures I support), include/ which has the necessary includes (you can find that under the openssl version you downloaded) and Android.mk which has the following:
include $(CLEAR_VARS)
LOCAL_MODULE := libssl
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libssl.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcrypto
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libcrypto.a
include $(PREBUILT_STATIC_LIBRARY)
Then, to use the library within another jni module I added the following to its Android.mk file:
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../openssl/include
LOCAL_STATIC_LIBRARIES := libssl libcrypto
This is also similar to what's been done here, except that it's not recommended to use .a files provided by non-openssl source.

How to link to the libmedia.so system library in an Android NDK app using android.mk?

I want to create a Player which uses Android system/lib/libmedia.so.
Directly use JNI to play a video.
In Android.mk, i add "-lmedia" for including the library, but i can't link this directly.
This is my process.
write a Cpp file which includes some header file in libmedia.so
add "-lmedia" in Android.mk of LOCAL_LDLIBS
such as..
LOCAL_LDLIBS -lmedia -lstagefright
use ndk-build to build .so
error occured!!
Does anybody have some answer to help???
libmedia.so and libsinstructionght.so are not part of the public API. This means that in theory, you should not rely on them. In practice, though, these libraries are present on all devices, but they are different.
You can extract this binary file from your device, or even from an emulator using command
adb pull /system/lib/libmedia.so C:/android-ndk/platforms/android-14/arch-arm/usr/lib
This will put ths file together with the public API so that using it with ndk-build is easier. On the other hand, you should be aware of fragmentation not lnly between different levels of Android, but also chipsets, manufacturers, and even models.
To handle this, I pull .so files from different devices into separate directories, and add one of them to the linker path, e.g.
LOCAL_LDLIBS += -Lc:/android/galaxys.4.1.2.system.lib
This instruction above can not resolve the big problem you are facing with your approach. libmedia.so is not intended to be linked to user apps. It assumes the context of a privileged user with access to protected devices, such as camera, codecs, and screen.
You can make full use of this library if you target a rooted device, or prepare a custom ROM. And know what you are doing, and how to avoid stealing essential resources from the system.
Otherwise there is very little gain in linking the media lib.
PREBUILT_SHARED_LIBRARY
Points to a build script used to specify a prebuilt shared library.
Unlike BUILD_SHARED_LIBRARY and BUILD_STATIC_LIBRARY, the value
of LOCAL_SRC_FILES must be a single path to a prebuilt shared
library (e.g. foo/libfoo.so), instead of a source file.
You can reference the prebuilt library in another module using
the LOCAL_PREBUILTS variable (see docs/PREBUILTS.html for more
information).
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.so
include $(PREBUILT_SHARED_LIBRARY)
Refrenced from NDK documentation.
PREBUILT_STATIC_LIBRARY
This is the same as PREBUILT_SHARED_LIBRARY, but for a static library
file instead. See docs/PREBUILTS.html for more.
Please read the NDK documentation for more details.

Android system app in c/c++?

I'm experimenting with a rooted Android tablet. I need to run some system applications in C/C++ that can run as native apps with/without using the NDK. This would work like existing command line applications such as toolbox as a native ARM Linux executable.
Is that a possibility?
Yes, you can. And you can do it using the NDK which you make things easier to you , cross-compiling to all platforms supported by Android (ARM variants and x86). You just need to do like you would do to create a shared library for native Java methods. Just make sure you change the makefile to use BUILD_EXECUTABLE instead of BUILD_SHARED_LIBRARY to create an executable. Of course you won't need the APK folder structure, just the "jni" folder.
Tutorial
Create the project folders:
mkdir project_folder
cd project_folder/jni
NDK_PROJECT_PATH=<path to>/project_folder
Create the Android.mk makefile in the jni folder
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := teste
LOCAL_SRC_FILES := teste.c
include $(BUILD_EXECUTABLE)
Create also your source code in the jni. In this case, you can see from above makefile, it is teste.c:
#include <stdio.h>
int main (){
puts("Hello World");
return 0;
}
Now go up to your project folder and run ndk-build from there:
# ~/Downloads/android-ndk-r8b/ndk-build
Compile thumb : teste <= teste.c
Executable : teste
Install : teste => libs/armeabi/teste
Although it is output to a lib folder it is a executable, as you can inspect with file
#file libs/armeabi/teste
libs/armeabi/teste: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), stripped
Yes, it's possible. When you download the NDK you get a set of tools (compiler, linker, etc.), headers and libraries. It's not significantly different from other cross compilation environments.
The NDK comes with a cross compiler and enough of a freestanding programming environment (includes and libs) to port simple C/C++ applications to run as native Android binaries. Check out the docs/STANDALONE-TOOLCHAIN.html file in the NDK for documentation. (It's available online at kandroid.com.)
I believe that the NDK does not have access to enough system services to write a complete app. You'll still have to write the scaffolding of the app in Java, but you can write plenty of native libraries for the Java to call.

Categories

Resources