Android studio, gradle и NDK


Я очень новичок в этой поддержке gradle и Android Studio. Мне удалось преобразовать мой проект android в gradle с помощью опции экспорта.

но я ищу некоторую документацию или начальную точку, как интегрировать сборку NDK в процесс сборки gradle.

Если возможно, мне также нужен какой-то этап" После", который копирует двоичные файлы сборки (файлы.so) в каталог активов.

23 148

23 ответа:

мы выпустили первую версию интеграции в качестве предварительного просмотра в 1.3:http://tools.android.com/tech-docs/android-ndk-preview

интеграция останется предварительным просмотром даже после того, как 1.3 станет окончательным. Нет текущего ETA относительно того, когда он будет окончательным (по состоянию на 2015/07/10).

дополнительная информация здесь:http://tools.android.com/tech-docs/android-ndk-preview

обновление: студия андроида с поддержкой НДК вне теперь:http://tools.android.com/tech-docs/android-ndk-preview

для построения со скриптом должно работать решение gradle ниже:

Я использую свой скрипт сборки и добавил в свой файл (кажется, работает для 0.8+): это, кажется, эквивалентно решению ниже (но выглядит лучше в файле gradle):

 android {
    sourceSets {
        main {
            jniLibs.srcDirs = ['native-libs']
            jni.srcDirs = [] //disable automatic ndk-build
        }
    }
 }

сборка, к сожалению, не удастся, если каталог отсутствует или не содержит .so файлы.

С обновлением Android Studio до 1.0 поддержка NDK toolchain значительно улучшилась (Примечание: пожалуйста, прочитайте мои обновления в нижней части этого сообщения, чтобы увидеть использование с новым экспериментальным плагином Gradle и Android Studio 1.5).

Android Studio и NDK интегрированы достаточно хорошо, так что вам просто нужно создать блок ndk{} в сборке вашего модуля.gradle, и установите исходные файлы в каталог (module)/src/main/jni - и все готово!

нет больше ndk-сборки из командной строки.

Я написал Все об этом в своем блоге здесь:http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/

основные моменты:

есть две вещи, которые нужно знать здесь. По умолчанию, если у вас есть внешние библиотеки, которые вы хотите загрузить в приложение Android, они по умолчанию ищут в (модуле)/src/main/jniLibs. Вы можете измените это с помощью параметра sourceSets.главный.джнилибс.srcDirs в сборке вашего модуля.градля. Вам понадобится подкаталог с библиотеками для каждой архитектуры, на которую вы ориентируетесь (например, x86, arm, mips, arm64-v8a и т. д.)

код, который вы хотите скомпилировать по умолчанию с помощью NDK toolchain, будет расположен в (module)/src/main / jni и, как и выше, вы можете изменить его, установив sourceSets.главный.средой JNI.srcDirs в сборке вашего модуля.gradle

и поставить это в сборка вашего модуля.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
}

это процесс компиляции вашего кода на C++, оттуда вам нужно загрузить его и создать обертки - но, судя по вашему вопросу, вы уже знаете, как это сделать, поэтому я не буду повторно хэшировать.

кроме того, я разместил РЕПО Github этого примера здесь:http://github.com/sureshjoshi/android-ndk-swig-example

обновление: 14 июня 2015

когда Android Studio 1.3 выходит, там должно быть лучшая поддержка C++ через плагин JetBrains CLion. В настоящее время я предполагаю, что это позволит разрабатывать Java и C++ из Android Studio; однако я думаю, что нам все равно нужно будет использовать раздел Gradle NDK, как я уже говорил выше. Кроме того, я думаю, что по-прежнему будет необходимость писать файлы-оболочки JavaC++, если CLion не будет делать это автоматически.

обновление: 5 января 2016 года

я обновил свой блог и GitHub РЕПО (в разработке филиал) для использования Android Studio 1.5 с последним экспериментальным плагином Gradle (0.6.0-alpha3).

http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/ http://github.com/sureshjoshi/android-ndk-swig-example

сборка Gradle для раздела NDK теперь выглядит следующим образом:

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
}

кроме того, довольно удивительно, Android Studio имеет автозаполнение для C++-Java генерируемых оболочек с использованием "родной" ключевое слово:

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

