Android Unsatisfied Link using gradle experimental v0.6.0-beta6 - android

I was trying to create a simple project to test the NDK in which a jnilib uses a prebuilt .so library but I keep getting an UnsatisfiedLink error:
With emulator:
java.lang.UnsatisfiedLinkError: dlopen failed: library "~/AndroidStudioProjects/HelloAndroidJni/app/src/main/jni/libs/dynamic/x86/libadd.so" not found
With actual device:
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1891]: 1675 could not load needed library '~/AndroidStudioProjects/HelloAndroidJni/app/src/main/jni/libs/dynamic/armeabi/libadd.so' for 'libhello-android-jni.so' (load_library[1093]: Library '~/AndroidStudioProjects/HelloAndroidJni/app/src/main/jni/libs/dynamic/armeabi/libadd.so' not found)
The .so library has a single function "add" which adds 2 numbers. I compiled it with the NDK standalone toolchain for different ABI (doc):
add.c
#include "add.h"
int add(int x, int y){
return x + y;
}
My jni (.c file):
#include <jni.h>
#include "add.h"
JNIEXPORT jint JNICALL
Java_com_example_tomas_helloandroidjni_MainActivity_addNumbersJni(JNIEnv *env, jobject instance,
jint n1, jint n2) {
return add(n1, n2);
}
My files structure looks like this:
And my gradle file (as defined in the experimental gradle guide):
apply plugin: 'com.android.model.application'
model {
repositories {
libs(PrebuiltLibraries) {
libadd{
headers.srcDir "src/main/jni/prebuilts/include"
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("src/main/jni/libs/dynamic/${targetPlatform.getName()}/libadd.so")
}
}
}
}
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
sources {
main {
jni {
dependencies {
library "libadd" linkage "shared"
}
}
}
}
ndk {
moduleName = "hello-android-jni"
debuggable = true
}
defaultConfig.with {
applicationId = "com.example.tomas.helloandroidjni"
minSdkVersion.apiLevel = 15
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
}
buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file("proguard-android.txt"))
}
}
productFlavors {
create ("x86"){
ndk.abiFilters.add("x86")
}
create("arm"){
ndk.abiFilters.add("armeabi")
}
create("arm7"){
ndk.abiFilters.add("armeabi-v7a")
}
create ("fat"){
}
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.0'
}
I'm not sure where to look at, as I keep getting this error... Maybe I need to add a flag or something?
Thanks in advance for any advice!
EDIT 1.
I tried with static libraries and they work fine. As a consequence (of adding the static libs) I changed the folders' structure slightly (modifying the gradle file accordingly).
I'm working on both:
Actual device: Samsung GT-I8190L Android 4.1.2, API 16 - ARMv7 Processor rev 1 (v7l)
Emulator: Nexus 4 API 23 - x86
EDIT 2.
To compile the libraries I'm doing it with the NDK Standalone Toolchain:
Actual device (ARMv7): SYSROOT=$NDK/platforms/android-21/arch-arm and CC="$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc-4.8 --sysroot=$SYSROOT"
Emulator (x86): SYSROOT=$NDK/platforms/android-21/arch-x86 and CC="/Users/Tomas/Library/Android/android-ndk-r10e/toolchains/x86-4.8/prebuilt/darwin-x86_64/bin/i686-linux-android-gcc-4.8 --sysroot=$SYSROOT"

This may not be the way these native dependencies were expected to work, but (update: this is implicitly written in the doc!) even with plugin 0.7.0, gradle does not copy libadd.so to the APK. There is a workaround, though; add to build.gradle the enchantment:
model {
android.sources.main {
jniLibs.source.srcDir 'src/main/jni/libs/dynamic'
}
}
Still, I recommend to move libs/dynamic folder out of the jni sources folder.

Related

Does Android Wear support C++ (JNI) in Android Studio?

