JNI и Gradle в Android Studio

Я пытаюсь добавить собственный код в свое приложение. У меня есть все в ../main/jni как это было в моем проекте Eclipse. Я добавил ndk.dir=... в мои local.properties . Я еще ничего не сделал (я не уверен, что еще нужно, поэтому, если я пропустил что-то, дайте мне знать). Когда я пытаюсь построить, я получаю эту ошибку:

 Execution failed for task ':app:compileDebugNdk'. > com.android.ide.common.internal.LoggedErrorException: Failed to run command: /Users/me/android-ndk-r8e/ndk-build NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/Users/me/Project/app/build/ndk/debug/Android.mk APP_PLATFORM=android-19 NDK_OUT=/Users/me/Project/app/build/ndk/debug/obj NDK_LIBS_OUT=/Users/me/Project/app/build/ndk/debug/lib APP_ABI=all Error Code: 2 Output: make: *** No rule to make target `/Users/me/Project/webapp/build/ndk/debug//Users/me/Project/app/src/main/jni/jni_part.cpp', needed by `/Users/me/Project/app/build/ndk/debug/obj/local/armeabi-v7a/objs/webapp//Users/me/Project/app/src/main/jni/jni_part.o'. Stop. 

Что мне нужно сделать?

Android.mk:

 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # OpenCV OPENCV_CAMERA_MODULES:=on OPENCV_INSTALL_MODULES:=on include .../OpenCV-2.4.5-android-sdk/sdk/native/jni/OpenCV.mk LOCAL_MODULE := native_part LOCAL_SRC_FILES := jni_part.cpp LOCAL_LDLIBS += -llog -ldl include $(BUILD_SHARED_LIBRARY) 

Application.mk:

 APP_STL := gnustl_static APP_CPPFLAGS := -frtti -fexceptions APP_ABI := armeabi armeabi-v7a APP_PLATFORM := android-8 

Solutions Collecting From Web of "JNI и Gradle в Android Studio"

Gradle Build Tools 2.2.0+ – Ближайший NDK когда-либо назывался магией,

