Using a third party .a library in Android ndk app - android

We are trying to use a third party .a static library in our Android app. The .a lib is built for x86 and we used it with a PC linux box without problem.
Then we try to use it on Android with this Android.mk:
LOCAL_PATH:= $(call my-dir)
# first lib, which will be built statically
#
include $(CLEAR_VARS)
LOCAL_MODULE := libtwolib-first
LOCAL_SRC_FILES := rwl.a
LOCAL_MODULE_SUFFIX := .a
include $(PREBUILT_STATIC_LIBRARY)
# second lib, which will depend on and include the first one
#
include $(CLEAR_VARS)
LOCAL_MODULE := libtwolib-second
LOCAL_SRC_FILES := second.c
LOCAL_STATIC_LIBRARIES := libtwolib-first
include $(BUILD_SHARED_LIBRARY)
We get this error:
could not read symbols: File in wrong format
Is it because the .a file is compiled with x86 and we are building for arm?
The .a file is a legacy and most likely can't be recompiled from source. If this is the issue, is there any other solution?
Thanks.

You need to obtain the source for the third-party lib and cross-compile it to native Android's NDK such that its binary compatible.
Simply dropping an x86 static lib into Android's NDK build will just not work.

Related

Add libstagefright in my Android NDK Application

I made some changes in AOSP code and compiled it. Now i want to Add created libstagefright.so in my Applicaton.
In Android.mk i'm adding as LOCAL_SRC_FILES compiled libstagefright.so library with path.
Here is it`
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libstagefright
LOCAL_SRC_FILES := ./Source/out/target/product/generic/system/lib/libstagefright.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := example
LOCAL_SRC_FILES := example.cpp
LOCAL_LDLIBS := -llog-landroid
LOCAL_SHARED_LIBRARIES := libstagefright
include $(BUILD_SHARED_LIBRARY)
When i'm building and running program I don't see any changes in library.What is the Problem that i don't see any changes?
Thanks in advance.
Instead of libstagefright.so, you can build the AOSP-derived library as libmybetterstagefrght.so and use it in your app instead of stagefright. You can put your library in your libs folder just like any other library. You don't need root for that.
Note that the library you build will still connect to many OMX and other binaries in /system/lib, so all interfaces should be maintained. You probably want to start with the AOSP revision that corresponds to the system level of your device. You may face compatibility problems if the device uses a customized Android - for best results, take a Nexus device.

Building System App With Prebuilt .so Library

I've been stuck here for a week trying to build a 3rd party .so library along with my app into custom Android system. I followed http://www.maxters.net/2012/05/adding-prebuilt-shared-library-to-android-build-system/ and successfully add the .so lib as prebuilt shared library to Android Build System. Now I can see the .so lib at ../out/target/product/crespo4g/obj/lib/.
But the libraries in this directory are not going to be migrated to device when flashing. And my .so lib is not appeared at /data/data/my_app_name/lib either. So UnsatisfiedLinkError occurs when executing System.loadLibrary().
I thought there are three ways to solve this, but just don't know how to implement:
Maybe my app failed to indicate to compiler that my .so is along with my app as a whole, so the .so lib is not compiled into the system image with my app. But I did declare by "LOCAL_STATIC_LIBRARIES := libXX", anything wrong?
Is there a way to build my .so lib into /system/lib/? Where are the so libs under /system/lib/ derived from?
I am new to Android building, please help..
Thanks!
You might want to check you makefile against advice in this answer and this one as well as the advice in this groups thread
UPDATE
My original makefile was incorrect but this does work for me building ICS:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libmozglue
LOCAL_SRC_FILES := libmozglue.so
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_TAGS := optional
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := libplugin-container
LOCAL_SRC_FILES := libplugin-container.so
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_TAGS := optional
include $(BUILD_PREBUILT)
where the above are the native libraries required by firefox for android that I include as a system app in my custom system build.

How to create .so (Shared Object library file) from .c (C file) for Arm Processor?

I wanted to create a Prebuilt Shared library .so from .c file for ARM processor. Kindly give me some steps to do this and also how to include and access its functions in android.
You are looking for:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_static_lib
LOCAL_C_INCLUDES := src
LOCAL_SRC_FILES := src/main_main.c
# Use this one to build a *.a file - static library
include $(BUILD_STATIC_LIBRARY)
# Use this one to build a *.so file - a shared library
include $(BUILD_SHARED_LIBRARY)

How to link a prebuilt shared Library to an Android NDK project?

Here I used this Android.mk file in jni/ folder.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE := offlineDownload
LOCAL_SRC_FILES := offline_download.c
LOCAL_SHARED_LIBRARIES :=../lib/libpackext.so.1.0
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)
And make one lib folder in project directory and put my prebuilt .so library and make one Android.mk file which contains following
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := packext
LOCAL_SRC_FILES := libpackext.so.1.0
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include
include $(PREBUILT_SHARED_LIBRARY)
And when i use ndk-build -B command than i got undefined reference to packageExtraction. Here I use my prebuilt library functions means I can't link my prebuilt shared library to my offlinedownload library.
So any body please help me to solved out this issue.
Here is a complete Android.mk file for using a 3rd party shared library.
The library (libffmpeg.so) is placed in the jni folder.
Its "LOCAL_EXPORT_C_INCLUDES" specifies where the header files are kept for the library.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := libffmpeg.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../ffmpeg/libs/arm-linux-androideabi4.7_1/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpegandroid
LOCAL_SRC_FILES := ffmpegandroid.c
LOCAL_SHARED_LIBRARIES := ffmpeg
include $(BUILD_SHARED_LIBRARY)
If you wanted to support multiple architectures then you could specify:
APP_ABI := armeabi armeabi-v7a x86 mips
in your jni/Application.mk and change the LOCAL_SRC_FILES to something like:
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libffmpeg.so
and place a libffmpeg.so at jni/armeabi/libffmpeg.so, jni/armeabi-v7a/libffmpeg.so etc ..
Android NDK official hello-libs CMake example
https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs
Just worked for me on Ubuntu 17.10 host, Android Studio 3, Android SDK 26, NDK 15.2. so I strongly recommend that you base your project on it.
The shared library is called libgperf, the key code parts are:
hello-libs/app/src/main/cpp/CMakeLists.txt:
// -L
add_library(lib_gperf SHARED IMPORTED)
set_target_properties(lib_gperf PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/gperf/lib/${ANDROID_ABI}/libgperf.so)
// -I
target_include_directories(hello-libs PRIVATE
${distribution_DIR}/gperf/include)
// -lgperf
target_link_libraries(hello-libs
lib_gperf)
on C++ code, use: #include <gperf.h>
header location: hello-libs/distribution/gperf/include/gperf.h
lib location: distribution/gperf/lib/arm64-v8a/libgperf.so
app/build.gradle:
android {
sourceSets {
main {
// let gradle pack the shared library into apk
jniLibs.srcDirs = ['../distribution/gperf/lib']
Then, if you look under /data/app on the device, libgperf.so will be there as well.
If you only support some architectures, see: Gradle Build NDK target only ARM
The example git tracks the prebuilt shared libraries, but it also contains the build system to actually build them as well: https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs
You have to do either one of the following:
Cut and paste everything except LOCAL_PATH := $(call my-dir) from your second Android.mk into your first.
Put the following in the end of your first Android.mk:
$(call import-module,packext)
Also make sure that you set your NDK_MODULE_PATH environment variable to a path where the Android.mk-file defining the module packext can be found.
You also have to change the LOCAL_SHARED_LIBRARIES in the same way mgiza said in the first answer. I suppose the packageExtraction that you got undefined reference to is in your prebuilt library so unless you have other linking problems this should solve the issue.
Have a look at the ndk documentation for prebuilts:
android-ndk/docs/PREBUILTS.html
You have to change
LOCAL_SHARED_LIBRARIES :=../lib/libpackext.so.1.0
to
LOCAL_SHARED_LIBRARIES := packext
Be sure that your folder containing the Android.mk for the packext module is named packext and can be found in in your NDK_MODULE_PATH.

Android NDK linking problems

I compiled Sox et al with NDK. So, I have all Android-friendly shared libs.
I made a simple test file which calls a sox function.
NDK build tells me:
undefined reference to `sox_open_read'
sox_open_read is defined in sox.h. I know it's finding sox.h because it gives me a warning about that file:
In file included from (...)/sox/sox.h:19
So maybe it wants to find sox_open_read in the actual libsox.so. Well, I've tried about a 100 different ways to tell it where the sox shared lib is e.g.
LOCAL_SHARED_LIBRARY := sox
LOCAL_LDLIBS := -L$(LOCAL_PATH_FULL)/jni/libs/libsox.so
However, It will work if I specify Sox as a static library:
#LOCAL_SHARED_LIBRARY := sox
LOCAL_STATIC_LIBRARIES := sox
LOCAL_LDLIBS := -L$(LOCAL_PATH_FULL)/jni/libs/libsox.so
It's my understanding that I don't want to staticly link to the sox lib - I want to dynamically link to it.
You should define libsox.so as a prebuilt library. Create a makefile as the following and put your prebuilt libsox.so in the same directory with this makefile. After that, you can use libsox same as you've rebuilt it. Don't forget to include this makefile into your build.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libsox
LOCAL_SRC_FILES := libsox.so
include $(PREBUILT_SHARED_LIBRARY)

Categories

Resources