I cannot get an Android Wear project to use C++. I am able to get a "Phone and Tablet" project to use C++. Here is what I have done.
Here is an image of the SDK Tools I have installed. I also have SDK API Levels 24-27 installed.
I create a new project. I check "Include C++ support". I check "Wear" (API 26: Android 8.0 (Oreo)). I select "Next" a bunch.
For C++ Standard I have tried all three (Toolchain Default, C++11, c++14).
I do not check -fexceptions or -frtti.
In the project that is created under the "mobile" Module, I have a "cpp" folder, but I do not have one under the "wear" Module.
If I create a project without "Phone and Tablet" support ("mobile" Module), then I still do not get a "cpp" folder under the "wear" Module.
I tried forcing the project to use C++ under the "wear" Module. Here is what I did.
I modified build.gradle (Module: wear) to look like this
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.example.xorgaming.watchtestcpp"
minSdkVersion 25
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.android.support:wearable:2.2.0'
implementation 'com.google.android.gms:play-services-wearable:11.8.0'
implementation 'com.android.support:percent:26.1.0'
implementation 'com.android.support:support-v4:26.1.0'
implementation 'com.android.support:recyclerview-v7:26.1.0'
implementation 'com.android.support:wear:26.1.0'
compileOnly 'com.google.android.wearable:wearable:2.2.0'
}
I restart the project which makes a "cpp" folder under the "wear" module.
I create a native-lib.cpp file in the "cpp" folder. It looks like this:
extern "C"
JNIEXPORT jstring JNICALL Java_com_example_xorgaming_watchtestcpp_MainActivity_stringFromJNIWatch(
JNIEnv *env, jobject /* this */)
{
std::string hello = "Hello from C++ WATCH!";
return env->NewStringUTF(hello.c_str());
}
In my java onCreate() function, I call: stringFromJNIWatch().
Everything builds without error (green hammer)
When I run the project (as a wearable device) I get this error:
No implementation found for java.lang.String com.example.xorgaming.watchtestcpp.MainActivity.stringFromJNIWatch()
Any idea what I'm doing wrong? Does Android Wear support C++?
Things have changed quite a bit since this question was posted. But half of the answer is: Yes, you can use C++ and Java together with Wear OS. You can follow the same instructions for Android applications.
As for why this failed, my suggestion would be double-check the paths. If you follow the instructions here you will note that the cpp directory goes in the same directory with the java directory. Typically something like MyApplication/app/src/main will have a java directory and a cpp directory. That helps everything get wrapped up into the eventual .apk

Open GL ES - GLM Library and Android Studio

I'm trying to import a little C++ Open GL ES framework I wrote for an iOS application into an Android application.
I want to use Android NDK to import this framework.
As the framework will be shared between iOS and Android, I placed it outside the jni folder. I specified the path to the source dir of this framework in my grade file as follow (http://tools.android.com/tech-docs/new-build-system/gradle-experimental#TOC-Source-Set):
In this framework I used the GLM library for math operation, but as you could see again from the above screenshot, when I try to compile the project I receive the error:
/Users/chicio/Desktop/SpectralBRDFExplorer/SpectralBRDFExplorer/glm/detail/glm.cpp:4:10: fatal error: 'glm/glm.hpp' file not found
What am I doing wrong?
I found a solution to the problem by myself.
As stated before, it was a problem in the setup of the include directories.
I made the app compile by specifying in the gradle file the include directories suing the C++ flag -I
Here you can find the complete gradle file:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion 24
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "it.chicio.android.spectralbrdfexplorer"
minSdkVersion.apiLevel 22
targetSdkVersion.apiLevel 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles.add(file('proguard-android.txt'))
}
}
ndk {
moduleName "LibOpenGLJNI"
toolchain = 'clang'
stl = 'gnustl_static'
CFlags.addAll(['-Wall'])
cppFlags.addAll(['-std=c++11','-Wall',
'-I' + file('src/main/jni'),
'-I' + file('../../SpectralBRDFExplorer'),
'-I' + file('../../SpectralBRDFExplorer/lodepng')])
ldLibs.addAll(['android', 'log', 'GLESv3'])
}
sources {
main {
jni {
source {
srcDir "../../SpectralBRDFExplorer"
}
}
}
}
sources {
main {
assets {
source {
srcDir "../../Assets"
}
}
}
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:design:24.2.0'
}

Android linker: undefined reference to bsd_signal

