Building other library with android ndk project - android

I am having a hard time in integrating dlib with my android studio NDK project, Basically I want to use the library in my native C++ code, I am not sure about the standard way of doing the same, I have my Android.mk file which is under app/src/main/jni as :
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := dlib
LOCAL_SRC_FILES := dlib/all/source.cpp
LOCAL_CPPFLAGS = -I/opt/X11/include
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
OPENCVROOT:= /Users/anmoluppal/Downloads/OpenCV-android-sdk
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=SHARED
include ${OPENCVROOT}/sdk/native/jni/OpenCV.mk
LOCAL_MODULE := ndkDemo
LOCAL_STATIC_LIBRARIES := dlib
LOCAL_SRC_FILES := main.cpp face_detector.cpp face_tracker.cpp ft_data.cpp patch_model.cpp shape_model.cpp
include $(BUILD_SHARED_LIBRARY)
And the Application.mk file looks something like:
APP_STL := gnustl_static
APP_CPPFLAGS += -fexceptions -frtti
APP_ABI := all
And the project structure is:
+ app
---+ src
-----+ main
-------+ jni
---------+ dlib
---------+ Application.mk
---------+ Android.mk
---------+ (... Other .cpp files)
And I am getting a lot of undefined reference to errors which are referring to X11 library on Mac, which is indeed installed properly, I want to know if this is the correct way of including a library in NDK project? Or alternatively I need to create a Android.mk file in dlib folder as well? Also I am unaware of the main .cpp files which are required as LOCAL_SRC_FILES for the .mk file.
After ndk-build I get the following output:
[arm64-v8a] Compile++ : ndkDemo <= main.cpp
[arm64-v8a] Compile++ : ndkDemo <= face_detector.cpp
[arm64-v8a] Compile++ : ndkDemo <= face_tracker.cpp
[arm64-v8a] Compile++ : ndkDemo <= ft_data.cpp
[arm64-v8a] Compile++ : ndkDemo <= patch_model.cpp
[arm64-v8a] Compile++ : ndkDemo <= shape_model.cpp
[arm64-v8a] Compile++ : dlib <= source.cpp
[arm64-v8a] StaticLibrary : libdlib.a
[arm64-v8a] SharedLibrary : libndkDemo.so

There are several things you need to consider.
First: The libraries you link need to be cross compiled for the respective ABIs. Your Application.mk says all so you need to provide all (arm, x86, MIPS,...). Are your libraries prebuilt? In that case you will need to cross compile them manually.
You are missing the include directories for your libraries. You can include them with :
LOCAL_EXPORT_C_INCLUDES
LOCAL_C_INCLUDES
This is the way to go instead of using CPP-Flags.
There are some other problems in your makefile which you should resolve by inspecting makefiles of other people on stackoverflow or search in the NDK documentation. For example I dont think that you can provide the LOCAL_SRC_FILES like you did, you need to separate them by backslashes like that:
LOCAL_SRC_FILES := \ x.cpp \ y.cpp
Your project structure is fine, I think you are almost there.
Feel free to provide the new version of your makefiles when you resolved the linking errors.

Related

Android call a (not JNI) function from external .so library

I am struggling with this problem since few weeks I hope someone can help me.
I have created a C function wrapper in my Android app that impements the JNI export. I have also created a second .so library in order to call my original library but here I have a problem when linking with ndk-build. This is my code:
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_prebuilt_lib
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../jni/
LOCAL_SRC_FILES := ../jniLibs/$(TARGET_ARCH_ABI)/my_prebuilt_lib.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := myjni
LOCAL_SRC_FILES := wrapper.cpp
LOCAL_SHARED_LIBRARY += my_prebuilt_lib
include $(BUILD_SHARED_LIBRARY)
This is the command I am using to build myjni.so:
ndk-build NDK_PROJECT_PATH=./ NDK_APPLICATION_MK=./jni/Application.mk
And I get this error:
Android NDK: WARNING: APP_PLATFORM android-16 is higher than android:minSdkVersion 1 in .//AndroidManifest.xml. NDK binaries will *not* be compatible with devices older than android-16. See https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md for more information.
[armeabi-v7a] Install : my_prebuilt_lib.so => libs/armeabi-v7a/liblocSDK4d.so
[armeabi-v7a] Compile++ thumb: myjni <= wrapper.cpp
[armeabi-v7a] SharedLibrary : libmyjni.so
jni/wrapper.cpp:24: error: undefined reference to 'hex2int(char)'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
Looking into my_prebuilt_lib.so I can see the following declaration about the function I want to call:
00004c51 T hex2int(char)
Any suggestion?

