157

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.

Cameron Lowell Palmer
  • 21,528
  • 7
  • 125
  • 126
plaisthos
  • 6,255
  • 6
  • 35
  • 63
  • I have posted my answer in the below mentioned link http://stackoverflow.com/questions/20900814/add-pre-built-so-files-in-project-using-gradle-0-7-3 – Ahmad Ali Nasir Jan 06 '14 at 11:23
  • 25
    New 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. – Sean Beach Jan 20 '15 at 21:00
  • If something really changes I will edit the question to relect the status – plaisthos Jun 02 '15 at 10:39
  • Android Studio 1.3 at canary channel fully supports NDK. Reference: http://tools.android.com/download/studio/canary/latest – Vikasdeep Singh Jun 05 '15 at 13:07
  • June 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: http://tools.android.com/recent/androidstudio13betaavailable – fastr.de Jun 20 '15 at 17:09
  • This solution is work, without code [Adding .so Library in Android Studio 1.0.2][1] [1]: http://stackoverflow.com/questions/24357687/how-to-include-so-library-in-android-studio#28430334 – tarn Aug 11 '15 at 13:38
  • @user1307559 That solution is not a solution for someone who needs to work with/compile the c/c++ files – plaisthos Aug 11 '15 at 14:09
  • Android Studio, gradle and NDK integration step by step http://ph0b.com/android-studio-gradle-and-ndk-integration/ – Biswajit Karmakar Mar 29 '16 at 19:03

23 Answers23

86

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

Xavier Ducrohet
  • 28,383
  • 5
  • 88
  • 64
  • 2
    Would be great if I could use NDK and command completion with debugging under Android Studio (and Gradle support) – powder366 Dec 19 '13 at 13:23
  • 1
    @GREnvoy - How do we configure the right NDK builder in Android studio ? Can you plz give me the steps ? :) – Shravan Dec 13 '14 at 16:58
  • 1
    @Shravan - I used this tutorial to start https://software.intel.com/en-us/videos/using-the-ndk-with-android-studio – Brian S Dec 15 '14 at 13:05
  • 1
    @Shravan - I also created a new answer with more of what I did. I hope that helps. – Brian S Dec 15 '14 at 13:14
  • 1
    @Shravan Much like GREnvoy, I've also created an answer with instructions on the new Android Studio: http://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... – SJoshi Jan 02 '15 at 15:12
  • Posted 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 Jan 20 '15 at 20:57
  • 7
    @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. – Xavier Ducrohet Jan 27 '15 at 00:06
  • 2
    My 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. – Sean Beach Jan 27 '15 at 19:43
  • 2
    NDK 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). – Cypress Frankenfeld May 28 '15 at 18:13
  • @CypressFrankenfeld: why does it say its in the stable channel when its not? where should it be? thanks! – shul Jun 04 '15 at 06:38
  • It's not in the stable channel. It's in the canary channel – Cypress Frankenfeld Jun 05 '15 at 16:46
  • 1
    Android-Studio 1.3 RC1 with NDK-Support is now available in the Canary-Channel https://sites.google.com/a/android.com/tools/download/studio/canary/latest – fastr.de Jul 10 '15 at 11:15
  • I have tried the 1.3 stable version, the [native code debug still not working](http://stackoverflow.com/questions/31786559/breakpoints-in-native-code-can-not-be-triggered-in-android-studio-13) – Maadiah Aug 03 '15 at 12:50
  • Downvoted. 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. – Dmitry Zaytsev Jan 24 '16 at 23:12
  • This answer was correct at time of posting, but is pretty dated now - anyone reading this question should take note of the Android Studio versions. – SJoshi Oct 15 '17 at 07:26
44

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.

Kevin Crain
  • 1,905
  • 1
  • 19
  • 28
plaisthos
  • 6,255
  • 6
  • 35
  • 63
  • 5
    This does not work anymore with the new Android Studio version, workaround? – powder366 Dec 19 '13 at 10:47
  • 2
    A bit of Groovy magic: `tasks.withType(com.android.build.gradle.tasks.PackageApplication) { it.jniFolders = [file("libs")] as Set }`. Thank you guys for help! – trnl Dec 30 '13 at 23:40
  • What is the procedure for android Studio 0.8.9 – Pandiri Deepak Sep 30 '14 at 07:58
  • It should still work with Android 0.8.9. Note there is no real official nice solution (as in developing ndk from Android Studio). – plaisthos Sep 30 '14 at 08:21
  • But this doesnt work for me.. My tree is like this MyProj > -app> -native-libs> -armeabi-v7a> -a.so -b.so -c.so – Pandiri Deepak Sep 30 '14 at 10:50
  • @plaisthos: can u show me the project structure, where can i keep these .so files. please. – Pandiri Deepak Sep 30 '14 at 11:41
  • my structure is as you described. Double check what you are doing and that .so files really are not in the apk (unzip) – plaisthos Sep 30 '14 at 12:29
  • I confirm that the sourceSets solution works on AS 1.0.2. Thanks! – Leo supports Monica Cellio Dec 29 '14 at 07:16
  • 1
    @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! – tonga Jan 14 '15 at 16:03
  • Syntax highlighting, inline compiler broken with AS 2.0 update. See this, need help. http://stackoverflow.com/questions/36567110/after-updating-to-android-studio-2-0-from-1-5-ndk-syntax-highlighting-not-worki – Arpan Apr 18 '16 at 07:55
41

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:

Example of auto-complete of C++-Java wrapper

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:

C++-Java wrapper moved to correct location

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.

SJoshi
  • 1,866
  • 24
  • 47
35

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).

  1. Download the NDK

  2. Either add ANDROID_NDK_HOME to your environment variables or add ndk.dir=/path/to/ndk to your local.properties in your Android Studio project. This allows Android studio to run the ndk automatically.

  3. 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.

  4. Copy the gradle.build from the NDK sample projects. It'll look something like this. This gradle.build creates a different apk for each architecture. You must select which architecture you want using the build variants pane. build 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
}
Community
  • 1
  • 1
