Android Studio, gradle and NDK integration

Tweet about this on TwitterShare on Google+Share on FacebookShare on LinkedInShare on RedditEmail this to someone

With the recent changes (release 0.7.3 around Dec 27), the new Android Build System starts to be really interesting also if you are using the NDK!

Now this is really easy to integrate native libraries in your package and generate APKs for different architectures while correctly handling version codes (for more information on why this may be important, please refer to my first article).

update 2015/08/10: this article remains fully up-to-date if you’re using the recent Android Studio and the stable Android gradle plugin (set android.useDeprecatedNdk=true inside gradle.properties). Another article on gradle-experimental is in the work!

update 2014/11/1: changed output.abiFilter to output.getFilter(com.android.build.OutputFile.ABI) in order to work with gradle 0.14

update 2014/09/19: I’ve added information and modified my sample build.gradle to demonstrate the brand new APK Splits feature introduced by the latest android gradle plugin (0.13)

update 2: I’ve modified the sample build.gradle file to make it call ndk-build scripts by itself.

update 1: Here is a screencast on how to set up a project with NDK sources from Android Studio:

Integrating .so files into your APK

If you are using Android Studio and need to integrate native libraries in your app, you may have had to use some complex methods before, involving maven and .aar/.jar packages… the good news is you don’t need these anymore 🙂

jniLibs

You only need to put your .so libraries inside the jniLibs folder under sub-directories named against each supported ABI (x86, mips, armeabi-v7a, armeabi), and that’s it !

Once it’s done, all the .so files will be integrated into your apk when you build it:

fatbinary

If the jniLibs folder name doesn’t suit you (you may generate your .so files somewhere else), you can set a specific location in build.gradle:

Building one APK per architecture, and doing it well !

You can use flavors to build one APK per architecture really easily, by using abiFilter property.

ndk.abiFilter(s) is by default set to all. This property has an impact on the integration of .so files as well as the calls to ndk-build (I’ll talk about it at the end of this article).

Let’s add some architecture flavors in build.gradle:

And then, sync your project with gradle files:

sync

You should now be able to enjoy these new flavors by selecting the build variants you want:

buildVariants

Each of these variants will give you an APK for the designated architecture:

thinbinary
app-x86-release-unsigned.apk

The fat(Release|Debug) one will still contain all the libs, like the standard package from the beginning of this blog post.

But don’t stop reading here! These arch-dependent APKs are useful when developing, but if you want to upload several of these to the Google Play Store, you have to set a different versionCode for each. And thanks to the latest android build system, this is really easy:

Automatically setting different version codes for ABI dependent APKs

The property android.defaultConfig.versionCode holds the versionCode for your app. By default it’s set to -1 and if you don’t change it, the versionCode set in your AndroidManifest.xml file will be used instead.

Hence if you want to be able to dynamically modify your versionCode, you need to first specify it inside your build.gradle:

But this is still possible to keep setting this variable only inside your AndroidManifest.xml if you retrieve it “manually” before modifying it:

Once it’s done, you can prefix the versionCode inside your different flavors:

Here I’ve prefixed it with 6 for x86, 4 for mips, 2 for ARMv7 and 1 for ARMv5. If you’re asking yourself why!? please refer to this paragraph I wrote before on architecture dependent APKs on the Play Store.

Improving multiple APKs creation and versionCode handling with APK Splits

Since version 0.13 of the android plugin, instead of having a product flavors to get multiple APKs, you can use splits to have a single build (and variant) that will produce multiple APKs (and it’s much cleaner and faster).

 

Compiling your C/C++ source code from Android Studio

If you have a jni/ folder in your project sources, the build system will try to call ndk-build automatically.

As of 0.7.3, this integration is only working on Unix-compatible systems, cf bug 63896. On Windows you’ll want to disable it so you can call ndk-build.cmd yourself. You can do so by setting this in build.gradle: this has been fixed 🙂

The current implementation is ignoring your Android.mk makefiles and create a new one on the fly. While it’s really convenient for simple projects (you don’t need *.mk files anymore !), it may be more annoying for projects where you need all the features offered by Makefiles. You can then disable this properly in build.gradle:

