Linking so file within android ndk - android

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

Related

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.

Building other library with android ndk project

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.

undefined reference to `cv::fastFree(void*)'

I have a C++ (ImageExtraction.cpp) file which uses OpenCV. Here is the snapshot of C++ file. I want to call this native C++ file from my Android java file. I am using Mac...
#include < string.h>
#include < jni.h>
#include < opencv2/imgproc/imgproc.hpp>
#include < opencv2/highgui/highgui.hpp>
#include < iostream>
#include < cv.h>
#include < stdio.h>
#include < algorithm>
#include < functional>
using namespace cv;
using namespace std;
extern "C"
{
JNIEXPORT jint JNICALL Java_com_clematistech_businesscardreader_BusinessCardReader_stringFromJNI(JNIEnv *env, jobject obj)
{
........
}
}
Here is my Android.mk:
LOCAL_PATH := $(call my-dir)
LOCAL_C_INCLUDES := /usr/local/include/opencv
include $(CLEAR_VARS)
include /Users/sritomamajumder/Documents/MISC/Softwares/OpenCV_for_Android/OpenCV-2.4.10-android-sdk/sdk/native/jni/OpenCV.mk
LOCAL_LDLIBS := -llog
LOCAL_MODULE := ImageExtraction
LOCAL_SRC_FILES := ImageExtraction.cpp
LOCAL_STATIC_LIBRARIES := libzip libpng libjpeg freetype
LOCAL_STATIC_LIBRARIES += libopencv_contrib libopencv_legacy libopencv_ml libopencv_stitching libopencv_nonfree libopencv_objdetect libopencv_videostab libopencv_calib3d libopencv_photo libopencv_video libopencv_features2d libopencv_highgui libopencv_androidcamera libopencv_flann libopencv_imgproc libopencv_ts libopencv_core
include $(BUILD_SHARED_LIBRARY)
Here is the Application.mk:
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := all
APP_PLATFORM := android-10
APP_MODULES := ImageExtraction
When I ran ndk-build command from my root Android project I am getting the following errors:
[arm64-v8a] Compile++ : ImageExtraction <= ImageExtraction.cpp
[arm64-v8a] SharedLibrary : libImageExtraction.so
./obj/local/arm64-v8a/objs/ImageExtraction/ImageExtraction.o: In function `cv::Mat::~Mat()':
/Users/sritomamajumder/Documents/MISC/Softwares/OpenCV_for_Android/OpenCV-2.4.10-android-sdk/sdk/native/jni/include/opencv2/core/mat.hpp:278: undefined reference to `cv::fastFree(void*)'
......
Please let me know what I have done wrong.
with APP_ABI set to all, the latest NDKs is set to compile your code for all 64bit platforms (arm64-v8a, x86_64...) as well as the 32bit ones.
But your OpenCV package doesn't contain binaries for 64bit platforms, I guess that's why you're experiencing the current issue.
You can set APP_ABI to all32 inside your Application.mk file to target only 32bit platforms (armeabi-v7a x86 armeabi mips) for which the OpenCV package is providing prebuilts for.

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