Стремясь избежать экспериментальных и откровенно сытых по горло NDK и всех его хакеров, я рад, что появился 2.2.x из Gradle Build Tools, и теперь он просто работает. Ключ – externalNativeBuild аргумент externalNativeBuild и указывающий ndkBuild пути ndkBuild на Android.mk или изменение ndkBuild для cmake и укажите аргумент path в скрипте сборки CMakeLists.txt .

 android { compileSdkVersion 19 buildToolsVersion "25.0.2" defaultConfig { minSdkVersion 19 targetSdkVersion 19 ndk { abiFilters 'armeabi', 'armeabi-v7a', 'x86' } externalNativeBuild { cmake { cppFlags '-std=c++11' arguments '-DANDROID_TOOLCHAIN=clang', '-DANDROID_PLATFORM=android-19', '-DANDROID_STL=gnustl_static', '-DANDROID_ARM_NEON=TRUE', '-DANDROID_CPP_FEATURES=exceptions rtti' } } } externalNativeBuild { cmake { path 'src/main/jni/CMakeLists.txt' } //ndkBuild { // path 'src/main/jni/Android.mk' //} } } 

Более подробно проверьте страницу Google на добавление собственного кода .

После правильной настройки вы можете ./gradlew installDebug и выйти. Вам также необходимо знать, что NDK переходит на clang, поскольку gcc теперь устарел в Android NDK.

Интеграция в Android Studio Clean и Build – DEPRECATED

Другие ответы указывают на правильный способ предотвратить автоматическое создание файлов Android.mk , но они не могут сделать дополнительный шаг для интеграции с Android Studio. Я добавил возможность фактически очищать и строить из исходного кода, не переходя в командную строку. local.properties файле local.properties необходимо ndk.dir=/path/to/ndk

 apply plugin: 'com.android.application' android { compileSdkVersion 14 buildToolsVersion "20.0.0" defaultConfig { applicationId "com.example.application" minSdkVersion 14 targetSdkVersion 14 ndk { moduleName "YourModuleName" } } sourceSets.main { jni.srcDirs = [] // This prevents the auto generation of Android.mk jniLibs.srcDir 'src/main/libs' // This is not necessary unless you have precompiled libraries in your project. } task buildNative(type: Exec, description: 'Compile JNI source via NDK') { def ndkDir = android.ndkDirectory commandLine "$ndkDir/ndk-build", '-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source '-j', Runtime.runtime.availableProcessors(), 'all', 'NDK_DEBUG=1' } task cleanNative(type: Exec, description: 'Clean JNI object files') { def ndkDir = android.ndkDirectory commandLine "$ndkDir/ndk-build", '-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source 'clean' } clean.dependsOn 'cleanNative' tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn buildNative } } dependencies { compile 'com.android.support:support-v4:20.0.0' } 

Каталог src/main/jni предполагает стандартную компоновку проекта. Он должен относиться к этому файлу build.gradle каталоге build.gradle .

Gradle – для тех, у кого есть проблемы

Также проверьте этот ответ переполнения стека .

Очень важно, чтобы ваша версия градиента и общая настройка были правильными. Если у вас более старый проект, я настоятельно рекомендую создать новую версию с последней версией Android Studio и посмотреть, что Google считает стандартным проектом. Кроме того, используйте gradlew . Это защищает разработчика от несоответствия версии градиента. Наконец, плагин gradle должен быть настроен правильно.

И вы спрашиваете, что такое последняя версия плагина gradle? Проверьте страницу инструментов и соответствующим образом отредактируйте версию.

Конечный продукт – /build.gradle

 // Top-level build file where you can add configuration options common to all sub-projects/modules. // Running 'gradle wrapper' will generate gradlew - Getting gradle wrapper working and using it will save you a lot of pain. task wrapper(type: Wrapper) { gradleVersion = '2.2' } // Look Google doesn't use Maven Central, they use jcenter now. buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.2.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { jcenter() } } 

Убедитесь, что gradle wrapper создает файл gradle/wrapper подкаталог gradle/wrapper . Это большая добыча.

ndkDirectory

Это появилось несколько раз, но android.ndkDirectory – это правильный способ получить папку после 1.1. Миграция проектов Gradle до версии 1.0.0 . Если вы используете экспериментальную или древнюю версию плагина, ваш пробег может отличаться.

Gradle поддерживает сбор ndk, создавая другой файл Android.mk с абсолютными путями к вашим источникам. NDK поддерживает абсолютные пути с r9 на OSX, r9c в Windows, поэтому вам нужно обновить NDK до r9 +.

Вы можете столкнуться с другими проблемами, так как поддержка NDK с помощью gradle является предварительной. Если это так, вы можете отключить компиляцию ndk из градиента, установив:

 sourceSets.main { jni.srcDirs = [] jniLibs.srcDir 'src/main/libs' } 

Чтобы иметь возможность вызывать ndk-build самостоятельно и интегрировать библиотеки libs /.

Кстати, у вас есть компиляция проблем для x86? Я вижу, вы не включили его в свой APP_ABI.

В моем случае я нахожусь в Windows и после ответа Cameron выше работает только если вы используете полное имя ndk-build, которое является ndk-build.cmd . Я должен очистить и перестроить проект , а затем перезапустить эмулятор, прежде чем заставить приложение работать (на самом деле я импортировал образец HelloJni из NDK в Android Studio). Однако убедитесь, что путь к NDK не содержит пробела .

Наконец, мой build.gradle переименован ниже:

 apply plugin: 'com.android.application' android { compileSdkVersion 21 buildToolsVersion "21.1.2" defaultConfig { applicationId "com.example.hellojni" minSdkVersion 4 targetSdkVersion 4 ndk { moduleName "hello-jni" } testApplicationId "com.example.hellojni.tests" testInstrumentationRunner "android.test.InstrumentationTestRunner" } sourceSets.main { jni.srcDirs = [] // This prevents the auto generation of Android.mk // sourceSets.main.jni.srcDirs = [] jniLibs.srcDir 'src/main/libs' // This is not necessary unless you have precompiled libraries in your project. } task buildNative(type: Exec, description: 'Compile JNI source via NDK') { def ndkDir = android.plugin.ndkFolder commandLine "$ndkDir/ndk-build.cmd", '-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source '-j', Runtime.runtime.availableProcessors(), 'all', 'NDK_DEBUG=1' } task cleanNative(type: Exec, description: 'Clean JNI object files') { def ndkDir = android.plugin.ndkFolder commandLine "$ndkDir/ndk-build.cmd", '-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source 'clean' } clean.dependsOn 'cleanNative' tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn buildNative } } dependencies { compile 'com.android.support:support-v4:21.0.3' } 

Моя проблема с OSX – это версия с градиентом. Gradle игнорировал мой Android.mk. Поэтому, чтобы переопределить этот параметр и вместо этого использовать мой make, я ввел эту строку:

SourceSets.main.jni.srcDirs = []

Внутри тега android в build.gradle .

Я потратил много времени на это!

Android Studio 2.2 вышел с возможностью использования ndk-build и cMake. Хотя нам пришлось ждать до 2.2.3 для поддержки Application.mk. Я пробовал, он работает … хотя мои переменные не отображаются в отладчике. Я все еще могу запросить их через командную строку.

Вам нужно сделать что-то вроде этого:

 externalNativeBuild{ ndkBuild{ path "Android.mk" } } defaultConfig { ndkBuild { arguments "NDK_APPLICATION_MK:=Application.mk" cFlags "-DTEST_C_FLAG1" "-DTEST_C_FLAG2" cppFlags "-DTEST_CPP_FLAG2" "-DTEST_CPP_FLAG2" abiFilters "armeabi-v7a", "armeabi" } } 

См. http://tools.android.com/tech-docs/external-c-builds

В модуле build.gradle в поле задачи я получаю сообщение об ошибке, если не использую:

 def ndkDir = plugins.getPlugin('com.android.application').sdkHandler.getNdkFolder() 

Я вижу, как люди используют

 def ndkDir = android.plugin.ndkFolder 

а также

 def ndkDir = plugins.getPlugin('com.android.library').sdkHandler.getNdkFolder() 

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