однако, это не совсем безоблачно... Если вы используете SWIG для обертывания библиотеки для автоматического создания кода, а затем пытаетесь использовать собственное ключевое слово auto-generation, он поместит код в неправильное место в вашем Swig _wrap.файл CXX... Поэтому вам нужно переместить его в блок "extern C":

C++-Java wrapper moved to correct location

обновление: 15 октября 2017

Я был бы неосторожен, если бы не упомянул об этом Android Studio 2.2 и далее имеет по существу "родную" (без каламбура) поддержку NDK toolchain через Gradle и CMake. Теперь, когда вы создаете новый проект, просто выберите поддержку C++, и вы можете идти.

вам все равно нужно будет создать свой собственный код слоя JNI или использовать технику SWIG, о которой я упоминал выше, но леса C++ в проекте Android теперь тривиальны.

изменения в файле CMakeLists (где вы размещаете исходные файлы C++) будут подобраны Android Studio, и он будет автоматически перекомпилировать любые связанные библиотеки.

в Google IO 2015, Google объявила о полной интеграции NDK в Android Studio 1.3.

это теперь из предварительного просмотра, и доступны для всех:https://developer.android.com/studio/projects/add-native-code.html

старый ответ: Gradle автоматически вызывает ndk-build Если у вас . 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
    }

}

обратите внимание, что это будет игнорировать ваш Android.mk и Application.mk файлы. В качестве обходного пути вы можете сказать gradle отключить вызов atuomatic ndk-build, а затем вручную указать каталог для источников ndk.

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
}

кроме того, вы, вероятно, захотите вызвать ndk-build в своем скрипте сборки gradle явно, потому что вы только что отключили автоматический вызов.

task ndkBuild(type: Exec) {
   commandLine 'ndk-build', '-C', file('src/main/jni').absolutePath
}

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

Я нашел " gradle 1.11 com.андроид.инструменты.сборка: gradle: 0.9.+ "поддерживает предварительную сборку ndk теперь, вы можете просто поставить*. so в dir src/main / jniLibs. при построении. Gradle будет пакет NDK в правильном месте.

вот мой проект

Project:
|--src
|--|--main
|--|--|--java
|--|--|--jniLibs
|--|--|--|--armeabi
|--|--|--|--|--.so files
|--libs
|--|--other.jar

Как сказал Ксавье, вы можете поместить свои предварительные сборки в /src / main/ jniLibs / если вы используете gradle 0.7.2+

взято из: https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/ctDp9viWaxoJ

на данный момент (Android Studio v0.8.6) это довольно просто. Вот шаги, чтобы создать приложение типа "Hello world":

  1. загрузите Android NDK и поместите корневую папку где-нибудь в здравом уме-в том же месте, что и папка SDK, возможно.

  2. добавьте следующее к вашему : ndk.dir=<path-to-ndk>

  3. добавьте в свою сборку следующее.gradle файл внутри defaultConfig закрытие, сразу после versionName линия:ndk { moduleName="hello-world" }

  4. в модуле вашего приложения создайте новую папку под названием jni.

  5. в этой папке создайте файл с именем hello-world.c, который вы увидите ниже.

  6. пример Activity код ниже для примера, как вызвать метод (или это функция?) в 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'])
}

найти полный исходный код очень похожего приложения здесь (минус NDK).

Если вы находитесь на unix последняя версия (0.8) добавляет ndk-build. Вот как его добавить:

android.ndk {
    moduleName "libraw"
}

он ожидает найти JNI под 'src / main/jni', в противном случае вы можете определить его с помощью:

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

по состоянию на 28 января 2014 года с версией 0.8 сборка разбита на windows, вы должны отключить сборку с:

sourceSets.main {
    jni.srcDirs = [] //disable automatic ndk-build call (currently broken for windows)
}

элегантный обходной путь показан в https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/Z5yWAvCh4h4J.

в основном вы создаете банку, которая содержит "lib/armeabi / yourlib.so", а затем включаете банку в сборку.

хороший ответ автоматизация упаковки легко составленному .so - файлы даны в другой (закрытой) темы. Чтобы заставить это работать, мне пришлось изменить строку:

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

в:

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

без этого изменения .so файлы не были найдены, и поэтому задача их упаковки никогда не будет выполняться.