I'm running gradlew to compile an Android app that has a static lib dependency. Somehow, I have an undefined reference to bsd_signal.
I was able to compile this app with gradle 1.X, but I've been obliged to switch to gradle 2.10 and to drop my Android.mk file in favour of putting more build instruction into my gradle.build file, and this is where the trouble arises.
Can anyone tell me whether there is a library that defines bsd_signal, which I should link to my project?
Compiler output
Starting process 'command '/home/myself/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++''. Working directory: /home/myself/projects/DroidEar/app Command: /home/myself/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ #/home/myself/projects/DroidEar/app/build/tmp/linkNativeArmeabi-v7aDebugSharedLibrary/options.txt
Successfully started process 'command '/home/myself/Android/Sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++''
/android/ndk/platforms/android-9/arch-arm/usr/include/signal.h:113: error: undefined reference to 'bsd_signal'
/android/ndk/platforms/android-9/arch-arm/usr/include/signal.h:113: error: undefined reference to 'bsd_signal'
collect2: error: ld returned 1 exit status
TMI: Here is my gradle.build file
apply plugin: 'com.android.model.application'
model {
repositories {
libs(PrebuiltLibraries) {
Superpowered {
binaries.withType(StaticLibraryBinary) {
def prefix = "src/main/jniLibs/Superpowered"
headers.srcDir "${prefix}"
if (targetPlatform.getName() == "armeabi-v7a")
staticLibraryFile = file("${prefix}/libSuperpoweredAndroidARM.a")
else if (targetPlatform.getName() == "arm64-v8a")
staticLibraryFile = file("${prefix}/libSuperpoweredAndroidARM64.a")
else if (targetPlatform.getName() == "x86_64")
staticLibraryFile = file("${prefix}/libSuperpoweredAndroidX86_64.a")
else if (targetPlatform.getName() == "X86")
staticLibraryFile = file("${prefix}/libSuperpoweredAndroidX86.a")
}
}
}
}
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.3"
sources {
main {
jni {
dependencies {
library "Superpowered" linkage "static"
}
}
}
}
ndk {
ldLibs.addAll(['log', 'android', 'c'])
}
defaultConfig {
applicationId = "edu.ucdavis.auditoryenhancer"
minSdkVersion.apiLevel = 22
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
}
}
android.ndk {
moduleName = "native"
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file("proguard-rules.pro"))
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
}
It looks to me like bsd_signal is defined in the signal.o component of platforms/android-9/arch-x86/usr/lib/libc.a, but even with my ldLibs call above including c, I get the error.
Till android-19 inclusive NDK-s signal.h declared bsd_signal extern and signal was an inline calling bsd_signal.
Starting with android-21 signal is an extern and bsd_signal is not declared at all.
What's interesting, bsd_signal was still available as a symbol in NDK r10e android-21 libc.so (so there were no linking errors if using r10e), but is not available in NDK r11 and up.
Removing of bsd_signal from NDK-s android-21+ libc.so results in linking errors if code built with android-21+ is linked with static libs built with lower NDK levels that call signal or bsd_signal. Most popular library which calls signal is OpenSSL.
WARNING: Building those static libs with android-21+ (which would put signal symbol directly) would link fine, but would result in *.so failing to load on older Android OS devices due to signal symbol not found in theirs libc.so.
Therefore it's better to stick with <=android-19 for any code that calls signal or bsd_signal.
To link a library built with <android-21 I ended up declaring a bsd_signal wrapper which would call bsd_signal from libc.so (it's still available in device's libc.so, even up to Android 7.0).
#if (__ANDROID_API__ > 19)
#include <android/api-level.h>
#include <android/log.h>
#include <signal.h>
#include <dlfcn.h>
extern "C" {
typedef __sighandler_t (*bsd_signal_func_t)(int, __sighandler_t);
bsd_signal_func_t bsd_signal_func = NULL;
__sighandler_t bsd_signal(int s, __sighandler_t f) {
if (bsd_signal_func == NULL) {
// For now (up to Android 7.0) this is always available
bsd_signal_func = (bsd_signal_func_t) dlsym(RTLD_DEFAULT, "bsd_signal");
if (bsd_signal_func == NULL) {
// You may try dlsym(RTLD_DEFAULT, "signal") or dlsym(RTLD_NEXT, "signal") here
// Make sure you add a comment here in StackOverflow
// if you find a device that doesn't have "bsd_signal" in its libc.so!!!
__android_log_assert("", "bsd_signal_wrapper", "bsd_signal symbol not found!");
}
}
return bsd_signal_func(s, f);
}
}
#endif
PS. Looks like the bsd_signal symbol will be brought back to libc.so in NDK r13:
https://github.com/android-ndk/ndk/issues/160#issuecomment-236295994
This is ABI breakage in the Android NDK. Libraries/binaries built with a pre-android-21 NDK using signal() won't work with android-21 or newer. And the other way around. This Rust ticket has a more detailed explanation: https://github.com/rust-lang/libc/issues/236#issuecomment-198774409
There is also this ticket for the Android NDK: https://github.com/android-ndk/ndk/issues/48