Cypress Frankenfeld
  • 2,317
  • 2
  • 28
  • 40
  • Yes. But that only works under Unix platforms and also limited if you a more complex than very simple ndk configuration/makefiles. – plaisthos Jun 06 '14 at 14:40
  • Yes, 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. – Cypress Frankenfeld Jun 12 '14 at 13:30
  • 1
    The call to ndk-build will only work at the command-line not from within Android Studio. – Cameron Lowell Palmer Nov 01 '14 at 15:47
  • Although 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". – Sean Beach Jan 20 '15 at 21:25
  • @CameronLowellPalmer, did you add your NDK path to local.properties? ndk.dir=/path/to/ndk – Cypress Frankenfeld Mar 03 '15 at 16:56
  • Of 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 http://stackoverflow.com/questions/21096819/jni-and-gradle-in-android-studio/26693354#26693354. – Cameron Lowell Palmer Mar 04 '15 at 07:46
  • 4
    I 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 }` – sherpya Mar 12 '15 at 01:14
23

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
Eric Woo
  • 231
  • 2
  • 2
18

As Xavier said, you can put your prebuilts in /src/main/jniLibs/ if you are using gradle 0.7.2+

taken from: https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/ctDp9viWaxoJ

Naxos
  • 191
  • 1
  • 5
16

As of now (Android Studio v0.8.6) it's quite simple. Here are the steps to create a "Hello world" type app:

  1. Download the Android NDK and put the root folder somewhere sane -- in the same location as the SDK folder, perhaps.

  2. Add the following to your local.properties file: ndk.dir=<path-to-ndk>

  3. Add the following to your build.gradle file inside of the defaultConfig closure, right after the versionName line: ndk { moduleName="hello-world" }

  4. In your app module's main directory, create a new folder called jni.

  5. In that folder, create a file called hello-world.c, which you'll see below.

  6. See the example Activity code below for an example of how to call a method (or is it a function?) in hello-world.c.


hello-world.c

#include <string.h>
#include <jni.h>

jstring
Java_me_mattlogan_ndktest_MainActivity_stringFromJNI(JNIEnv* env, jobject thiz)
{
    return (*env)->NewStringUTF(env, "Hello world!");
}

MainActivity.java

public class MainActivity extends Activity {

    static {
        System.loadLibrary("hello-world");
    }

    public native String stringFromJNI();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String testString = stringFromJNI();

        TextView mainText = (TextView) findViewById(R.id.main_text);
        mainText.setText(testString);
    }
}

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "me.mattlogan.ndktest"
        minSdkVersion 15
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"

        ndk {
            moduleName "hello-world"
        }
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

Find the full source code of a very similar app here (minus the NDK).

Matt Logan
  • 5,886
  • 5
  • 31
  • 48
  • I'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. – alice.harrison Aug 17 '14 at 00:44
  • @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. – aaa90210 Jan 05 '15 at 06:01
  • @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 – Leo supports Monica Cellio Jan 05 '15 at 13:04
  • 1
    it worked with me. PS: anyone seeing this answer, don't forget to change ```Java_me_mattlogan_ndktest_MainActivity_stringFromJNI``` to your own :) – AbdulMomen عبدالمؤمن Jun 11 '15 at 16:39
8

If you're on unix the latest version (0.8) adds ndk-build. Here's how to add it:

android.ndk {
    moduleName "libraw"
}

It expects to find the JNI under 'src/main/jni', otherwise you can define it with:

sourceSets.main {
    jni.srcDirs = 'path'
}

As of 28 JAN 2014 with version 0.8 the build is broken on windows, you have to disable the build with:

sourceSets.main {
    jni.srcDirs = [] //disable automatic ndk-build call (currently broken for windows)
}
Anthony
  • 7,638
  • 3
  • 38
  • 71
  • 1
    Is there any documentation to that feature? I could not find any. At the moment that seems to completly ignore my Android.mk/Application.mk. – plaisthos Jan 28 '14 at 16:30
  • I 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? – Anthony Jan 28 '14 at 16:38
  • See http://stackoverflow.com/questions/20674650/how-to-configure-ndk-with-android-gradle-plugin-0-7 – Alex Cohn Jan 28 '14 at 19:46
  • it actually expects to find prebuilt *.so files in jniLibs.srcDirs – Alpine Feb 08 '14 at 05:42
  • I'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. – Anthony Feb 08 '14 at 09:55
7

An elegant workaround is shown in https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/Z5yWAvCh4h4J.

Basically you create a jar which contains "lib/armeabi/yourlib.so" and then include the jar in the build.

aleb
  • 2,490
  • 1
  • 28
  • 46
  • Yeah. 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. – plaisthos Aug 12 '13 at 19:12
  • 1
    I've [modified Android's Hello-JNI example](https://github.com/OnlyInAmerica/Android-JNI-Gradle) with a [simple bash script](https://github.com/OnlyInAmerica/Android-JNI-Gradle/blob/master/jni/ndk-build.sh) 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. – dbro Oct 17 '13 at 19:18
4

A good answer automating the packaging of readily compiled .so-files is given in another (closed) thread. To get that working, I had to change the line:

from fileTree(dir: 'libs', include: '**/*.so')

into:

from fileTree(dir: 'src/main/libs', include: '**/*.so') 

Without this change the .so files were not found, and the task for packaging them would therefore never run.

Community
  • 1
  • 1
HYS
  • 771
  • 6
  • 11
  • Update: 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. – HYS Nov 20 '15 at 14:47
4

The answer from @plaisthos broke in the latest gradle version, but there is still a way to do it. Create a native-libs directory in the root of your project directory and copy all y our libs into this directory.

Add the following lines to your build.gradle. Build and be happy.

task copyNativeLibs(type: Copy) {
    from(new File(project(':<your project>').getProjectDir(), 'native-libs')) { include '**/*.so' }
    into new File(buildDir, 'native-libs')
}

tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs }

clean.dependsOn 'cleanCopyNativeLibs'
Leandros
  • 16,805
  • 9
  • 69
  • 108
3

This is the code i use to build using android-ndk from gradle. For this add ndk directory path in gradle.properties ie . add ndkdir=/home/user/android-ndk-r9d and put all jni files in a folder native in src/main/ as you can see from code posted below. It will create jar with native libs which you can use normally as in System.loadLibrary("libraryname");

dependencies {
    compile fileTree(dir: "$buildDir/native-libs", include: '*.jar')
}

task ndkBuild(type: Exec) {
    commandLine "$ndkdir/ndk-build", "--directory", "$projectDir/src/main/native", '-j', Runtime.runtime.availableProcessors(),
            "APP_PLATFORM=android-8",
            "APP_BUILD_SCRIPT=$projectDir/src/main/native/Android.mk",
            "NDK_OUT=$buildDir/native/obj",
            "NDK_APP_DST_DIR=$buildDir/native/libs/\$(TARGET_ARCH_ABI)"
}

task nativeLibsToJar(type: Jar, description: 'create a jar with native libs') {
    destinationDir file("$buildDir/native-libs")
    baseName 'native-libs'
    from fileTree(dir: "$buildDir/native/libs", include: '**/*.so')
    into 'lib/'
}

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

nativeLibsToJar.dependsOn 'ndkBuild'
Jeff Brateman
  • 3,229
  • 2
  • 20
  • 26
sujithvm
  • 2,351
  • 3
  • 15
  • 16
3

I have used the following code to compile native dropbox libraries, I am using Android Studio v1.1.

task nativeLibsToJar(type: Zip) {
    destinationDir file("$buildDir/native-libs")
    baseName 'native-libs'
    extension 'jar'
    from fileTree(dir: 'src/main/libs', include: '**/*.so')
    into 'lib/'
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn(nativeLibsToJar)
}
Sam
  • 546
  • 3
  • 16
2

I have used ndk.dir=/usr/shareData/android-ndk-r11b // path of ndk

in local.properties file in android studio project. and add this line :
android.useDeprecatedNdk=true

in gradle.properties file in android studio project.

More information here: http://tools.android.com/tech-docs/android-ndk-preview

Praveen Kumar Verma
  • 2,988
  • 2
  • 18
  • 31
1

To expand on what Naxos said (Thanks Naxos for sending me in the right direction!), I learned quite a bit from the recently released NDK examples and posted an answer in a similar question here.

How to configure NDK with Android Gradle plugin 0.7

This post has full details on linking prebuilt native libraries into your app for the various architectures as well as information on how to add NDK support directly to the build.gradle script. For the most part, you shouldn't need to do the work around zip and copy anymore.

Community
  • 1
  • 1
reactive-core
  • 1,071
  • 1
  • 7
  • 15
1

configure project in android studio from eclipse: you have to import eclipse ndk project to android studio without exporting to gradle and it works , also you need to add path of ndk in local.properties ,if shows error then add

sourceSets.main {
        jniLibs.srcDir 'src/main/libs' 
        jni.srcDirs = [] //disable automatic ndk-build callenter code here
    }

in build.gradle file then create jni folder and file using terminal and run it will work

Shajo
  • 873
  • 2
  • 11
  • 22
1

Here are the steps that I used to get the NDK working in my Android Studio project. I used this tutorial to help me out https://software.intel.com/en-us/videos/using-the-ndk-with-android-studio

In order to use NDK you must add a NDK line to local.properties. So under your sdk.dir add

ndk.dir=C\:\\MyPathToMyNDK\ndk

In my apps build.gradle I have the following code

        ndk {
            moduleName "myLib"
            ldLibs "log"
            stl "gnustl_shared"
            cFlags "-std=c++11 -frtti -fexceptions -pthread"
        }

moduleName is the name you want to give your native code. I believe this is what the shared library will be called. ldLibs allows me to log to LogCat, stl is the stl that you want to import. There are lots of options, same as the Eclipse NDK. (http://www.kandroid.org/ndk/docs/CPLUSPLUS-SUPPORT.html)

cFlags are still a certain amount of black magic for me. I have not found a good source for all the options and what they give me. Search around StackOverflow for anything you need, that is where I found it. I do know that the c++11 allows me to use the new c++ 11 standard.

Here is an example of how I log to LogCat from the native code

__android_log_print(ANDROID_LOG_DEBUG, "TestApp", "Adding - String %d has a field name of %s and a value of %s", i, lKeyUTF8.c_str(), lValueUTF8.c_str());
Brian S
  • 3,096
  • 37
  • 55
1

Now that Android Studio is in the stable channel, it is pretty straightforward to get the android-ndk samples running. These samples use the ndk experimental plugin and are newer than the ones linked to from the Android NDK online documentation. Once you know they work you can study the build.gradle, local.properties and gradle-wrapper.properties files and modify your project accordingly. Following are the steps to get them working.

  1. Go to settings, Appearance & Behavior, System Settings, Android SDK, selected the SDK Tools tab, and check Android NDK version 1.0.0 at the bottom of the list. This will download the NDK.

  2. Point to the location of the newly downloaded NDK. Note that it will be placed in the sdk/ndk-bundle directory. Do this by selecting File, Project Structure, SDK Location (on left), and supplying a path under Android NDK location. This will add an ndk entry to local.properties similar to this:

    Mac/Linux: ndk.dir=/Android/sdk/ndk-bundle
    Windows: ndk.dir=C:\Android\sdk\ndk-bundle

I have successfully built and deployed all projects in the repository this way, except gles3gni, native-codec and builder. I'm using the following:

Android Studio 1.3 build AI-141.2117773
android-ndk samples published July 28, 2015 (link above)
SDK Tools 24.3.3
NDK r10e extracted to C:\Android\sdk\ndk-bundle
Gradle 2.5
Gradle plugin 0.2.0
Windows 8.1 64 bit

Nate
  • 2,449
  • 3
  • 21
  • 29
1

NDK Builds and gradle (basic)

Generally building with the NDK is as simple as correctly specifying an ndkBuild path to Android.mk or cmake path to CMakeLists.txt. I recommend CMake over the older Android.mk because Android Studio's C/C++ support is based upon CLion and it uses CMake as its project format. This in my experience has tended to make the IDE more responsive on larger projects. Everything compiled in your project will be built and copied into the APK automatically.

apply plugin: 'com.android.library'

android {
    compileSdkVersion 19
    buildToolsVersion "25.0.2"

    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 19

        ndk {
            abiFilters 'armeabi', 'armeabi-v7a', 'x86'
            // 64-bit support requires an Android API level higher than 19; Namely 21 and higher
            //abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
        }

        externalNativeBuild {
            cmake {
                arguments '-DANDROID_TOOLCHAIN=clang',
                        '-DANDROID_PLATFORM=android-19',
                        '-DANDROID_STL=gnustl_static',
                        '-DANDROID_ARM_NEON=TRUE'

            }
        }
    }

    externalNativeBuild {
        cmake {
            path 'src/main/jni/CMakeLists.txt'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

Adding prebuilt libraries to the project (advanced)

Static libraries (.a) in your NDK build will automatically be included, but prebuilt dynamic libraries (.so) will need to be placed in jniLibs. This can be configured using sourceSets, but you should adopt the standard. You DO NOT NEED any additional commands in build.gradle when including prebuilt libraries.

The layout of jniLibs

You can find more information about the structure in the Android Gradle Plugin User Guide.

|--app:
|--|--build.gradle
|--|--src:
|--|--|--main
|--|--|--|--java
|--|--|--|--jni
|--|--|--|--|--CMakeLists.txt
|--|--|--|--jniLibs
|--|--|--|--|--armeabi
|--|--|--|--|--|--.so Files
|--|--|--|--|--armeabi-v7a
|--|--|--|--|--|--.so Files
|--|--|--|--|--x86
|--|--|--|--|--|--.so Files

You can then validate the resulting APK contains your .so files, typically under build/outputs/apk/, using unzip -l myApp.apk to list the contents.

Building shared libraries

If you're building a shared library in the NDK you do not need to do anything further. It will be correctly bundled in the APK.

Cameron Lowell Palmer
  • 21,528
  • 7
  • 125
  • 126
0

Just add this lines to app build.gradle

dependencies {
    ...
    compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')
}

task nativeLibsToJar(type: Zip, description: 'create a jar archive of the native libs') {
    destinationDir file("$buildDir/native-libs")
    baseName 'native-libs'
    extension 'jar'
    from fileTree(dir: 'libs', include: '**/*.so')
    into 'lib/armeabi/'
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn(nativeLibsToJar)
}
sagus_helgy
  • 1,417
  • 1
  • 18
  • 30
  • I think the jniLibs.srcDirs approach is cleaner than this since you can use abiFilter/flavours but your approach should also work. – plaisthos Jul 31 '14 at 19:37
0

now.I can load the so success!

1.add the .so file to this path

Project:

|--src |--|--main |--|--|--java |--|--|--jniLibs |--|--|--|--armeabi |--|--|--|--|--.so files

2.add this code to gradle.build

android {
splits {
    abi {
        enable true
        reset()
        include 'x86', 'x86_64', 'arm64-v8a', 'armeabi-v7a', 'armeabi'
        universalApk false
    }
}

}

3.System.loadLibrary("yousoname");

  1. goodluck for you,it is ok with gradle 1.2.3
xiaoyuan hu
  • 175
  • 2
  • 2
0
  1. If your project exported from eclipse,add the codes below in gradle file:

    android {
       sourceSets{
            main{
               jniLibs.srcDir['libs']  
          }  
        }
    }
    

2.If you create a project in Android studio:

create a folder named jniLibs in src/main/ ,and put your *.so files in the jniLibs folder.

And copy code as below in your gradle file :

android {
    sourceSets{  
       main{  
         jniLibs.srcDir['jniLibs']  
      }  
    }
}
Yachao
  • 37
  • 3
0

While I believe SJoshi (oracle guy) has the most complete answer, the SWIG project is a special case, interesting and useful one, at that, but not generalized for the majority of projects that have done well with the standard SDK ant based projects + NDK. We all would like to be using Android studio now most likely, or want a more CI friendly build toolchain for mobile, which gradle theoretically offers.

I've posted my approach, borrowed from somewhere (I found this on SO, but posted a gist for the app build.gradle: https://gist.github.com/truedat101/c45ff2b69e91d5c8e9c7962d4b96e841 ). In a nutshell, I recommend the following:

  • Don't upgrade your project to the latest gradle build
  • Use com.android.tools.build:gradle:1.5.0 in your Project root
  • Use com.android.application in your app project
  • Make sure gradle.properties has: android.useDeprecatedNdk=true (in case it's complaining)
  • Use the above approach to ensure that your hours and hours of effort creating Android.mk files won't be tossed away. You control which targets arch(s) to build. And these instructions are kind to Windows users, who should theoretically be able to build on windows without special issues.

Gradle for Android has been a mess in my opinion, much as I like the maven concepts borrowed and the opinionated structure of directories for a project. This NDK feature has been "coming soon" for almost 3+ years.

truedat101
  • 76
  • 1
  • 6