I'm trying to load a library I built with the standalone NDK toolchain.
I built libGLmove.so and placed it in libs/armeabi of my Eclipse project
However, the call to System.loadLibrary("GLmove") throws an UnsatisfiedLinkError
Any ideas as to how to resolve the problem or make Android find my library?
How does ndk-build package the library after it builds it?
Edit: The exact compile flags are:
/Users/thomas/Documents/android-ndk-r5b/toolchains/arm-eabi-4.4.0/prebuilt/darwin-x86/bin/arm-eabi-g++ --sysroot=/Users/thomas/Documents/android-ndk-r5b/platforms/android-8/arch-arm -march=armv7-a -mfloat-abi=softfp -mfpu=neon -Wl,--fix-cortex-a8 -fno-exceptions -fno-rtti -nostdlib -fpic -shared -o GLmove.so -O3
Have you checked in the resulting .APK file (use a zip utility to look at/unarchive it) to see if your library makes it through packaging? I'm a little suspicious that it might not, because I notice that everything that gets built into the "libs" folder in the project and on my build machine goes into a folder called "lib" (no 's') in the APK.
I wouldn't be too surprised if it turned out that the Eclipse build process doesn't package up any libraries it doesn't know about. This is, of course, unlike what happens with resources, which just get packaged by virtue of being in the right place.
If you find your library is not in your APK file, I don't think you can just manually put it in there, since it won't show up in the package manifest and will break any signing as well.
You don't mention whether or not your Eclipse project is an NDK project (right click on the project, Android Tools->Add Native Support.) If not, I suspect you'll need to make it into one and then add your library to the Android.mk file as a dependency and not a target.
Or: you could try putting your library into /res in the project and use System.load() instead of System.loadLibrary() to load it. I'll admit that I've never tried that myself, tho.
I was running into this same problem. The things I had wrong.
In the make file I had the "LOCAL_SRC_FILES" spelled wrong.
In the c source file I had the library name inside the method name
Java_com_my_namespace_libname_activity_methodName(JNIEnv* env, jobject _this) {
//Fancy Native Junk Here
}
Once I fixed those two things, re-ran ndk-build and refreshed the eclipse project with F5 it started to work.
You don't give very many details, but it may be that the .so you've built relies on a library that isn't available on the version of phone you're using.
I've not found any way to tell the NDK which Android SDK version you're targeting so don't have any very clear idea of how this side of it should work, but it looks like it would be easy to bring in a dependency from a newer SDK version into your .so so it won't load on all phones.
Could you please check the syntax and the location of System.loadLibrary("GLmove")
the System.loadLibrary call should be in static block of the Java source file
static {
System.loadLibrary("nativelib");
}
http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html
If your native library needs other libraries you'll need to load them first. If that doesn't help, check to see that your project directory does not contain spaces.
Also, you may find this tutorial helpful: http://mindtherobot.com/blog/452/android-beginners-ndk-setup-step-by-step/
Related
I compile my Android project in QtCreator with BOOST_ALL_NO_LIB. This means I include all boost .cpp files right into my project. When I converted this project to Visual Studio project to try to build it for windows, one boost file started to cause problems: zlib.cpp
It contains these lines:
#include "zlib.h" // Jean-loup Gailly's and Mark Adler's "zlib.h" header.
// To configure Boost to work with zlib, see the
// installation instructions here:
// http://boost.org/libs/iostreams/doc/index.html?path=7
I don't understand how is this ever meant to compile, since the directory looks like this:
That means the zlib.h is not there and cannot be included. Visual Studio experiences exactly that problem:
boost159\libs\iostreams\src\zlib.cpp(20): fatal error C1083: Cannot open include file: 'zlib.h': No such file or directory
At the same time, it compiles all right in QtCreator with qmake. So what's going on, how can it ever work? And how to make it work in Visual Studio 2010
You're supposed to have the library dependencies installed.
This means that zlib.h is in your system's include directories.
Your IDE might silently add some convenient libraries your include paths.
I am trying to build Qt application for android using Qt Creator. I use CrystaX NDK for android instead of goolge's one because I need to use boost libraries in my project, and, as CrystaX's official site says, it is comes with it.
I am using following versions of tools:
Qt Creator 3.4.2
Qt 5.5.0
CrystaX NDK 10.2.1
At first, I had to manually add libraries and headers paths in my .pro file, because it hasn't been found automatically. There was compiler error: can't locate libcrystax, there was some errors in source files about including boost headers. I've added following lines in my project file:
android {
INCLUDEPATH += $$NDK_ROOT/sources/crystax/include \
$$NDK_ROOT/sources/boost/1.58.0/include \
$$PWD/ssl
LIBS += -L"$$PWD/ssl" -lssl -lcrypto
LIBS += -L"$$NDK_ROOT/sources/crystax/libs/$$ANDROID_TARGET_ARCH"
ANDROID_EXTRA_LIBS = $$NDK_ROOT/sources/crystax/libs/$$ANDROID_TARGET_ARCH/libcrystax.so
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
}
After rebuilding again, I've got an error (runtime error) that says libgnustl_shared requires libcrystax, but libcrystax is not loaded or something similar.
After searching the internet, I've found that it's happening because one library that requires another, is loading before it, and that second library, is not being searched for, at application directory, only in system paths.
I've found a workaround - to load required library manually. I copied default QtActivity.java into my project directory (android/src/.../QtActivity.java) to replace default one and added following code:
static {
System.loadLibrary( "crystax" );
}
After that I am not getting that error, but now I'm stuck with another one:
java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1285]: 37 cannot locate '__aeabi_ldiv0'...
Is it possible to use Qt + CrystaX NDK for build android app? Am I doing it wrong way? Please, explain how to do it properly, if I've mistaken or if I misunderstood whole concept. Any help is appreciated.
This happens because you haven't linked with libgcc.a. I don't know how exactly your build system works (well, Qt's one), but generally, adding libgcc.a to the list of additional libraries should help:
ANDROID_EXTRA_LIBS = $$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9/libgcc.a
This line specify arm variant of libgcc.a; obviously, you should use proper one depending on ANDROID_TARGET_ARCH value.
I have an Android/Eclipse project that uses the NDK and I've recently enabled c++11 support by adding the following to my Application.mk file:
NDK_TOOLCHAIN_VERSION := 4.8 #same result here with clang
APP_CPPFLAGS += -std=c++11
This basically works fine, c++11 features are available and compile as expected. This goes for ndk-build and Eclipse builds (which just invoke nkd-build), but the eclipse code parser becomes confused now. When I open a file that uses types added to the STL in c++11 (like for example std::unique_ptr), I get red squiggles and an error entry in the Problems tab saying Symbol 'unique_ptr' could not be resolved. This wouldn't be so bad, but if errors are present in that list Eclipse refuses to launch (or debug) the application. Right-clicking on the #include <memory> line and selecting Open Declaration also opens the wrong (4.6) file.
When checking the project properties under C/C++ General --> Paths and Symbols --> Includes it still lists the old (4.6) includes when Show Built-in values is ticked: Screenshot
Are those just cached from somewhere and I can get it to re-generate those entries? I've obviously tried to Clean and Rebuild the project, with no effect. I'd rather not add them manually if that can be avoided, upgrading the NDK to new versions already requires quite a few changes until it compiles again. Where are these entries generated from and how do I trigger an update?
I wish I could say I have a definitive answer for you, as I've been battling this problem for quite a while myself, but I do have a decent workaround. For starters, the "built-in" entries under "CDT Managed Build Setting Entries", are generated based on the contents of your Application.mk file which is located in the jni directory. There is no other way of changing them, and these are what populate the "Includes" section in the C++ perspective's Project Explorer. But I see that must have read the documentation.html in the NDK installation to see what to put in that file already. The issue then becomes that as soon as you change something or breathe too hard, your includes suddenly and irreversably become unresolved. The workaround for this is to recall the exact path of each include entry, right-click on the project, go to New->Folder, then in the dialog click Advanced, and select Link to Alternate Location (Linked Folder). Then navigate to the path (or extend a variable if you are fancy) of the include folder, rename it something descriptive (you can't have 4 linked folders named "include"), and voilĂ ! You suddenly have a usable workspace again. I guess the "Includes" section functionality is a bit flimsy still, at least for ADT, and doing this puts the includes on the same footing as other files that are actually in your project. I'd be thrilled if the officially sanctioned mechanism started to work reliably, and I eagerly await news of such. HTH!
I've got a hold of a proprietary JNI application which I need to build for a MIPS device. I've read "Initializing a Build Environment", parts of the NDK docs, some Google Groups threads and numerous StackOverflow questions, but I'm still short of my answer.
So far, I've checked out the Android source using Google's repo script and have it under ~/AndroidSource. I've also separately downloaded the SDK under ~/AndroidSDK and the NDK under ~/AndroidNDK. The code I'm trying to build is in a separate location. The SDK and NDK binaries are in my path. For building, I tried to use two different versions of the NDK as well as the one under the Android source tree, and experienced different sets of problems. My current setup uses NDK r8b, downloaded separately from the Android source.
The application has its Android.mk and jni/Android.mk. However, several directives in the latter point to paths such as
frameworks/base/include
system/core/include
with no prefixes. I thought these were meant to point to the respective directories in the Android source, so I symlinked them to the current directory. After some more symlinking and makefile and source hacking, I got the application to compile, but am currently stuck on the linking phase with lots of references to missing method bodies. During the whole time I knew I was doing something wrong.
I'm on a Linux x86_64 host, if it is of any concern.
So my question is:
What is the proper method to set up a build environment for JNI applications? What environment variables, symlinks and/or path expansions should I set up? Do I need to call any scripts once or before each ndk-build invocation?
Also, I'd be happy if you corrected me on any concepts or terminology I've gotten wrong.
Your approach wiyh symlinking the AOSP tree for system headers is correct. What you need now are the system libraries compiled for MIPS. The easiest way to get them is to adb pull them from a target device (or emulator image). But you can also build these libraries yourself, as part of the AOSP build (see build instructions for the source tree you downloaded).
If you still have any problems remaining, run your ndk-build with parameter V=1 and publish the link command and its results.
I use the following in my build (YMMV).
Explicitly invoke arm-linux-androideabi-gcc as your compiler or linker (should be in PATH).
NDK_PLATFORM=/path/to/android-ndk-r*/platforms/android-14
Pass -I"$(NDK_PLATFORM)/arch-arm/usr/include" to the compiler
Pass -nostdlib -L"$(NDK_PLATFORM)/arch-arm/usr/lib/" -lgcc -lc -lm to the linker
A project that I am trying to build has one of these, and I want to know exactly which tools are needed to build the project. I see some reference to NDK when I search but is that the only tool? It appears that this file is making a jar file, I see no reference to native code ( c++ )
The Android.mk files in the SDK samples are required to properly include the samples in the SDK build (if you are actually venturing into that territory). These have no bearing on what you are doing when you use the sample. To the OP, I'm not sure if you are using a sample project, but if you are, you can ignore this file.
the best answer to your question is reading this article:
Android.mk file syntax specification
https://android.googlesource.com/platform/ndk/+/4e159d95ebf23b5f72bb707b0cb1518ef96b3d03/docs/ANDROID-MK.TXT
after reading it you can figure out the idea behind the android.mk file.
cheers
I've seen some of the Android sample code come with an Android.mk file for no apparent reason -- maybe this gets auto-generated upon project creation if you happen to have the NDK installed or something. Android.mk does seem to be an NDK-specific thing.
So if there's really no native code involved, then if you're looking to build from the command line, make sure you have the JDK, Ant, and Android SDK installed.
Then take a look at
http://developer.android.com/guide/developing/projects/projects-cmdline.html#UpdatingAProject
After you run the "android update project ..." step, you should hopefully be able to do an "ant debug" to build the application.