Android studio, gradle and NDK
Solution 1
We have released a first version of the integration as a preview in 1.3: http://tools.android.com/tech-docs/android-ndk-preview
The integration will stay a preview even after 1.3 becomes final. No current ETA as to when it'll be final (as of 2015/07/10).
More information here: http://tools.android.com/tech-docs/android-ndk-preview
Solution 2
UPDATE: The Android Studio with NDK support is out now: http://tools.android.com/tech-docs/android-ndk-preview
For building with a script the gradle solution below should work:
I am using my build script and added to my file (Seems to work for 0.8+
): This seems to be equivalent to the solution below (but looks nicer in the gradle file):
android {
sourceSets {
main {
jniLibs.srcDirs = ['native-libs']
jni.srcDirs = [] //disable automatic ndk-build
}
}
}
The build unfortunately does not fail if the directory is not present or contains no .so
files.
Solution 3
With the update of Android Studio to 1.0, the NDK toolchain support improved immensely (note: please read my updates at the bottom of this post to see usage with the new experimental Gradle plugin and Android Studio 1.5).
Android Studio and the NDK are integrated well enough so that you just need to create an ndk{} block in your module's build.gradle, and set your source files into the (module)/src/main/jni directory - and you're done!
No more ndk-build from the command line.
I've written all about it in my blog post here: http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/
The salient points are:
There are two things you need to know here. By default, if you have external libs that you want loaded into the Android application, they are looked for in the (module)/src/main/jniLibs by default. You can change this by using setting sourceSets.main.jniLibs.srcDirs in your module’s build.gradle. You’ll need a subdirectory with libraries for each architecture you’re targeting (e.g. x86, arm, mips, arm64-v8a, etc…)
The code you want to be compiled by default by the NDK toolchain will be located in (module)/src/main/jni and similarly to above, you can change it by setting sourceSets.main.jni.srcDirs in your module’s build.gradle
and put this into your module's build.gradle:
ndk {
moduleName "SeePlusPlus" // Name of C++ module (i.e. libSeePlusPlus)
cFlags "-std=c++11 -fexceptions" // Add provisions to allow C++11 functionality
stl "gnustl_shared" // Which STL library to use: gnustl or stlport
}
That's the process of compiling your C++ code, from there you need to load it, and create wrappers - but judging from your question, you already know how to do all that, so I won't re-hash.
Also, I've placed a Github repo of this example here: http://github.com/sureshjoshi/android-ndk-swig-example
UPDATE: June 14, 2015
When Android Studio 1.3 comes out, there should be better support for C++ through the JetBrains CLion plugin. I'm currently under the assumption that this will allow Java and C++ development from within Android Studio; however I think we'll still need to use the Gradle NDK section as I've stated above. Additionally, I think there will still be the need to write Java<->C++ wrapper files, unless CLion will do those automatically.
UPDATE: January 5, 2016
I have updated my blog and Github repo (in the develop branch) to use Android Studio 1.5 with the latest experimental Gradle plugin (0.6.0-alpha3).
http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/ http://github.com/sureshjoshi/android-ndk-swig-example
The Gradle build for the NDK section now looks like this:
android.ndk {
moduleName = "SeePlusPlus" // Name of C++ module (i.e. libSeePlusPlus)
cppFlags.add("-std=c++11") // Add provisions to allow C++11 functionality
cppFlags.add("-fexceptions")
stl = "gnustl_shared" // Which STL library to use: gnustl or stlport
}
Also, quite awesomely, Android Studio has auto-complete for C++-Java generated wrappers using the 'native' keyword:
However, it's not completely rosy... If you're using SWIG to wrap a library to auto-generate code, and then try to use the native keyword auto-generation, it will put the code in the wrong place in your Swig _wrap.cxx file... So you need to move it into the "extern C" block:
UPDATE: October 15, 2017
I'd be remiss if I didn't mention that Android Studio 2.2 onwards has essentially 'native' (no pun) support for the NDK toolchain via Gradle and CMake. Now, when you create a new project, just select C++ support and you're good to go.
You'll still need to generate your own JNI layer code, or use the SWIG technique I've mentioned above, but the scaffolding of a C++ in Android project is trivial now.
Changes in the CMakeLists file (which is where you place your C++ source files) will be picked up by Android Studio, and it'll automatically re-compile any associated libraries.
Solution 4
In Google IO 2015, Google announced full NDK integration in Android Studio 1.3.
It is now out of preview, and available to everyone: https://developer.android.com/studio/projects/add-native-code.html
Old answer: Gradle automatically calls ndk-build
if you have a jni
directory in your project sources.
This is working on Android studio 0.5.9 (canary build).
-
Either add
ANDROID_NDK_HOME
to your environment variables or addndk.dir=/path/to/ndk
to yourlocal.properties
in your Android Studio project. This allows Android studio to run the ndk automatically. -
Download the latest gradle sample projects to see an example of an ndk project. (They're at the bottom of the page). A good sample project is
ndkJniLib
. -
Copy the
gradle.build
from the NDK sample projects. It'll look something like this. Thisgradle.build
creates a different apk for each architecture. You must select which architecture you want using thebuild variants
pane.apply plugin: 'android' dependencies { compile project(':lib') } android { compileSdkVersion 19 buildToolsVersion "19.0.2" // This actual the app version code. Giving ourselves 100,000 values [0, 99999] defaultConfig.versionCode = 123 flavorDimensions "api", "abi" productFlavors { gingerbread { flavorDimension "api" minSdkVersion 10 versionCode = 1 } icecreamSandwich { flavorDimension "api" minSdkVersion 14 versionCode = 2 } x86 { flavorDimension "abi" ndk { abiFilter "x86" } // this is the flavor part of the version code. // It must be higher than the arm one for devices supporting // both, as x86 is preferred. versionCode = 3 } arm { flavorDimension "abi" ndk { abiFilter "armeabi-v7a" } versionCode = 2 } mips { flavorDimension "abi" ndk { abiFilter "mips" } versionCode = 1 } fat { flavorDimension "abi" // fat binary, lowest version code to be // the last option versionCode = 0 } } // make per-variant version code applicationVariants.all { variant -> // get the version code of each flavor def apiVersion = variant.productFlavors.get(0).versionCode def abiVersion = variant.productFlavors.get(1).versionCode // set the composite code variant.mergedFlavor.versionCode = apiVersion * 1000000 + abiVersion * 100000 + defaultConfig.versionCode } }
Note that this will ignore your Android.mk and Application.mk files. As a workaround, you can tell gradle to disable atuomatic ndk-build call, then specify the directory for ndk sources manually.
sourceSets.main {
jniLibs.srcDir 'src/main/libs' // use the jni .so compiled from the manual ndk-build command
jni.srcDirs = [] //disable automatic ndk-build call
}
In addition, you'll probably want to call ndk-build in your gradle build script explicitly, because you just disabled the automatic call.
task ndkBuild(type: Exec) {
commandLine 'ndk-build', '-C', file('src/main/jni').absolutePath
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
Solution 5
I found "gradle 1.11 com.android.tools.build:gradle:0.9.+" supports pre-build ndk now, you can just put the *.so in the dir src/main/jniLibs. when building gradle will package the ndk to the right place.
here is my project
Project: |--src |--|--main |--|--|--java |--|--|--jniLibs |--|--|--|--armeabi |--|--|--|--|--.so files |--libs |--|--other.jar
Related videos on Youtube
Comments
-
plaisthos over 3 years
I am very new to this whole gradle and Android Studio support. I have managed to convert my android project to gradle using the export option.
But I am looking for some documentation or start point how to integrate the NDK build into the gradle build process.
If possible I also need some sort of "after" stage that copies the build binaries (.so files) to the asset directory.
-
Ahmad Ali Nasir over 10 yearsI have posted my answer in the below mentioned link stackoverflow.com/questions/20900814/…
-
Sean Beach over 9 yearsNew readers: Be aware this question was initially asked during the Android Studio beta period; the answer has changed over time. Pay attention to the Gradle version mentioned in the answers, as well as when the answers were actually posted.
-
plaisthos almost 9 yearsIf something really changes I will edit the question to relect the status
-
Vikasdeep Singh almost 9 yearsAndroid Studio 1.3 at canary channel fully supports NDK. Reference: tools.android.com/download/studio/canary/latest
-
fastr.de almost 9 yearsJune 18th, 2015: Android Studio 1.3 Beta is now available in the beta channel! Sorry, this build does not yet contain the C/C++ support; source: tools.android.com/recent/androidstudio13betaavailable
-
tarn over 8 yearsThis solution is work, without code [Adding .so Library in Android Studio 1.0.2][1] [1]: stackoverflow.com/questions/24357687/…
-
plaisthos over 8 years@user1307559 That solution is not a solution for someone who needs to work with/compile the c/c++ files
-
Biswajit Karmakar about 8 yearsAndroid Studio, gradle and NDK integration step by step ph0b.com/android-studio-gradle-and-ndk-integration
-
-
plaisthos over 10 yearsYeah. That only works well if you don't change your code native often. And you will have to include binary jar files in the repository. Otherwise you end up with a build script that creates a jar on fly.
-
dbro over 10 yearsI've modified Android's Hello-JNI example with a simple bash script that wraps
ndk-build
, generates.jar
s for each.so
and places them in gradle's build path to ease this pain. Check it out. -
powder366 over 10 yearsThis does not work anymore with the new Android Studio version, workaround?
-
powder366 over 10 yearsWould be great if I could use NDK and command completion with debugging under Android Studio (and Gradle support)
-
Leandros over 10 years@powder366 See my answer.
-
user19108801 over 10 yearsA bit of Groovy magic:
tasks.withType(com.android.build.gradle.tasks.PackageApplication) { it.jniFolders = [file("libs")] as Set }
. Thank you guys for help! -
Ryan Heitner over 10 yearsHow can we see the sample mentiuoned in 0.7.2 ndkJniLib ?
-
plaisthos over 10 yearsIs there any documentation to that feature? I could not find any. At the moment that seems to completly ignore my Android.mk/Application.mk.
-
Anthony over 10 yearsI haven't found any. It may have snuck into the build half-baked. I'm on windows so I can only confirm that it fails on trying to call the unix ndk-build script. There'd be no other reason to call that then to integrate native compile in gradle. Are you in unix?
-
Alex Cohn over 10 years
-
Alpine about 10 yearsit actually expects to find prebuilt *.so files in jniLibs.srcDirs
-
Anthony about 10 yearsI'd disagree based on the fact that it crashes calling ndk-build which absolutely isn't necessary if it requires built libraries. I cannot confirm since I don't have the time to vm Linux right now.
-
plaisthos almost 10 yearsYes. But that only works under Unix platforms and also limited if you a more complex than very simple ndk configuration/makefiles.
-
Cypress Frankenfeld almost 10 yearsYes, it will autogenerate makefiles for the limited things that you can set in the gradle build file, however there is a workaround. I added it to my answer.
-
plaisthos almost 10 yearsI think the jniLibs.srcDirs approach is cleaner than this since you can use abiFilter/flavours but your approach should also work.
-
alice.harrison over 9 yearsI'm doing exactly as instructed in my current project, but the NDK stuff still isn't getting built. Any ideas? It seems like it's building everything else, but just skipping the jni stuff.
-
personne3000 over 9 yearsUseful for using libraries such as SqlCipher
-
Pandiri Deepak over 9 yearsWhat is the procedure for android Studio 0.8.9
-
plaisthos over 9 yearsIt should still work with Android 0.8.9. Note there is no real official nice solution (as in developing ndk from Android Studio).
-
Pandiri Deepak over 9 yearsBut this doesnt work for me.. My tree is like this MyProj > -app> -native-libs> -armeabi-v7a> -a.so -b.so -c.so
-
Pandiri Deepak over 9 years@plaisthos: can u show me the project structure, where can i keep these .so files. please.
-
plaisthos over 9 yearsmy structure is as you described. Double check what you are doing and that .so files really are not in the apk (unzip)
-
Cameron Lowell Palmer over 9 yearsThe call to ndk-build will only work at the command-line not from within Android Studio.
-
plaisthos over 9 yearsSee see my own answer. That is the workaround I am currently using but it is not really a solution.
-
Shravan over 9 years@GREnvoy - How do we configure the right NDK builder in Android studio ? Can you plz give me the steps ? :)
-
Brian S over 9 years@Shravan - I used this tutorial to start software.intel.com/en-us/videos/…
-
Brian S over 9 years@Shravan - I also created a new answer with more of what I did. I hope that helps.
-
Leo supports Monica Cellio over 9 yearsI confirm that the sourceSets solution works on AS 1.0.2. Thanks!
-
SJoshi over 9 years@Shravan Much like GREnvoy, I've also created an answer with instructions on the new Android Studio: stackoverflow.com/a/27737154/992509 This current answer was correct last May, but Android Studio has just built in NDK with Gradle in Android Studio, so some of the other answers are a bit more correct now...
-
umbreonben over 9 years@NannuoLei thanks, I tried but I am getting a problem where the .so are not being generated. Everything else seems to work, but when I run the apkg in the emulator, it complains it cannot load the shared object.
-
Leo supports Monica Cellio over 9 years@aaa90210 is your emulator based on an x86 image? By default NDK will just produce an ARMEABI library, if you want to build an x86 image you can add this line into Application.mk: APP_ABI := armeabi x86
-
tonga over 9 years@plaisthos Thanks a lot for pointing out the right direction! The second line in the gradle script
jni.srcDirs = [] //disable automatic ndk-build
is very important since it will prevent Android Studio from rebuilding C/C++ source code. I have been trying to figure this out for two days until I saw your post and this solved my problem. I really think NDK build is better separately built by Android.mk command line makefile only, not by gradle script since C/C++ has been built by Makefile for more than 40 years! -
fawkes over 9 yearsput the *.so in (module)/src/main/jniLibs
-
Sean Beach over 9 yearsPosted January 20th, 2015. I downvoted this answer because it is now outdated. Unfortunately, I have not found a reliable, updated answer. @Xavier, if you could point us in the right direction with a comment, or add a comment to the answer you feel is most appropriate, it would be much appreciated!
-
Sean Beach over 9 yearsAlthough this is not the most recent answer, it seems likely to be the most accurate. Pay special attention to step 3: "Download the latest gradle sample projects".
-
Xavier Ducrohet over 9 years@DirtyBeach Why is it outdated? There still isn't an integration of the NDK in Studio. We are working on it but no ETA at this time.
-
Sean Beach over 9 yearsMy action was based upon how I was defining "integration". I understood it to mean "a way to use the NDK with gradle" which now does exist, albeit none of them are fantastic solutions. However, based on your comment, it seems your team has something else in mind for what a true integration could be. I retract my previous statement.
-
Cypress Frankenfeld about 9 years@CameronLowellPalmer, did you add your NDK path to local.properties? ndk.dir=/path/to/ndk
-
Cameron Lowell Palmer about 9 yearsOf course. For some reason my comment now seems out of context. Not sure what I was referring to at the time. I actually have a very similar answer at stackoverflow.com/questions/21096819/….
-
sherpya about 9 yearsI use this hack instead of disabling src dir so I can edit c/c++ files within the ide
tasks.all { task -> if (task.name.contains('Ndk')) task.enabled = false }
-
Cypress Frankenfeld almost 9 yearsNDK integration was announced during Google IO 2015. It's available in Android Studio 1.3 (preview can be downloaded soon. I'll post a link when it's available).
-
shul almost 9 years@CypressFrankenfeld: why does it say its in the stable channel when its not? where should it be? thanks!
-
Cypress Frankenfeld almost 9 yearsIt's not in the stable channel. It's in the canary channel
-
AbdulMomen عبدالمؤمن almost 9 yearsit worked with me. PS: anyone seeing this answer, don't forget to change
Java_me_mattlogan_ndktest_MainActivity_stringFromJNI
to your own :) -
fastr.de almost 9 yearsAndroid-Studio 1.3 RC1 with NDK-Support is now available in the Canary-Channel sites.google.com/a/android.com/tools/download/studio/canary/…
-
Maadiah almost 9 yearsI have tried the 1.3 stable version, the native code debug still not working
-
HYS over 8 yearsUpdate: please note that in the newer Android Studios (at least in 1.5) the native code is much better incorporated, and it is not necessary to do this separate task for packaging your code.
-
pt123 over 8 yearswhy is NDEBUG always set when using Android Studio, even on debug builds
-
Dmitry Zaytsev over 8 yearsDownvoted. I must say that state of NDK integration is very frustrating. Even though integration was announced on Google I/O 2015, it's still not even close to be a production-ready solution with no ETA available. I understand that topic might be very complicated from the inside, but from the outside (from developer perspective) it just seems that Google does not care about NDK.
-
Arpan about 8 yearsSyntax highlighting, inline compiler broken with AS 2.0 update. See this, need help. stackoverflow.com/questions/36567110/…
-
SJoshi over 6 yearsThis answer was correct at time of posting, but is pretty dated now - anyone reading this question should take note of the Android Studio versions.