I am building a mixed mode Android project, the project is using the native ffmpeg
The Libs are
2.1. libavutil.so -> libavutil.so.51
2.2. libavcodec.so -> libavcodec.so.54
2.3. libavformat.so -> libavformat.so.54
My Java code include the following JNI section to load the native libs:
static {
System.loadLibrary("avutil");
System.loadLibrary("avcodec");
System.loadLibrary("avformat");
}
'libavcodec.so' depends on 'libavutil.so.51' AND NOT on 'libavutil.so'.
When running my activity System.loadLibrary("avcodec"); excepts with "could not load needed library 'libavutil.so.51' for 'libavcodec.so' (Library 'libavutil.so.51' not found)"
On my Android.mk I have the following section to have the native libs added to the APK:
include $(CLEAR_VARS)
LOCAL_MODULE := mylib
LOCAL_SRC_FILES := ../../../mylib/libmylib.so
include $(PREBUILT_SHARED_LIBRARY)
replacing libmylib.so with libmylib.so.%some number% cause the build to fail with [LOCAL_SRC_FILES should point to a file ending with ".so"]
Having the above in mind, how can I have libavcodec loading w/o the dependency problem ?
Can I fix libavcodec.so dependency to point to libavutil.so and not to libavutil.so.51 ?
Can I change Android.mk so it will be able to pack libavutil.so.51 ( non .SO extention ) ? will it then be loadable using 'System.loadLibrary' ?.
Any help will be appreciated!!!
Nadav at Sophin
Work-around was simply to use the static libs rather than the dynamic libs, this however, is a temporary work-around as due to LGPL limitations the SharedLibs are mandatory for commercial use.
Related
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.
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!!!
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.
I have an android project with a libs folder structure like this:
/libs
/armeabi
libfoo.so
libbar.so
libmystuff.so
libgnustl_shared.so
/armeabi-v7a
libfoo.so
libbar.so
foo and bar are third party libraries, mystuff is my own library from a separate android JNI project which requires gnustl_shared, which is from the same JNI project.
When I build my project in Eclipse, I can view the contents of the generated APK using unzip -l, and it indeed shows that all of these library files have been included.
However, after installing the APK, the /data/data/com.myproject/lib folder contains no libgnustl_shared.so, even though the other libraries are present.
This inevitably leads to the following error:
UnsatisfiedLinkError: Couldn't load gnustl_shared: findLibrary returned null
As a sanity check, I ran adb push ./libs/armeabi/libgnustl_shared.so /data/data/com.myproject/lib and sure enough, the application starts as expected.
I don't see anything in the build log or Eclipse console that suggests there were any issues building or installing the app.
What could be preventing libgnustl_shared.so from being installed with my application?
Where can I go to learn about what happens when an APK is installed?
Please let me know in a comment if there's any specific information I can provide that might help.
I think that, in your JNI project's Android.mk file, most probably, when you build libmystuff.so, you're referencing libgnustl_shared.so like:
LOCAL_LDLIBS += -lgnustl_shared
Maybe you can try to add it as a module (NDK works really focused on modules), something like:
include $(CLEAR_VARS)
LOCAL_MODULE := gnustl_shared
LOCAL_SRC_FILES := libgnustl_shared.so
include $(PREBUILT_SHARED_LIBRARY)
and (in the section you're building libmystuff.so):
LOCAL_SHARED_LIBRARIES := gnustl_shared
And check if it's finally copied
I think your libgnustl_shared.so need under /armeabi-v7a not under /armeabi
Please try copy libgnustl_shared.so to /armeabi-v7a
Look at the answer here: How to link any library in ndk application
The problem is most likely in your Android.mk file. You should have a line like the one on the bottom:
include $(BUILD_SHARED_LIBRARY)
If not, then you're not including your shared library.
I have written C++ file in JNI folder of my application. I am using Windows system with NDK and Cygwin 1.7.I want reffer to CURL library available in Cygwin.How can we refer to external .h(libraries/header) files while creating JNI application in Android?I have created a combined Android and C++ project. But I am referring CURL header file. When I build the project I am getting fatal error: curl/curl.h: No such file or directory issue.
Follow these steps:
Converting from Android project to C/C++ project:
Right click on your project name, go to 'Android Tools' and click 'Add native support'
Adding paths to external .h files:
Right click on your project name, go to 'Properties', under 'C/C++ General', go to 'Paths and Symbols', under 'Includes' tab, add the folder in which your .h file is. Remember to add to all languages and configurations if asked.
Also, since you are in Windows, I think you will need to change your Build command (which is in the 'C/C++ Build' section in project properties) to "bash C:\Development\android-ndk-r8\ndk-build.cmd"
Add the following to your Android.mk:
LOCAL_CFLAGS += -I$/PATH/TO/YOUR/curl.h
LOCAL_LDLIBS += -L$/PATH/TO/YOUR/libcurl.a.for.android -lcurl
The libcurl.a you have installed in cygwin is not usable for android, you need a version targetting android. If you don't have it, build it yourself.
When you get that libcurl.a file, do not forget to copy the headers folder of curl (get into your usr/include/curl from Cygwin) and add this folder to the JNI one in your project, so it knows the headers while compiling.
Which means also referring in your Android.mk :
for the libcurl library
LOCAL_SRC_FILES := libcurl.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/curl
and for your C++ files
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/curl
LOCAL_WHOLE_STATIC_LIBRARIES := libcurl
Please used this tutorial is nice one.
Don't forgot to change this setting after convert project to C / C ++ native project.
Builder Settings to Build Command
bash C:\tools\android-ndk-r8b-windows\android-ndk-r8b\ndk-build
This is my path of NDK you can change this path accordingly your NDK path.