NDK module not included in final APK

I've inherited a really messy android project with a lot of NDK dependencies and having a lot of problems with getting gradle to correctly link and include all .so and .a files into the resulting apk.
The project consists of some java code that sets up some activities and call into a big NDK library, built from C++ which in turn links with a dosens of 3rd party library (prebuilt or built from source).
I have managed to make it build with the latest gradle experimental plugin, but for some reason, my module isn't included in the apk while my 3rd party .so files are even though I can see that gradle have built my module into a .so file which it have placed in the build directory.
My build.gradle looks like this:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "22.0.1"
defaultConfig.with {
applicationId = "<removed>"
minSdkVersion.apiLevel = 7
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
}
ndk {
moduleName = "XM"
CFlags.add("-I${file("src/main/jni")}".toString())
cppFlags.addAll(["-I${file("../../3rd_part/android/osg")}".toString()])
cppFlags.addAll(["-I${file("../../3rd_part/android/opus")}".toString()])
ldFlags.add("-L${file("src/main/jniLibs/armeabi-v7a")}".toString())
ldLibs.addAll(["osgdb_jpeg", "osgdb_freetype", "jpeg","argsub_es", "jnigraphics", "android", "log"])
stl = "gnustl_shared"
abiFilters.add("armeabi-v7a")
}
sources {
main {
jni {
source {
srcDir "../../core"
srcDir "src/main/jni"
}
}
}
}
lintOptions.abortOnError = false
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-rules.txt'))
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-v4:23.0.0'
compile 'com.android.support:appcompat-v7:23.0.0'
compile 'com.android.support:design:23.0.0'
compile 'com.wunderlist:sliding-layer:1.1.1'
}
So to sum up my question: why does gradle build my module (libXM.so), place it into build/libs/xM/shared/armeabi-v7a/debug, but not include it into my final apk file?
I didn't get several things: if you want to build a shared library with gradle, then you have to use apply plugin: 'com.android.model.library' and not application
If you want to build an application and use prebuilt library, then you have to write something like this:
sources {
main {
jni {
source {
srcDir "../../core"
srcDir "src/main/jni"
}
dependencies{
library "XM" linkage "shared"
}
And, of course, to set ldFlags previously.

NDK in Android Studio not working

I am doing every single step from video:
https://www.youtube.com/watch?v=kFtxo7rr2HQ
but no shared libraries are generated.
Here is a version, where android-studio should generate shared libraries on his own. However when I create apropraite Makefiles and execute ndk-build, shared libraries are not generated as well.
MainActivity.java:
public native String HelloJNI();
static
{
System.loadLibrary("HelloJNI");
}
Build->Make Project
[*#* main]$ javah -d jni -classpath {sdk_dir}/platforms/android-14/android.jar:../../build/intermediates/classes/debug com.example.ndker.ndkapp.MainActivity
Creating HelloJNI.c:
#include "com_example_ndker_ndkapp_MainActivity.h"
JNIEXPORT jstring JNICALL Java_com_example_ndker_ndkapp_MainActivity_HelloJNI
(JNIEnv *, jobject) {
return (*env)->NewStringUTF(env, "Hello from jni");
}
local.properties:
sdk.dir={sdk_dir}
ndk.dir={ndk_dir}
build.grandle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.example.ndker.ndkapp"
minSdkVersion 14
targetSdkVersion 21
versionCode 1
versionName "1.0"
ndk {
moduleName "HelloJNI"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
}
Thank You for replies.
I've created a blog post that documents setting up Android Studio, Gradle, and the NDK here:
http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/
Also, I've created a sample project in BitBucket with everything already set up for you here: https://bitbucket.org/sureshjoshi/android
Perhaps you could give those a try and see if they work for you?
The key thing is that Gradle will now automatically generate Makefiles and compile for you!
Right. If you put the video on HD, you can then realize that to generate the native compilation, you should use ";" instead of ":". Like:
[*#* main]$ javah -d jni -classpath {sdk_dir}/platforms/android-14/android.jar;../../build/intermediates/classes/debug com.example.ndker.ndkapp.MainActivity
Here is an screenshot of the screen (taken from the video you've posted)
Let me know if that did the trick!

Categories

Resources