MSI SDR device sample code does not compile

I am trying to interface with an MSI SDR dongle, using an android app
This device is a clone of the SDRPlay SDR device, and is compatible with it's software and drivers
I am trying to interface with this using an OTG cable and android phone
The android drivers for this can be downloaded from here https://www.sdrplay.com/downloads/
It is in the Android tab under the API/HW – V2.11 (15TH NOV 2017) link (https://www.sdrplay.com/anddl.php)
A possible sample code for this driver can be found here: https://www.sdrplay.com/docs/AndroidIntegrationNote.pdf
Before making the full android program it says the library (libmir_sdr_api.a) should be built into an .so library file using ndk-build
I currently have Android's hello-jni sample project from here: https://github.com/android/ndk-samples/tree/android-mk/hello-jni
I have replaced the jni folder using the Android.mk file, libmir_sdr_api.a, mir_sdr.h, initialization-jni.cpp, demod-jni.cpp and demod-jni.h files mentioned in section 3 of the AndroidIntegrationNote.pdf file I linked above
When I execute ndk-build from the hello-jni project folder, I get he following error:
Android NDK: Found platform level in ./default.properties. Setting APP_PLATFORM to android-25.
Android NDK: android-25 is an alias for android-24. Adjusting APP_PLATFORM to match.
[arm64-v8a] Gdbserver : [aarch64-linux-android] libs/arm64-v8a/gdbserver
[arm64-v8a] Gdbsetup : libs/arm64-v8a/gdb.setup
[x86_64] Gdbserver : [x86_64-linux-android] libs/x86_64/gdbserver
[x86_64] Gdbsetup : libs/x86_64/gdb.setup
[armeabi-v7a] Gdbserver : [arm-linux-androideabi] libs/armeabi-v7a/gdbserver
[armeabi-v7a] Gdbsetup : libs/armeabi-v7a/gdb.setup
[x86] Gdbserver : [i686-linux-android] libs/x86/gdbserver
[x86] Gdbsetup : libs/x86/gdb.setup
make: *** No rule to make target 'jni/initialisation-jni.cpp', needed by 'obj/local/arm64-v8a/objs-debug/mirics-jni/initialisation-jni.o'. Stop.
I am used to compiling NDK code suing Android Studio and cmake so I am not sure what is going on here. I have not been able to link the .a file through cmake either so I thought of giving the driver manufacturer's sample code a try, but it not working either. Is the Android.mk file in pdf file linked earlier incomplete, or am I not building it correctly? These are the contents of the Android.mk file:
# $(call my-dir) returns the local directory which is the jni directory
LOCAL_PATH := $(call my-dir)
# libmir_sdr_api.a – this section creates a version of the Mirics API to be used below
include $(CLEAR_VARS)
LOCAL_MODULE := mir_sdr_api-prebuilt
LOCAL_SRC_FILES := libmir_sdr_api.a
LOCAL_EXPORT_C_INCLUDES := $(call my-dir)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
# mirics-jni – this section uses the jni C++ source code to build the dynamic library
LOCAL_MODULE := mirics-jni
LOCAL_SRC_FILES := initialisation-jni.cpp demod-jni.cpp
LOCAL_C_INCLUDES := $(call my-dir)
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib
LOCAL_STATIC_LIBRARIES := mir_sdr_api-prebuilt
include $(BUILD_SHARED_LIBRARY)
Regarding missing jni/initialisation-jni.cpp, you probably have the file jni/initialization-jni.cpp instead.
Also, unfortunately, the document is wrong. You can only use $(call my-dir) easily at the top of the file. Luckily, Android NDK adds the jni directory to includes path for you. Still, to be on the safe side, better write:
# $(call my-dir) returns the local directory which is the jni directory
LOCAL_PATH := $(call my-dir)
# libmir_sdr_api.a – this section creates a version of the Mirics API to be used below
include $(CLEAR_VARS)
LOCAL_MODULE := mir_sdr_api-prebuilt
LOCAL_SRC_FILES := libmir_sdr_api.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
# mirics-jni – this section uses the jni C++ source code to build the dynamic library
LOCAL_MODULE := mirics-jni
LOCAL_SRC_FILES := initialization-jni.cpp demod-jni.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib
LOCAL_STATIC_LIBRARIES := mir_sdr_api-prebuilt
include $(BUILD_SHARED_LIBRARY)
Finally, pay attention to your build process. You only have one kind of the libmir_sdr_api.a static library, it's built for a 32-bit ARM CPU. Therefore you cannot build your libmirics-jni.so for other architectures. Add
APP_ABIS = armeabi-v7a
to your Application.mk file, or specify
abifilters = armeabi-v7a
in your build.gradle, if you build your library in Android Studio.

Linking so file within android ndk

I'm trying to use openssl within android ndk.
I've used openssl source code from guardianproject github page, which is able to produce libssl.so and libcrypto.so files.
Currently I'm stuck at linking those 2 files with my jni interface c file.
Below is my Android.mk file, my jni interface c file called "security.c"
LOCAL_PATH := $(call my-dir)
# Prebuilt libssl
include $(CLEAR_VARS)
LOCAL_MODULE := ssl
LOCAL_SRC_FILES := libprebuilt/libssl.so
include $(PREBUILT_SHARED_LIBRARY)
# Prebuilt libcrypto
include $(CLEAR_VARS)
LOCAL_MODULE := crypto
LOCAL_SRC_FILES := libprebuilt/libcrypto.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := security
LOCAL_SRC_FILES := security.c
LOCAL_SHARED_LIBRARIES= ssl crypto
include $(BUILD_SHARED_LIBRARY)
And this is my security.c file
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <jni.h>
#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
jstring Java_com_test_stringFromJNI(JNIEnv* env, jobject thiz) {
SSL_load_error_strings();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();
return (*env)->NewStringUTF(env, "Hello from JNI");
}
When build with ndk-build, this error occured
Android NDK: WARNING: APP_PLATFORM android-19 is larger than android:minSdkVersion 8 in /Users/huydo/cur-project/company/kimisaki_native/android_os/ensemble_girls/AndroidManifest.xml
[armeabi-v7a] Install : libcrypto.so => libs/armeabi-v7a/libcrypto.so
[armeabi-v7a] Compile thumb : security <= security.c
[armeabi-v7a] SharedLibrary : libsecurity.so
[armeabi-v7a] Install : libsecurity.so => libs/armeabi-v7a/libsecurity.so
[armeabi-v7a] Install : libssl.so => libs/armeabi-v7a/libssl.so
[armeabi] Install : libcrypto.so => libs/armeabi/libcrypto.so
[armeabi] Compile thumb : security <= security.c
[armeabi] SharedLibrary : libsecurity.so
[armeabi] Install : libsecurity.so => libs/armeabi/libsecurity.so
[armeabi] Install : libssl.so => libs/armeabi/libssl.so
[x86] Install : libcrypto.so => libs/x86/libcrypto.so
/Users/huydo/android-ndk-r9d/toolchains/x86-4.6/prebuilt/darwin-x86_64/bin/i686-linux-android-strip: Unable to recognise the format of the input file `/Users/huydo/cur-project/XXX/android_os/YYY/libs/x86/libcrypto.so'
make: *** [/Users/huydo/cur-project/XXX/android_os/YYY/libs/x86/libcrypto.so] Error 1
make: *** Deleting file `/Users/huydo/cur-project/XXX/android_os/YYY/libs/x86/libcrypto.so'
Noted that libssl.so and libcrypto.so has been correctly copied into armeabi and armeabi-v7a. It stucked when building for mips and x86 architecture.
If you experienced this error before, can you give me a glue what happened.
You're using the same ARM libssl.so and libcrypto.so when compiling for every architecture, which can't work.
You need to use prebuilts targeting the right architectures. For this you can create subfolders inside libprebuilt named against each architecture (armeabi, armeabi-v7a, x86, mips), add your prebuilts .so files under each of these, and use $(TARGET_ARCH_ABI) inside your Android.mk to reference your .so files:
LOCAL_PATH := $(call my-dir)
# Prebuilt libssl
include $(CLEAR_VARS)
LOCAL_MODULE := ssl
LOCAL_SRC_FILES := libprebuilt/$(TARGET_ARCH_ABI)/libssl.so
include $(PREBUILT_SHARED_LIBRARY)
# Prebuilt libcrypto
include $(CLEAR_VARS)
LOCAL_MODULE := crypto
LOCAL_SRC_FILES := libprebuilt/$(TARGET_ARCH_ABI)/libcrypto.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := security
LOCAL_SRC_FILES := security.c
LOCAL_SHARED_LIBRARIES= ssl crypto
include $(BUILD_SHARED_LIBRARY)
If you don't find x86 versions of libssl.so and libcrypto.so, you can pull these out from the x86 emulator.
To specify against which architecture you want to compile your projet, use APP_ABI variable inside Application.mk, for example :
APP_ABI := armeabi-v7a x86 mips

NDK Library Not Found

I'm getting the following error;
E/AndroidRuntime(446): Caused by: java.lang.UnsatisfiedLinkError: Library XYZ not found
but I have library XYZ in my project. The folder struct is:
-ProjectFolder
--obj
---local
----armeabi
-----objs
------libXYZ.so
------libstdc++.a
------XYZ
-------folderA
--------fileX.o
--------fileX.o.d
--jni
---Android.mk
---folderA
----fileX.cpp
----fileX.h
Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
APP_ABI := armeabi armeabi-v7a x86
LOCAL_MODULE := XYZ
LOCAL_SRC_FILES := folderA/fileX.cpp
include $(BUILD_SHARED_LIBRARY)
C++ compile output:
Compile++ thumb : XYZ <= fileX.cpp
In file included from jni/folderA/fileX.h:1:0,
from jni/folderA/fileX.cpp:1:
/Applications/android-ndk-r8b/platforms/android-5/arch-arm/usr/include/jni.h:592:13: note: the mangling of 'va_list' has changed in GCC 4.4
StaticLibrary : libstdc++.a
SharedLibrary : libXYZ.so
Install : libXYZ.so => libs/armeabi/libXYZ.so
I don't understand why the error says "Library XYZ not found", when the library is in the correct place.

Android NDK - Use of APP_STL in Application.mk

I have the latest android ndk installed. I am using Eclipse along with Sequoyah.
I am trying to use various things that should be found in stlport or gnustl libraries, but I keep getting errors that they cannot be found.
In JNI/Application.mk I only have
APP_STL := stlport_shared
I have tried stlport_static and the gnustl_static/shared and all get the same result.
In my Android.mk I have
LIB_TEST_DIR := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PATH := $(LIB_TEST_DIR)
LOCAL_MODULE := testmod
LOCAL_MODULE_FILENAME := libtestmod
LOCAL_CPP_EXTENSION := .cxx .cpp .cc
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libtest2/
LOCAL_CFLAGS := -DHAVE_CONFIG_H
LOCAL_SRC_FILES := test.cc
include $(BUILD_SHARED_LIBRARY)
In a header file that test.cc includes, I have
#include <cassert>
#include <algorithm>
#include <iosfwd>
But, when I build, it cannot find any of these. Any idea what I am doing wrong?
When I do a clean, I see this:
Clean: addiJNI [armeabi]
Clean: stlport_shared [armeabi]
Clean: stlport_static [armeabi]
So, it seems like it knew I wanted stlport. Similar thing happens if I use the gnu libs instead. But when I build even the simplest example, I get something like...
jni/test.cpp:4:19: error: cassert: No such file or directory
jni/test.cpp:6:21: error: algorithm: No such file or directory
jni/test.cpp:7:18: error: iosfwd: No such file or directory
make: *** [obj/local/armeabi/objs/addiJNI/addiJNI.o] Error 1
This was the problem, not sure why.
LOCAL_CPP_EXTENSION := .cxx .cpp .cc
It didn't like the .cxx at the beginning.

Categories

Resources