If you want to use the on-the-fly generated Makefile, you can configure it first by setting the ndk.moduleName property, like so:

 And you’re still able to set these other ndk properties:

  • cFlags
  • ldLibs
  • stl (ie: gnustl_shared, stlport_static…)
  • abiFilters (ie: “x86”, “armeabi-v7a”)

You can also set android.buildTypes.debug.jniDebuggable to true so it will pass NDK_DEBUG=1 to ndk-build when generating a debug APK.

If you are using RenderScript from the NDK, you’ll need also to set the specific property defaultConfig.renderscriptNdkMode to true.

If you rely on auto-generate Makefiles, you can’t easily set different cFlags depending on the target architecture when you’re building multi-arch APKs. So if you want to entirely rely on gradle I recommend you to generate different libs per architecture by using flavors like I’ve described earlier in this post:

My sample .gradle file

Putting this altogether, Here is one build.gradle file I’m curently using. It’s using APK Splits to generate multiple APKs, it doesn’t use ndk-build integration to still rely on Android.mk and Application.mk files, and doesn’t require changing the usual location of sources and libs (sources in jni/, libs in libs/). It’s also automatically calling ndk-build script from the right directory:

Troubleshooting

NDK not configured

If you get this kind of error:

This means the tools haven’t found the NDK directory. You have two ways to fix it: set the ANDROID_NDK_HOME variable environment to your NDK directory and delete local.properties, or set it manually inside local.properties:

No rule to make target

If you get this kind of error:

This may come from a current NDK bug on Windows, when there is only one source file to compile. You only need to add one empty source to make it work again.

Other issues

You may also find some help on the official adt-dev google group: https://groups.google.com/forum/#!forum/adt-dev 

Getting more information on NDK integration

The best place to get more information is the official project page:  http://tools.android.com/tech-docs/new-build-system.

You can look at the changelog and if you scroll all the way down you’ll also get access to sample projects dealing with NDK integration, inside the latest “gradle-samples-XXX.zip” archive.

Tweet about this on TwitterShare on Google+Share on FacebookShare on LinkedInShare on RedditEmail this to someone

Published by

Xavier Hallade

Software Engineer working at Intel Software and Service Group (SSG) in Paris, France. Google Developer Expert for Android. Helping developers to make a better use of Intel-based platforms, with a focus on the Android NDK.

