I'm working on a project that requires me to integrate CLSTM library (a C++ implementation of LSTM networks for OCR) in an Android application. I'm a beginner Android developer and this is my first time working with NDK.
I'm having trouble integrating the C++ code with my project. I have been trying to do it for a couple of days, but have still gotten nowhere. I have been looking for solutions everywhere, but I can't find exact instructions for my problem.
What I have been able to do till now is:
Created new project with C++ support
Downloaded Android NDK
Downloaded CMake
Created JNI Folder
Cloned the source code into JNI Folder
I am not sure if I was supposed to do steps 4, 5 above. Also, from all the tutorials I have found, I think after these I am supposed to create an Android.mk and Application.mk files. I'm not sure what to write in them.
Can anyone guide me with exact steps for how to integrate this particular library in my Android application?
It's not really clear what exact problem you are having but I'll give it a shot as I've been dabbling with this myself recently. These are the steps I took:
Using classpath 'com.android.tools.build:gradle:2.2.0 as my build tools version
Added the C libraries in my app/src/main/jni directory
Added an Android.mk and Application.mk file in my app/src/main/jni directory
Added the following to my app/build.gradle:
```
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
```
You can find the contents of my Application.mk and Android.mk here.
I based my setup of the .mk files & contents upon the keepassdroid project.
Edit:
if you also want to use travis-ci you can use this to download and use the android ndk in your builds:
before_install:
- curl -L http://dl.google.com/android/repository/android-ndk-r14-linux-x86_64.zip -O
- unzip -q android-ndk-r14-linux-x86_64.zip
- export ANDROID_NDK_HOME=`pwd`/android-ndk-r14
- export PATH=$PATH:${ANDROID_NDK_HOME}
Related
I've installed Visual Studio 2017 with Cross Platform Development kit and have managed to compile SDL2 as a dynamic shared library following this steps:
https://trederia.blogspot.hr/2017/03/building-sdl2-for-android-with-visual.html
When deployed on Visual Studio Android Emulator the application runs correctly.
Using the same steps, I also compiled Box2D library. I then added the paths, to the SDL2 application from above and added Box2D in libraries array in SDLActiviy.java and linked the project with libBox2D.so.
But when run on emulator it says this:
https://imgur.com/a/LsI21
I can also see from the compile that Box2D lib is not linked and is not in the libs folder of *.apk file
Anyone knows what I'm missing here?
P.S. I compiled everything with ARM architecture.
After a lot of trial and error.
Add new project to the original SDL2_Project solution and select Dynamic Shared Library.
Add all the *.cpp files in the Box2D library and compile.
Open SDL2_Application.java and add "Box2D" in the library list.
Right Click on the references in the SDL2_Application and click Box2D checkbox. This will add Box2D library to the final APK packet and will include the compiled lib in the /lib folder of the APK.
Android Studio 2.2 introduces cmake external build system. The problem is that documentation is really lacking and I do not know how should I link third party libraries? I've tried cmake directive target_link_libraries:
target_link_libraries(native-lib libs/libSomething.so)
And it "works" in that app compiles but then I get dlopen error at runtime because libSomething.so has not been packaged with application. The libs directory is under "app" if that changes anything and I've started with default JNI project generated by Android Studio 2.2...
[Update]
I've tried putting libSomething.so under app/src/main/jniLibs/armeabi-v7a but now the "main" (native-lib) library is not packaged.
[Update2]
I've added source set config that includes cmake output dir and this works but is ugly as hell and is not really a permanent solution...
sourceSet
{
main
{
jniLibs.srcDirs = [ "libs", ".externalNativeBuild/cmake/debug/obj"]
}
}
For now I ended up copying libSomething.so to cmake library output directory in a post build step. This works because it turns out that Android Studio copies into apk EVERYTHING that is in that directory.
Command in cmake is the following:
add_custom_command(TARGET native-lib POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/libs/${ANDROID_ABI}/libSomething.so
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libSomething.so
)
For now, you could also put your shared libs into directory, and configure jniLibs to point to that directory, that will pack it. One sample is here: https://github.com/googlesamples/android-ndk/tree/master/hello-libs, follow gperf see if that helps. This way app not depending on the generated build folders. When android studio added packing libs, the jniLibs workaround is not necessary anymore
I've been doing a lot of attempts to get libpcap compiled for Android, and I don't see any pattern or any progress worth writing down.
I have a very simple sniffer (that works fine in a MIPS linux) that uses libpcap, so I thought to myself oh, ok... no biggie... I'll just compile libpcap for Android (in the end, Android is just a Linux)... and here's where the problems started. I have no idea on how to compile libpcap using ndk-build and the Android.mk and all that infrastructure.
I have the Android NDK in a directory. That NDK has the toolchains built (I have a lot of directories under ~/Documents/Projects/Android_NDK/toolchains/ ) but none of the toolchains has libpcap available.
I've tried with two different libpcap version or... branches:
The Android one, which is the one I'd like to use,
https://android.googlesource.com/platform/external/libpcap/
and the regular one:
http://www.tcpdump.org/release/libpcap-1.5.3.tar.gz
All tries I've done have been very unsuccessful. I've seen the question Android NDK: Link using a pre-compiled static library which is similar, but I'm still getting various errors.
I have downloaded those pcap libraries to their own directories. Maybe is that the problem? Do I need to put the Android libpcap in some directory within the NDK root directory and re-create the toolchains?
I'm using NDK-r9 on a MacOSX 10.9.2 64bit.
Finally!!
After getting annoyed by the non existing headers in and stuff like that, I found this question, that pointed to a SVN repo (http://sourceforge.net/p/prueba-android/code/HEAD/tree/trunk/jni/) with a libpcap that compiled!
If someone else wants additional details on how my Android.mk and directory structure looks like, please add a comment and I'll extend this answer.
Please read an excellent article at http://blog.umitproject.org/2011/05/libpcap-for-android.html. There are instructions that will help you link to libpcap, but the most important takeaway is that you cannot use libpcap on non-rooted Android. So maybe it's not worth your effort.
On a rooted device, you can simply install a free sniffer like Shark for Root.
If anyone else is having problems compiling libpcap for Android using the NDK, there is version 1.5.2 here with a built Android.mk file in it: https://android.googlesource.com/platform/external/libpcap.git and instructions for compiling this using the NDK are here: http://ducbh.blogspot.co.uk/2013/12/cross-compile-libpcap-for-android.html . I can confirm this works using the current NDK (r10b)...although you may have to add AndroidManifest.xml (blank) and and Application.mk that points to your Android.mk file.
I don't think it would be that difficult to modify the .mk file for the current libpcap version (1.6.2)
In case anyone ends up here in 2022+. You can now cross-compile for Android from the official source. Steps:
First, setup the NDK:
Download Android NDK (I used r21e) and extract to a directory of your choosing:
$ cd ~
$ mkdir Android
$ unzip android-ndk-r21e-linux-x86_64.zip
Prepare the environment variables for cross-compilation by placing the commands below (replace <YOUR_USER>) into a file named setup_env.sh (can be saved anywhere):
export NDK=/home/<YOUR_USER>/Android/android-ndk-r21e
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
export TARGET=aarch64-linux-android
export API=21
export AR=$TOOLCHAIN/bin/$TARGET-ar
export AS=$TOOLCHAIN/bin/$TARGET-as
export CC=$TOOLCHAIN/bin/$TARGET$API-clang
export CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
export LD=$TOOLCHAIN/bin/$TARGET-ld
export RANLIB=$TOOLCHAIN/bin/$TARGET-ranlib
export STRIP=$TOOLCHAIN/bin/$TARGET-strip
Now, build libpcap:
Download libpcap tar ball (e.g. https://www.tcpdump.org/release/libpcap-1.10.1.tar.gz)
Extract (in a directory of your choosing): tar xf libpcap-1.10.1.tar.gz
Prepare your env: source <path_to>/setup_env.sh
Change into the extract libpcap directory and configure: ./configure --host=aarch64-linux-android
I found the Makefile generated had the wrong linker set (line 48), so I had to change it to: LD = /home/<YOUR_USER>/Android/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/x86_64-linux-android/bin/ld
Finally, build: make
This build worked for me with running tcpreplay on a rooted Android, hopefully it works for other purposes as well!
I am trying to test OpenCV Android, on Android Studio, I am confused about how to include the NDK.
What I want to do is run the samples which come with OpenCV. Of the 6 samples provided I managed to run 4 successfully. The exceptions were face-detection and native-activity.
I suspect the reason is I have not set up my NDK correctly.
Googling I found a bunch of discussions but do not really understand them. This is my first time I am trying to work with both the NDK and OpenCV, and my Gradle understanding is limited.
I set an environment variable in my .bash_profile
export ANDROID_NDK=pathTo/android-ndk-r9
I do not understand how to get this to studio.
I see reference to jniFolder but do not understand what these are and should I care right now.
Stackoverflow.com/questions/17767557
tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->
pkgTask.jniFolders = new HashSet<File>()
pkgTask.jniFolders.add(new File(projectDir, 'native-libs'))
}
What am I supposed to do with this paste at the end of my build.gradle file ?
In summation, my questions are.
How do I get Android Studio to read the NDK variable ?
What exactly are the jniFolders ?
Is it enough just to paste at the end of my build.gradle file ?
Google Group Discussions on Gradle and NDK
For anyone coming across this this is how I resolved it apart from Xaviers anwser.
First I read OVERVIEW.html which comes with the NDK, in the docs directory.
I then compiled the .mk and .cpp files into an .so file. I did this inplace in the sample jni directory
This created the .so file in the libs folder which I copied to the destination as given by Xavier.
If you have libraries that you build with the ndk and want to put them in a gradle-enabled android project (using version 0.7.+ of the plugin), you can just put them in
src/main/jniLibs/<abi>/libfoo.so
for example:
src/main/jniLibs/armeabi-v7a/libfoo.so
src/main/jniLibs/x86/libfoo.so
and they'll get packaged automatically.
If you want to keep them in the native-libs folder you can put the following in your gradle file:
android {
sourceSets.main {
jniLibs.srcDirs = ['native-libs']
}
}
All this does really is tell gradle where the jniLibs folder for the main source set is (relative to the project root.)
The snippet you showed is doing something different. It's telling the package task to also include some native libraries. This was a hack that used to work in a previous version using undocumented API of the task that are no longer supported.
I have built a dynamic library in android using android build system. This library provides jni interface for functions inside it. Now I want to include this library in an application (.apk). I am using eclipse for application development. Now, how can I use the prebuild dynamice library (.so) in my application ? I tried putting it in a lib folder in my application but it is not working.
Any pointers are appreciated.
I am not using ndk to build my .so.
Since you write 'so' I think you're using NDK. If you're using NDK I don't know the answer.
If you're using the "Java" SDK, then in your library project go to Properties -> Android, and Check "Is Library". In your "apk" project, go to Properties -> Android -> Add . And your Library project should be available.
Also, any Library added in the "Java Build Path" Menu (again, in project properties) should be available in the APK in the end.
I know it's slightly old, but have you checked in the built APK to see if your .so library is there? Should be in the libs/armeabi folder.
Also, your .so file should be in lib/armeabi folder in your eclipse solution. I'm guessing the armeabi bit depends on which processor your .so file is build for.
Also, I know that if your library isn't called lib[name].so, it won't get copied when the apk is installed on the device. So:
libfoo.so copies
foo.so doesn't copy
foo.so doesn't copy
Also, you can use DDMS (its a view in eclipse) and it's file explorer to see if it's been copied to your device. It should be under data/data/[packagename]/lib.
Hope this helps a bit!
Andy.
I hit this same problem while building Qiqqa for Android. Under your eclipse android project, make sure you have a libs directory (not that it is plural libS not singular lib). Inside that create the armeabi/etc subdirs with their respectibe .so files.
Then when you build, eclipse will automatically pick up this libs directory and create the corresponding lib in your apk. System.loadLibrary("XXX") will then resolve to libXXX.so on your correct architecture...
Cheers,
Jimme