ответ от @plaisthos сломался в последней версии gradle, но все еще есть способ сделать это. Создайте native-libs каталог в корневом каталоге вашего проекта и скопируйте все наши библиотеки в этот каталог.

добавьте следующие строки в свою сборку.градля. Стройте и будьте счастливы.

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'

это код, который я использую для создания с помощью android-ndk от gradle. Для этого добавьте путь к каталогу ndk в gradle.properties ie . добавить ndkdir=/home/user/android-ndk-r9d и поместите все файлы jni в папку native на src/main/ как вы можете видеть из кода размещены ниже. Он создаст банку с родными библиотеками, которые вы можете использовать нормально, как в 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'

я использовал следующий код для компиляции собственных библиотек dropbox, я использую 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)
}

я использовал ndk.dir=/usr/shareData/android-ndk-r11b / / путь ndk

на местные.свойства файл в проекте android studio. и добавьте эту строку :
android.useDeprecatedNdk=true

на gradle.свойства файл в проекте android studio.

Более подробная информация здесь: http://tools.android.com/tech-docs/android-ndk-preview

об этом заявил Наксос (Наксос Спасибо за отправку меня в правильном направлении!), Я узнал совсем немного из недавно выпущенных примеров NDK и опубликовал ответ на аналогичный вопрос здесь.

как настроить NDK с Android Gradle плагин 0.7

Это сообщение содержит полную информацию о связывании готовых собственных библиотек в ваше приложение для различных архитектур, а также информацию о том, как добавить поддержку NDK непосредственно в сборку.Gradle в скрипт. По большей части, вам больше не нужно делать работу вокруг zip и копировать.

вот шаги, которые я использовал, чтобы заставить NDK работать в моем проекте Android Studio. Я использовал этот учебник, чтобы помочь мне https://software.intel.com/en-us/videos/using-the-ndk-with-android-studio

для использования NDK необходимо добавить строку NDK в local.свойства. Так что под вашим sdk.реж добавить

ndk.dir=C\:\MyPathToMyNDK\ndk

в моих приложениях сборки.gradle у меня есть следующий код

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

moduleName-это имя, которое вы хотите дать своему собственному коду. Я считаю, что общая библиотека будет называться. ldLibs позволяет мне войти в LogCat, stl-это stl, который вы хотите импортировать. Есть много вариантов, таких же, как Eclipse NDK. (http://www.kandroid.org/ndk/docs/CPLUSPLUS-SUPPORT.html)

cFlags все еще определенное количество черной магии для меня. Я не нашел хорошего источника для всех вариантов и того, что они мне дают. Поиск вокруг StackOverflow для всего, что вам нужно, вот где я нашел его. Я знаю что c++11 позволяет мне использовать новый стандарт C++ 11.

вот пример того, как я войти в LogCat из собственного кода

__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());

настройки проекта в Android-студия из eclipse: вы должны импортировать проект eclipse ndk в Android studio без экспорта в gradle, и он работает , также вам нужно добавить путь ndk в местные.свойства ,Если показывает ошибку, то добавить

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

in построить.gradle затем создать jni папка и файл с помощью терминала и запустить его будет работать

теперь, когда Android Studio находится в стабильном канале, довольно просто получить андроид-НДК образцов работает. Эти образцы используют экспериментальный плагин ndk и новее, чем те, которые связаны с онлайн-документацией Android NDK. Как только вы узнаете, что они работают, вы можете изучить сборку.Gradle, а местные.свойства и gradle-обертка.файлы свойств и соответствующим образом измените свой проект. Ниже приведены шаги, чтобы получить их рабочий.

  1. перейдите в Настройки, Внешний вид и поведение, Системные настройки, Android SDK, выберите вкладку SDK Tools и проверьте Android NDK версии 1.0.0 в нижней части списка. Это позволит загрузить NDK.

  2. укажите местоположение вновь загруженного NDK. Обратите внимание, что он будет помещен в каталог sdk/ndk-bundle. Для этого выберите Файл, структуру проекта, расположение SDK (слева) и укажите путь в разделе расположение Android NDK. Это добавит запись ndk в local.свойства, подобные этому:

    Mac / Linux: ndk.dir= / Android / sdk / NDK-bundle
    Окна: НДК.dir=C:\Android\sdk\NDK-bundle