92 thoughts on “Android Studio, gradle and NDK integration”

  1. Hi Xavier, thanks for the post. I have downloaded one .so file and trying to integrate with my project but getting unsatisifiedlinkerror and method not found exceptions when tried to call jni functions. And am using eclipse IDE, it would be helpful if you can write the same article for eclipse as well.

    Pradeep.

    1. Hi Pradeep,

      Maybe your .so files don’t get integrated correctly inside your APK, you can check this by opening it using any unzip program.
      If you’re not using gradle, the location where you should put your .so file isn’t jniLibs/(armeabi|x86|…) but libs/(armeabi|x86|…).
      If the .so files are there and get loaded, your problem may be the mapping between your Java and your native libraries – but this has more to do with your code than the Android tools.

  2. Hi Xavier, thanks for the reply. I think you are right lib is loaded successfully but jni call is failing, below is my logs:
    E/AndroidRuntime( 2976): java.lang.UnsatisfiedLinkError: quit

    when i tried to call a jni function from my onCreate:
    public class MainActivity extends Activity {

    static {
    System.loadLibrary(“tag”);
    System.loadLibrary(“neon”);
    System.loadLibrary(“faad2”);
    System.loadLibrary(“sdl-1.2”);
    System.loadLibrary(“mplayer”);
    }

    public native int isalbum(String paramString1, String paramString2);

    public native int ispaused();

    public native void nativeCommand(int paramInt1, int paramInt2, int paramInt3);

    public native void nativeExit();

    public native void play(String paramString, int paramInt);

    public native void quit();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    quit();
    }
    }

    am I calling the jni function in right way?

    Pradeep.

    1. No, you either need to implement your C function with this prototype:

      JNIEXPORT int JNICALL Java_com_lightbox_android_photoprocessing_MainActivity_quit(JNIEnv *env, jobject obj)

      or declare your Java quit() method as public native static void inside com.vnc.mplayer.MPlayer class so it fits with your current libmplayer.so

  3. Hi Xavier, I have compiled android-mplayer.c file in my .so lib which has defined quit function as below:
    JNIEXPORT int JNICALL Java_com_vnd_mplayer_MPlayer_quit(JNIEnv *env, jclass cls) {
    run_command_android(“quit”);
    }

    Pradeep.

  4. Ok, correct me if am wrong:
    I need to have MPlayer.java class file inside package com.vnd.mplayer, declare public native static void quit(); and also load libs inside this MPlayer class file?

    Pradeep.

  5. I have been importing my existing project in android studio which contain jni .so files and in android studio it also made the folder jniLibs and all .so files are there but while i run my app this cause error that the classdefnotfound, can’t load .so files blah….. blah….

  6. You can unzip your APK to see if your files are indeed integrated or not.
    Under jniLibs, your .so files are under armeabi, x86, etc folders ?
    Are you using latest versions of android plugin, Android Studio and gradle ?

  7. thanks for your response:-

    I have unzip the apk and I cant see the .so files let me know where this files should be in folder after unzip.

    yes I have included all the .so files Under jniLibs as instructed

    and I am using the
    Gradle 1.10
    ————————————————————

    Build time: 2013-12-17 09:28:15 UTC
    Build number: none
    Revision: 36ced393628875ff15575fa03d16c1349ffe8bb6

    Groovy: 1.8.6
    Ant: Apache Ant(TM) version 1.9.2 compiled on July 8 2013

    Android studio 0.5.3.

    please let me know how can I resolve this.

  8. the .so files inside the APK should be inside lib/armeabi/, lib/x86/, and so on.
    You haven’t done any refactoring that would require you to modify your native libraries ?
    Maybe you’re using proguard ? it shouldn’t obfuscate classes that contains methods defined as native.

  9. ok now i can see the lib folder with .so files,
    and one more thing this .so files are directly accessed by one javacv.jar file and i am calling this jar file.

  10. here is the logcat please help :

    03-31 15:47:04.512 14386-17481/com.packagename E/dalvikvm﹕ dlopen(“/data/app-lib/com.packagename-2/libopencv_core.so”) failed: dlopen failed: could not load library “../../lib/libtbb.so” needed by “libopencv_core.so”; caused by library “../../lib/libtbb.so” not found
    03-31 15:47:04.512 14386-17481/com.packagename E/dalvikvm﹕ dlopen(“/data/app-lib/com.packagename-2/libjniopencv_core.so”) failed: dlopen failed: could not load library “libopencv_core.so” needed by “libjniopencv_core.so”; caused by could not load library “../../lib/libtbb.so” needed by “libopencv_core.so”; caused by library “../../lib/libtbb.so” not found
    03-31 15:47:04.512 14386-17481/com.packagename W/dalvikvm﹕ Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/googlecode/javacv/cpp/opencv_core;
    03-31 15:47:04.512 14386-17481/com.packagename W/dalvikvm﹕ Exception Ljava/lang/NoClassDefFoundError; thrown while initializing Lcom/googlecode/javacv/cpp/opencv_imgproc;
    03-31 15:47:04.512 14386-17481/com.packagename W/dalvikvm﹕ Exception Ljava/lang/NoClassDefFoundError; thrown while initializing Lcom/googlecode/javacv/cpp/opencv_highgui;
    03-31 15:47:04.522 14386-17481/com.packagename W/dalvikvm﹕ threadid=21: thread exiting with uncaught exception (group=0x416e0e18)

  11. Hello! Can I ask question? I need implement pdf viewer in my android application(I’m using Android Studio), so what I can use for that ?Any libraries?

  12. Hi, XAVIER, I googled a lot but can’t find whether android studio supports ndk debug.

    Can I debug into ndk library code in the android studio.

    Or can I ndk debug a android generated app.

  13. Hi Xavier, maybe you can help me with this…

    I’m trying to create an Android Library that will include the spatialite native library. But when I try to deploy the APK into the Emulator I’m getting the following error:


    04-25 10:28:12.774 2532-2532/? D/dalvikvm﹕ No JNI_OnLoad found in /system/lib/libsqlite.so 0xaddc0590, skipping init
    04-25 10:28:12.774 2532-2532/? W/dalvikvm﹕ No implementation found for native Ljsqlite/Database;.internal_init:()V
    04-25 10:28:12.784 2532-2532/? W/dalvikvm﹕ Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Ljsqlite/Database;
    04-25 10:28:15.584 2532-2532/? D/AndroidRuntime﹕ Shutting down VM
    04-25 10:28:15.584 2532-2532/? W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xadad7ba8)
    04-25 10:28:15.674 2532-2532/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.rudder.android.facileguideslibrary.facileguidestest, PID: 2532
    java.lang.UnsatisfiedLinkError: Native method not found: jsqlite.Database.internal_init:()V
    at jsqlite.Database.internal_init(Native Method)
    at jsqlite.Database.(Database.java:956)

    I downloaded the last version of the Android Studio (0.5.2) and I have created an empty project (using Gradle) composed by 2 modules: a library and a test project.

    The example project can be downloaded here.

    I also downloaded the bradh-spatialiteandroid and compiled it using the given instructions. Getting the libjsqlite.so files for armeabi, armeabi-v7a and x86 architectures.

    As you could see in the project, I put the native libraries into the “src/main/jniLibs” folder, as you said in your post, and the final APK contains the libraries based on the flavor I used to generate the APK (armeabi-v7a).

    The contents of the final APK file is:
    AndroidManifest.xml
    classes.dex
    lib/armeabi-v7a/libjsqlite.so
    META-INF/…
    res/…
    resources.arsc

    The Library is loaded by the sqlite java classes copied from the bradh-spatialiteandroid project, as informed in the spatialite-android-tutorial. There we will find the “jsqlite.Database.java” class that is trying to load the library using the following instruction:

    static {
    try {
    System.loadLibrary(“sqlite”);
    } catch (Throwable t) {
    System.err.println(“Unable to load sqlite_jni: ” + t);
    }

    Thanks in advance!! I hope you can give me some light on that.
    Javier

    1. Hi,

      I think you made a typo, maybe you should load “jsqlite” instead of “sqlite” from Database.java.
      btw, your comment is a bit outside of the scope of this article. stackoverflow.com would be a better place for asking such questions.

  14. Hi Xavier,

    I’m trying to convert an existing Android.mk into Gradle format. One of the modules has a LOCAL_SHARED_LIBRARIES definition that links with prebuilt libraries. Do you know if and how that translates into the Gradle format?

    Thanks,
    Dennis

  15. Hi Dennis,
    Maybe you can get it working through the ldLibs var, but this will be hacky. It’s not supported yet so I think it’s better still using .mk files for now. I’ve updated my build.gradle file to show how to call ndk-build directly instead of relying on the android gradle plugin.

    1. I tried to add the local shared library names to the ldLibs, but ended up with “ld: error: cannot find -l…”. Any way to configure where ld looks to point to the local jniLibs in the project?

      Otherwise, I guess the only fall back is your ndk-build suggestion.

  16. Hi Xavier,

    Sorry if I sound too desperate 🙂

    I’m trying to start using Android Studio (latest 0.6.0 downloaded from the official site) for NDK development but I can’t get the studio to do anything with native code. It’s like it doesn’t even notice the ndk stuff in the project. I’ve tried adding the ndk {…} block in the defaultConfig block but that makes no difference (and tooltip tells it can’t resolve ‘ndk’).

    Is there some special plugin or something that needs to be installed to get this working?

    There seems to be two kind of comments in the internet: gradle & AS now support NDK, and that AS doesn’t still support it (see AS bug tracker feature request about it) . Which one is correct? I really would like to see this working since I’d rather not deal with eclipse anymore…

  17. There’s a problem with compiling on windows when using your sample gradle file in the ndkBuild task.

    I found the solution in this stack overflow link: http://stackoverflow.com/questions/19170850/commandline-in-build-gradle-causes-android-studio-0-2-10-build-to-fail

    Basically you should add a ‘cmd’ in front of the ‘ndk-build.cmd’ call.

    It should change to:

    task ndkBuild(type: Exec) {
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
    commandLine ‘cmd’, ‘ndk-build.cmd’, ‘-C’, file(‘src/main’).absolutePath
    } else {
    commandLine ‘ndk-build’, ‘-C’, file(‘src/main’).absolutePath
    }
    }

    1. I thought it was working at first, but realized that ndk-build wasn’t called at all.

      I added the /C command to cmd so it actually runs the specified command.

      This is the real fix:

      task ndkBuild(type: Exec) {
      if (Os.isFamily(Os.FAMILY_WINDOWS)) {
      commandLine 'cmd', '/C', 'ndk-build.cmd', '-C', file('src/main').absolutePath
      } else {
      commandLine 'ndk-build', '-C', file('src/main').absolutePath
      }
      }

      1. Ah wait, I have the same problem again, more or less.

        It all works if I run gradlew compileArmDebugJava from the android project root.

        Android Studio itself keeps having issues. Now I’m getting: ‘ndk-build.cmd’ is not recognized as an internal or external command,
        operable program or batch file.

        I even added it to the PATH and restarted Android Studio.

  18. Hi,
    On my system (Windows 8.1, Android Studio 0.8.4, Java 7u51 64-bits, the direct call to ndk-build.cmd is working.

    I don’t know what could be the cause of the issue you’re facing…
    What happens if you call ndk-build.cmd from the terminal panel that’s inside Android Studio ?

  19. Hello Man,
    you are a life saver dude.
    Got worked after too many search and pulled couple of hair, Got this article really informative and worked like a charm.

    Thank you very much dude..
    :)))))
    🙂

  20. Hi,

    I and many other have had problems with the instructions provided in the video. When it comes time to generate the C headers using javah, the directory “../../build/debug” doesn’t exist, nor do any of the directories contain a class file for my activity. I am new to Java/Android development, so I imagine there is a simple remedy/explanation, but after hours of searching and experimentation I have been unable to find an answer.

    Any help would be greatly appreciated,

    Thanks

  21. I have a C++ library using openCV, Eigen and Vfleat libraries all in C++ and I want to use NDK and JNI to be able to use the calls in the library available in Java. I would really appreciate it if you can guide me how to achieve it in Android Studio.

    Thanks

  22. I had the problem that disabling the jni srcDirs removed that from the android studio folder list.

    Instead I disabled the NdkCompile task:

    put this at the top of your gradle file:
    import com.android.build.gradle.tasks.NdkCompile

    and this before buildTypes:
    tasks.withType(NdkCompile) {
    compileTask -> compileTask.enabled = false
    }

  23. Hi, I am developing android app based on Opencv i-e, i can take the image in java part pass it to native(cpp) file and do image processing (using opencv) there get the final output and display it in java part.
    What i want to know is how can i debug the native part of my app???? I am using ANDROID STUDIO v1.0 stable. and Android ndk r10d.

  24. Thanks for the excellent guide. Is there a way to specify multiple modules with different cFlags and such using the Gradle automatic ndk-build way? It seems to just compile everything in the /jni folder into one module.

    1. There is no way to specify multiple ndk modules inside one project.
      You can still have several gradle projects with a jni folder for each of them but it will be messy if there are dependencies between them.
      The current automatic ndk-build way is deprecated anyway, so for such setup I think it’s better to rely on classic Android.mk/Application.mk and an independent ndk-build call.

      1. Thanks for the excellent post. Finally your post really helped to understand what has to be done for a ndk project. THANK YOU!

        I’m using the latest build (AS 1.02, and latest gradle 2.2.1 I think).
        I’m getting ndkbuild=null error.
        I followed your website to create the tasks exactly as you mentioned.
        My questions are> Do I disable Android.mk? what am i missing here? THanks!

        sourceSets.main {
        jniLibs.srcDir ‘src/main/libs’ //set .so files location to libs
        jni.srcDirs = [] //disable automatic ndk-build call
        }

        tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn ndkLibsToJar
        }

        task ndkBuild(type: Exec, description: ‘Compile JNI source via NDK’) {
        def ndkDir = project.plugins.findPlugin(‘com.android.application’).getNdkFolder()
        println(‘executing ndkBuild’)
        println(ndkDir)
        }
        task ndkLibsToJar(type: Zip, dependsOn: ‘ndkBuild’, description: ‘Create a JAR of the native libs’) {
        // def buildDir =’src/main/’
        destinationDir new File(buildDir, ‘libs’)
        baseName ‘ndk-libs’
        extension ‘jar’
        from(new File(buildDir, ‘libs’)) { include ‘**/*.so’ }
        into ‘lib/’
        }

        1. Hi,

          you are currently disabling the automatic ndk-build integration and you need to have your own valid Android.mk file.
          But you have several mistakes in your configuration:

          • You should remove the ndkLibsToKar task since that’s an old hack to include .so files in a APK. Specifying the jniLibs.srcDir like you did is enough.
          • Once you’ve removed it, you should replace the dependency you added to it from compileTask, to a dependency to the ndkBuild task.
          • your ndkBuild task doesn’t look like the one I’ve proposed, it’s not doing anything here. You can copy/paste mine instead
  25. How to find the Gradle plugin version? Plugins showing version as N/A. I am using Android Studio 1.0.2.
    .
    Thanks for this very helpful post
    Harsha

      1. I think the build time increased since i use the split feature… (but i’m not one hundred percent sure about that^^) and it’s not relevant for me to have this feature in a development way.

        1. The split feature is quite light, maybe your build time increase comes from somewhere else.
          Also, this feature automatically allows you to push smaller APKs to devices/emulators during development, it saves quite some time when you deal with big libraries.

          1. I fixed my problem by setting a project property enableSplitAbi by command line :

            ./gradlew assembleDebug -PenableSplitAbi

            and retrive it in the build.gradle file like this :

            project.hasProperty(“enableSplitAbi”);

  26. Thanks for your response. A big thank you for pointing out the corrections in my Android.mk and build.gradle.
    I made the correction and I could compile.
    The library (SoundTouch) that I’m using supports only Androids with an FPU (armeabi-v7a). I’m able to compile and create (.so) file for arm64-v8a,arm64-v7a,mips64, x86-64, but I am getting an error for arm:

    Error:error: cannot convert ‘soundtouch::SAMPLETYPE* {aka short int*}’ to ‘float*’ for argument ‘2’ to ‘void convertInput(jbyte*, float*, int, int)’

    My questions are:
    1. Is it a good idea to disable arm? If so, How could I disable arm?
    2. I found that if you include V=1 option in ndk-build, that option is supposed to show all the commands being executed (for debugging purposes).
    How do I include in ndk-build command:
    Below is my ndk-build command:
    sourceSets.main {
    // jniLibs.srcDir ‘src/main/libs’ //set .so files location to libs
    jni.srcDirs = [] //disable automatic ndk-build call
    }

    tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn ndkBuild
    }

    task ndkBuild(type: Exec, description: ‘Compile JNI source via NDK’) {
    def ndkDir = project.plugins.findPlugin(‘com.android.application’).getNdkFolder()

    commandLine “$ndkDir/ndk-build”,
    ‘NDK_PROJECT_PATH=build/intermediates/ndk’,
    ‘NDK_LIBS_OUT=src/main/jniLibs’,
    ‘APP_BUILD_SCRIPT=src/main/jni/Android.mk’,
    ‘NDK_APPLICATION_MK=src/main/jni/Application.mk’

    println(‘executing ndkBuild’)
    println(ndkDir)
    }

    Thank you!

  27. I have figured out how to disable arm.
    In Application.mk file I included all the architecture except arm.
    I still don’t know how to include V=1 option in ndk-build.

  28. You’re fine disabling armeabi target, unless you want to support really old and slow devices.

    To include V=1 to your ndk-build command, this should work:

    commandLine “$ndkDir/ndk-build”,
    ‘V=1’,
    ‘NDK_PROJECT_PATH=build/intermediates/ndk’,

  29. Hello

    thank you for great article on topic that has brought me big troubles recently. one question. how can I create using gradle build files project similar to two-libs sample from android ndk? one module with one source file creates a static library, another module uses this static library, adds some other sources and builds a dynamic library, that I can load from within Android code and use there. Your help would be greatly appreciated.

    PS is there any correct way how to take a NDK sample and import it to Android Studio? ( and maybe convert to gradle build system )

    Thanks a lot in advance!

    Marek

    1. Thanks.
      There is no way to have dependencies between NDK modules (like with two-libs sample) using the built-in NDK support.
      You have to deactivate it and rely on ndk-build and *.mk files, as described in the article.
      Importing a NDK sample to Android Studio actually takes care about the conversion to the gradle build system. But since it doesn’t overcome its limitations, it’s not always properly working.
      You can also find some old Android Studio ndk samples from the bottom of this page: http://tools.android.com/tech-docs/new-build-system (direct link:
      http://tools.android.com/tech-docs/new-build-system/gradle-samples-0.14.4.zip?attredirects=0&d=1)

  30. Hi, could you please elaborate how to make working abi splits if my native code is in a library module (not in the application module) and is built with “ndk-build”.

    app.gradle: http://pastebin.com/B9rFbdNL
    lib.gradle: http://pastebin.com/pY7me32c

    As a result i receive APK’s with all platform SO libs. The ABI filter doesn’t seem to work. If i remove ndkLibsToJar i receive APK’s without any SO libs inside. :S

    1. Remove the ndkLibsToJar task and set sourceSets.main.jniLibs.srcDir ‘src/main/libs’ to integrate your .so files that are inside libs/ (the default location is jniLibs).
      You can also remove the split configuration from your library, it’s only for your application.

  31. Hi Xavier,
    I’m using a third party library “SoundTouch”.
    I’m using ndk r-10d and Android Studio1.02.
    I followed all your steps above that you mentioned and I was able to build .so successfully in my jnilibs folder.

    I have a .java that calls the static method to load my library.
    In that java class as you mentioned I have some native method
    calls.

    I created a JNI.h file for that java file using javah tool.
    I copied that .h file and renamed as .cpp file and have the implementation for those methods. That .cpp file also has the extern c implementation of those native methods.

    When I run the app, I’m getting the “exception” error without any insight of what the error. Basically the app crashes.

    My questions:
    1. How can I make sure that my lib is loaded even though I see .so file in my folder?
    2. How do I debug my native code? I tried to add V=1 in ndkbuild but my build fails if I add that option.

    I’m stuck in this issue,. Could you please send me some pointers where I debug my native code?

    Thanks!

  32. Hi Xavier, thanks for the awesome article, helped me a ton. I’m using the latest Android Studio 1.1.0, it no longer support the following:

    android.buildTypes.debug.jniDebugBuild

    Instead, it should be:

    android.buildTypes.debug.jniDebuggable

    Hope that makes sense!

  33. Hello Xavier,
    Would you have an advice :
    I migrated my project from Eclipse to Android and one of my library use C++ code . I try to recompile my C/C++ source code from Android Studio with all jni, jniLibs, gradle build configured as advised above but i still have the “Execution failed for task ‘:tesstwo:ndkBuild’.> A problem occurred starting process ‘command ‘ndk-build.cmd” .
    The only difference with you example is my module is a libray that i use in my main project (local properties in main project in of course defined with ndk-dir).
    I am stuck for half a day so i would be glad if you had time to provide me a tips. Thanks. CU

    1. You should be able to get the error message emitted by the command. You can get it from Android Studio messages tab, or by executing “gradlew :tesstwo:ndkBuild” from your project.

  34. The article helps me a log.

    Could you tell me how to set NDK_DEBUG=1 for debug build in classic Android.mk/Application.mk.

  35. Hi.
    Your article is very useful, I am trying to integrate one .so file using the new gradle version. I created an OpenSSL FIPS library follow the wiki for that, now I have the .so file and i am putting it in the jniLibs, when i compile my APK I see the file inside it, but now my problem is that I am creating a wrapper class to link the .so with java, I am plannig to put there the methods that i am going to use in order to call from java using the native modifier.
    But my problem is that i have not found the way to link the .so with my wrapper.c class, any advice to achieve that? I tried using the ldLibs in my gradle file but it doesn’t work.
    Thanks in advice.

    1. If you need to have a native dependency on another .so file, as you describe it, the best is to stick to the classic NDK way, not the gradle specific one yet: use an Android.mk file, declare your .so as a PREBUILT_SHARED_LIBRARY and make your module depend on it using LOCAL_SHARED_LIBRARIES.

  36. Hi, Xavier, your article is so helpful and up to date. These days, the new Android Studio 1.3.1 is released and I found your article explained very important improvement in NDK integration. I know the convenience of using new Android Studio, but I still cannot find a way to integrate native OpenCV for C++, because I want to use the local native OpenCV C++ code. Is it not necessary to use Android.mk? and how to configure the Gradle? I am novice in this part and really confused, could you help me… Thanks!

  37. Hi Xavier,

    I am using android-ndk-r10e and i am trying to use it for a project that will help me interact with hardware pins from my android app. Now when i try to sync it with gradle. It says that i need to set the android.useDeprecatedNdk property to true. But when i do it shows the error that useDeprecatedNdk is not defined. What should be done?? Any ideas??

      1. The problem is that i am not able to find any gradle.properties file. The only file that i have is gradle-wrapper.properties or local.properties.

        Should i write the property in gradle-wrapper.properties ?

  38. In case they haven’t been previously reported, a couple of broken links for downloading samples, one on this page and one on the tools site:

    (From your reply on February 12, 2015 at 1:34 pm on this page, http://ph0b.com/android-studio-gradle-and-ndk-integration/):
    http://tools.android.com/tech-docs/new-build-system/gradle-samples-0.14.4.zip?attredirects=0&d=1

    (Linked from http://tools.android.com/tech-docs/new-build-system near bottom of page in sentence “You can download a small bundle containing a few different (mostly empty) projects that show some of the build features: here”):
    http://tools.android.com/tech-docs/new-build-system/gradle-samples-0.3.zip?attredirects=0&d=1

    Do you know if these are available elsewhere? Seem like good resources.

  39. Debugging C++ in Android Studio using legacy NDK support

    Is there any way to use Android Studio to debug C++ without migrating fully to gradle-experimental?

    Due to complexity of our app (multiple static libs built using a set of finely tuned Android.mk files) and lack of 3rd party support for gradle-experimental (required for our crash/stats reporting service) we are unable to migrate to gradle-experimental and must continue with the legacy NDK support as instructed on this webpage.

    For this reason we have also stayed with the legacy android project structure (no “app” folder) and continue to use Eclipse solely for C++ debugging.

    So is there any way to provide C++ debugging using Android Studio but without migrating fully to the new gradle-experimental approach (which would break too many things in our app)?

    Thank you

  40. I’m porting a project from Eclipse to Android Studio.

    I’m getting the error undefined reference to `__system_property_get’. However, the old project builds just fine using Ant and Eclipse.

    Is there anything I need to add to the ndk section of build.gradle?

    1. __system_property_get doesn’t exist anymore if you’re compiling against android-21+. You need to specificy an earlier APP_PLATFORM, by using the new NDK plugin or regular Makefiles.

  41. Super article.

    One thing I’ve noticed happening to me with AS 1.4 is that a clean build would yield an aar with no native libraries packaged inside.

    I had to make ‘tasks.withType(Copy)’ depend on my ndk build task rather than ‘tasks.withType(JavaCompile)’.

Leave a Reply

Your email address will not be published. Required fields are marked *