I am facing issues in using an external shared library in my Android application. I created an Android.mk file as given below:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyApp
LOCAL_SRC_FILES := myexternallib.so
include $(PREBUILT_SHARED_LIBRARY)
Using ndk-build I am able to generate a local native library and I use this native library in my System.loadLibrary method.
When I run the application I get an error java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1486]: 2659 unknown reloc type 19 # ( 4220)
On further search I found a link which recommends to build the shared library using the android toolchain. So I used one of the toolchain arm-eabi-gcc, which is available in the prebuilt/linux_x86/toolchain/arm-eabi-4.4.3/bin directory of the android source code, to build my source files. I get an error arm-eabi-gcc: error trying to exec 'cc1': execvp: No such file or directory. I also noticed that the toolchain folder does not have a file named cc1.
Am I following the right procedure? Is there some other way to reference external shared library in Android code?
It is true that you should use Android toolchain.
Android NDK comes with detailed instructions on using its toolcahin: http://source-android.frandroid.com/ndk/docs/STANDALONE-TOOLCHAIN.html. If you have specific questions about this document, feel free to ask.
Related
I'm trying to compile an open source project (let's say foo) into a libfoo.so native library to use for my android app. However, this project also uses google's protocol buffer library.
So i was able to compile Google's lib protobuf for iOS as follows: https://gist.github.com/BennettSmith/7150245 .
However, this just generates libprotobuf.a file. The problem is that I can't seem to figure out a way to include this libprotobuf.a file to my libfoo.so file for use with my android application. I THOUGHT i had referenced it when i did:
include $(CLEAR_VARS)
LOCAL_MODULE := libprotobuf
LOCAL_SRC_FILES := ./src/lib/libprotobuf.a
LOCAL_EXPORT_C_INCLUDES := ./src/include
include $(PREBUILT_STATIC_LIBRARY)
in my Android.mk file. However, it seems that it is definitely not getting linked properly. Whenever i try to ndk-build the open source project (which depends on using lib protobuf), i get a bunch of undefined references, like:
undefined reference to 'google::protobuf::internal::empty_string_'
so then i thought that maybe i'm not supposed to have the symbols defined here? like maybe i'm supposed to first compile the libfoo.so file, and then somehow link lib protobuf as libprotobuf.a or libprotobuf.so ?? so i ended up using LOCAL_ALLOW_UNDEFINED_SYMBOLS := true to just get my project to generate the libfoo.so file.
but this libfoo.so gives me some load error as soon as i try to use it within my android app:
dlopen failed: cannot locate symbol "_ZN6google8protobuf11MessageLite15ParseFromStringERKSs" referenced by libfoo.so
So I'm wondering:
How do i include this protobuf library in my android app?
Do i try to include this protobuf library into libfoo.so first?
Would it even work if i tried to ignore linker warnings and then tried to generate libprotobuf.so and include that with my application?
is it even possible to generate libprotobuf.so? I can't generate it using the instructions on their github - i get a ton of errors
Note that the only reason i'm even able to get undefined reference errors when trying to generate libfoo.so is because i manually copied all of the *.h in google's lib protobuf.
Any help would be greatly appreciated!!!
This is the first time I decided to write here, but I have long time successfully used stackoverflow, thanks to people who spend his time helping others! :)
Now, I have not found information about this, I am trying to use a library which uses Qt in my android application. The problem is that I am not able to load libQt5Core.so. When running Android throw an unsatisfiedLinkError: unknown failure.
I have tried to load it in two ways.
First one, with its own Android.mk:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Qt5Core
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libQt5Core.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include \
$(LOCAL_PATH)/include/QtCore
include $(PREBUILT_SHARED_LIBRARY)
Second one, adding it manually to lib dir.
I load libraries froma Native.java file in this way:
System.loadLibrary("gnustl_shared");
System.loadLibrary("Qt5Core");
System.loadLibrary("mysharedlibray");
System.loadLibrary("thewholelibrary");
I mysharedlibrary with a Makefile, it's the library which uses Qt.
The whole library includes the jni code and mysharedlibrary, I make it using ndk-build.
I have got libQt5Core.so from the Necessitas package, I suppose I can use it out from the Necessitas system.
I also would like make a "standalone shared library" mysharedlibrary with the Qt "inside" it (since I use no Qt at jni in Android" but it does not let me do that.
Thanks a lot!
To load libQt5Core.so in your android project, you should add dependency to QtAndroid-bundled.jar. You can find the file in the Qt installation directory under the jar directory. After this step you can call System.loadLibrary("Qt5Core"); without UnsatisfiedLinkError.
The reason: QtCore's JNI_OnLoad loads an activity called QtNative when it starts and returns JNI_ERR if it is not found. QtNative is defined in QtAndroid-bundled.jar. I fount anwer here: https://stackoverflow.com/a/25856689/1091536
I've found one solution:
static {
try {
System.loadLibrary("gnustl_shared");
System.loadLibrary("Qt5Core");
}
catch( UnsatisfiedLinkError e ) {
System.err.println("Native code library failed to load.\n" + e);
}
System.loadLibrary("mysharedlibray");
System.loadLibrary("thewholelibrary");
}
If your library uses Qt but just inside itself that works.
I've built an AOSP system service following this tutorial:
http://www.androidenea.com/2009/12/adding-system-server-to-android.html
Now I want to use a pre-compiled .so file and cannot figure out where to put it so my code will be able to access it.
so, i created a folder at framewaork/base/libs/my_folder/
and put there two files:
my_lib.so
android.mk
the content of the android.mk is :
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= my_lib
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
the make ran without errors, but when the code tried to load the library via:
System.loadLibrary("my_lib");
i got this error:
06-27 13:58:55.581: E/AndroidRuntime(806): Caused by: java.lang.UnsatisfiedLinkError: Library my_lib not found; tried [/vendor/lib/my_lib.so, /system/lib/my_lib.so]
so i added the so file to out/target/product/generic/system/lib
but got the same error.
so where should i place the my_lib.so file ? and is an android.mk needed for it ?
maybe i should register it somewhere on the system ?
Thanks in advance!
So the answer was quite simple.
I really need to copy my lib to the system image, to the system/lib folder, because the make command doesn't copy it from out/target/product/generic/system/lib to system.img
the trick is to add this line
PRODUCT_COPY_FILES += $(LOCAL_PATH)/my_lib.so:system/lib/my_lib.so
to full.mk file. it's location is:
android-source/build/target/product
also put the my_lib.so near it
(as seen by the path)
if you are planning to run the image on a real device, add this line after the device name definition.
f.ex. if you are running on Nexus 4, put it at android-source/device/lge/mako/full_mako.mk
You can add your prebuilt library in Android AOSP source code and it be a part of your AOSP System Image. I am describing step by step procedure for it.
Step 1 Create a folder ( let say myLibs) inside external folder of AOSP source code.
external folder of AOSP source code refers to external open source libraries.
That means libraries that the Android platform depend upon but that are not primarily developed and maintained by the Android open source project.
examples are webkit for the browser, FreeType for fonts, SqlLite for databases and so on. As more features are added to Android, more of these libraries are included in external.
Step 2 Create a Android.mk file
Create a Android.mk file inside your folder(let say myLibs) and copy your .so file in it.
You can use following content for your android.mk file
# Prebuilt Lib
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libMyabc # your lib name
LOCAL_SRC_FILES := libMyabc.so
# your lib .so file name
include $(BUILD_SHARED_LIBRARY)
Step 3 Add your library in Framework
In final step you have to add your library in Android AOSP framework makefile so that it will recognise and build as a part of System image.
You find Framework Android.mk file on following location
/android_aosp_sourcecode_download_folder/framenter code hereeworks/base/core/jni/
Open Android.mk file and add your library in following section
LOCAL_SHARED_LIBRARIES := \
You can put your library name in that section example libMyabc \
That's it... now make it (make -j4) and you find your added so file in following folder
/android_aosp_sourcecode_download_folder/out/target/product/generic/obj/lib
with file name like :- libMyabc.so and libMyabc.so.toc
and you also found it in system/lib folder
/android_aosp_sourcecode_download_folder/out/target/product/system/lib
in my case, solved this problem by creating Android.bp file in the repo where i put my prebuilt libraries, then i added them as product packages in the product mk file. this is an example :
Android.bp :
cc_prebuilt_library {
name: "product_package_name_in_MK_file",
relative_install_path: "sub_lib/sub_sub_lib",
stem: "output_file_name", // .so will be added automatically to out file name.
compile_multilib: "both",
multilib: {
lib32: {
srcs: ["path for src 32bit lib"],
},
lib64: {
srcs: ["path for src 64bit lib"],
},
},
strip: {
none:true,
},
allow_undefined_symbols: true,
check_elf_files: false,
vendor: true,
enabled: true,
}
product_mk file :
...
PRODUCT_PACKAGES += product_package_name_in_MK_file
...
I'm having trouble refactoring some make files into manageable modules.
Following is the structure I try to accomplish:
jni/Android.mk
jni/Application.mk
jni/libobj/Android.mk
jni/libpng/Android.mk
jni/libzip/Android.mk
jni/freetype/Android.mk
jni/ftgles/Android.mk
jni/qcar/Android.mk
jni/imagetargets/Android.mk
Note: I started from the Vuforia SDK ImageTargets example and added
some other libraries like reading OBJ, PNG and ZIP files. I've also
included the freetype and ftgles library.
I call the other make files from my the root Android.mk file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include jni/libobj/Android.mk
include jni/libpng/Android.mk
include jni/libzip/Android.mk
include jni/freetype/Android.mk
include jni/ftgles/Android.mk
include jni/qcar/Android.mk
include jni/imagetargets/Android.mk
You can see all make files in a gist on github.
The compiler gives following error:
Install : libFTGLES.so => libs/armeabi/libFTGLES.so Compile++
arm : ImageTargets <= ImageTargets.cpp
jni/imagetargets/ImageTargets.cpp:44:24: fatal error: libpng/png.h: No
such file or directory compilation terminated. make: *
[obj/local/armeabi/objs/ImageTargets/ImageTargets.o] Error 1
Any idea how to make the libpng (and other modules) headers available for the imagetargets module?
I think that specifying the path to the includes in each sub-makefile using LOCAL_EXPORT_C_INCLUDES would ensure that the headers are available when building the final module.
Check the documentation for this flag in the NDK documentation (available in your NDK directory), but from what I understand, it will do exactly what you're trying to do: automatically export the include path of each sub-module to the final module.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I was searching for library which should convert .doc/.docx to .pdf in android platform.
I got PdFTron android sdk,in that they have given libPDFNetC.so file.
For Conversion, there is class called Convert, inside that there is a method toPDF(),
in that method they have internally called native method FileToPdf().I tried that code but unable to call that native method and was getting errors
I want to know that if there is existing .so file present with you and if you want to call native method which is present in .so file then is there need to use JNI?. i dont know much about JNI. any help.
You have to link your final shared library that is generated by the Android NDK using the ndk-build to the PDF shared library you said you already have compiled for the ARM architecture.
(Ensure that this is the case, otherwise the library won't work on Android!)
For that, if for example you have the following directory structure:
jni
└── libs
└────── my_shared_lib.so
└── Android.mk
└── Application.mk
You need to have the following content inside the Android.mk file:
LOCAL_PATH := $(call my-dir)
# define our prebuilt shared library as a module to the build system
include $(CLEAR_VARS)
LOCAL_MODULE := mysharedlib
LOCAL_SRC_FILES := libs/my_shared_lib.so
include $(PREBUILT_SHARED_LIBRARY)
# The final shared library that will be bundled inside the .apk
include $(CLEAR_VARS)
LOCAL_MODULE := mynativelib
LOCAL_LDLIBS := -landroid -llog
LOCAL_CPPFLAGS := -O0 -g3 -std=c++11 -Wall -Wextra
LOCAL_SHARED_LIBRARIES := mysharedlib
LOCAL_C_INCLUDES := myheader1.h myheader2.h
LOCAL_SRC_FILES := src_file1.cpp src_file2.cpp
include $(BUILD_SHARED_LIBRARY)
and the contents of the Application.mk file (for using the C++ Standard Library, and build the the final shared library for two different versions of the ARM architecture):
APP_OPTIM := debug
APP_PLATFORM := android-14
APP_STL := gnustl_static
APP_ABI := armeabi armeabi-v7a
Then after you compile your code from within Eclipse or from the command line using the ndk-build script it'll compile you final shared library and link it against your prebuilt shared library (i.e. the PDF shared library you said you are trying to use).
For shared libraries the apk that is generated and deployed to the device/emulator contains the final shared library as well as all the prebuilt shared libraries you linked against, in contrast with linking against static libraries which are not bundled inside the apk.
For your use case you should have two shared libraries in the lib directory of your Android application after the apk is unpacked on the device.
You can check this by running the following command from a terminal:
adb shell ls -l /data/data/com.company.myapp/lib
Replace com.company.myapp with your application's package name.
Also, don't forget to put the following inside a static context of a Java class:
class MyClass
{
static
{
try
{
System.loadLibrary("mynativelib");
}
catch (UnsatisfiedLinkError ule)
{
Log.e(TAG, "WARNING: Could not load native library: "
+ ule.getMessage());
}
}
// other code here...
}
Notice the use of the same name inside the System.loadLibrary method call as the final shared library name.
You need to make sure the .so file that maps to the native interface is available on your system, and can be found by Java.
There should be a call like System.loadLibrary("<libraryname>") or System.load("/path/to/libs/lib<libraryname>.so") somewhere in your Java code.
That will instruct the JVM to search for the library with the given name and load it.
System.load("/path/to/libs/lib<libraryname>.so") will just look for the file specified as argument, and load it.
System.loadLibrary("<libraryname.") will look in the configured library path for a library with the name lib<libraryname>.so . The library path is taken from the system variable java.library.path .
Also make sure that the library version you are loading is compatible with the Java JNI mapping!
To work on ndk , there is a .mk (make file) that is complied under JNI to get the .so file.
.mk file is written in the native code using the c /c++ snippet.
Now to compile using JNI , there are the two common ways:
1.While working old ADT + SDK versions:
You would require a linux environment to be configured on the windows configuration for running the JNI commands on shell. This environment can be achieved via various software available on net such as cygwin setup.
2.If the ADT + SDK versions that you use are updated:
Then there is a NDK pluggin available in ADT itself . So it easier to work on the ndk and native library.
For more details on NDK visit here