Я успешно построил и развернул все проекты в репозитории таким образом, за исключением gles3gni, native-codec и builder. Я использую следующее:

Android Studio 1.3 build AI-141.2117773
Android-NDK образцы опубликованы 28 июля, 2015 (ссылка выше)
SDK Tools 24.3.3
НДК р10э извлеченный к C:\Android\sdk\ndk-bundle
Gradle 2.5
Gradle плагин 0.2.0
ОС Windows 8.1 64 бит

NDK строит и gradle (basic)

как правило, построение с помощью NDK так же просто, как правильно указать путь ndkBuild к Android.mk или путь cmake к CMakeLists.формат txt. Я рекомендую CMake над старым Android.mk потому что поддержка Android Studio C / C++ основана на CLion и использует CMake в качестве формата проекта. Это, по моему опыту, как правило, делает IDE более отзывчивой на более крупные проекты. Все скомпилированное в вашем проекте будет построено и скопировано в APK автоматически.

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'])
}

добавление готовых библиотек в проект (дополнительно)

статические библиотеки (.a) в вашей сборке NDK будет автоматически включен, но предварительно построенные динамические библиотеки (.so) должны быть помещены в jniLibs. Это можно настроить с помощью sourceSets, но вы должны принять стандарт. Вам не нужны никакие дополнительные команды в build.gradle при включении готовых библиотек.

расположение jniLibs

вы можете найти более информация о структуре в Android Gradle Plugin Руководство Пользователя.

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

затем вы можете проверить, что полученный APK содержит ваши файлы. so, как правило, под build/outputs/apk/, используя unzip -l myApp.apk для просмотра содержимого.

создание общих библиотек

если вы создаете общую библиотеку в NDK, вам не нужно ничего делать дальше. Он будет правильно упакован в APK.

просто добавьте эти строки в приложение 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)
}

сейчас.Я могу загрузить так успех!

1.добавить .так что файл по этому пути

Project:

/ --src |--|--главный |--|--|--ява |-- / -- / --jniLibs |--|--|--|--норм |--|--|--|--|--.так что файлы

2.добавьте этот код в gradle.строй

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

}

3.System.loadLibrary("yousoname");

  1. goodluck для вас, это нормально с gradle 1.2.3
  1. если ваш проект экспортируется из eclipse, добавьте коды ниже в файл gradle:

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

2.Если вы создаете проект в Android studio:

создайте папку с именем jniLibs в src/ main / ,и поместите ваши файлы *.so в папку jniLibs.

и скопируйте код, как показано ниже в вашем файле gradle :

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

хотя я считаю, что SJoshi (oracle guy) имеет наиболее полный ответ, проект SWIG является частным случаем, интересным и полезным, но не обобщенным для большинства проектов, которые хорошо справились со стандартными проектами на основе SDK ant + NDK. Мы все хотели бы использовать Android studio сейчас, скорее всего, или хотите более CI дружественной сборки toolchain для мобильных устройств, которые gradle теоретически предлагает.

Я опубликовал свой подход, заимствованный откуда-то (я нашел это так, но суть для сборки приложения.gradle:https://gist.github.com/truedat101/c45ff2b69e91d5c8e9c7962d4b96e841). В двух словах, я рекомендую следующее:

  • Не обновляйте свой проект до последней сборки gradle
  • использовать com.андроид.инструменты.сборка: gradle: 1.5.0 в корне вашего проекта
  • использовать com.андроид.применение в вашем проекте приложения
  • убедитесь, что gradle.свойства: андроид.useDeprecatedNdk=true (в случае, если это жалуюсь)
  • используйте вышеуказанный подход, чтобы гарантировать, что ваши часы и часы усилий создания Android.mk файлы не будут выброшены. Вы управляете тем, какие цели арки(ы) построить. И эти инструкции добры к пользователям Windows, которые теоретически должны иметь возможность строить на windows без особых проблем.

Gradle для Android был беспорядок на мой взгляд, так как мне нравятся заимствованные концепции maven и самоуверенная структура каталогов для проекта. Эта функция NDK была "скоро" в течение почти 3+ лет.