Android studio, gradle and NDK

2019-01-01 04:57发布

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.

23条回答
长期被迫恋爱
2楼-- · 2019-01-01 05:21

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

查看更多
宁负流年不负卿
3楼-- · 2019-01-01 05:21

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)
}
查看更多
柔情千种
4楼-- · 2019-01-01 05:22

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)
}
查看更多
无与为乐者.
5楼-- · 2019-01-01 05:23

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.

查看更多
呛了眼睛熬了心
6楼-- · 2019-01-01 05:24

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.

查看更多
查无此人
7楼-- · 2019-01-01 05:24

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());
查看更多
登录 后发表回答