Android Studio中的JNI和Gradle

我正在尝试将本地代码添加到我的应用程序。 我拥有../main/jni所有内容, ../main/jni在我的Eclipse项目中一样。 我已经添加ndk.dir=...到我的local.properties 。 我还没有做任何其他事情(我不知道还有什么其他要求,所以如果我错过了一些让我知道)。 当我尝试build立我得到这个错误:

 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 

Gradle Build Tools 2.2.0+ – 离NDK最近被称为“魔术”

在试图避免实验性,坦率地厌倦了NDK及其所有的骇客,我很高兴2.2.x的Gradle构build工具出来,现在只是工作。 关键是externalNativeBuild并在Android.mk指向ndkBuildpath参数,或将ndkBuild更改为cmake ,并将path参数指向CMakeLists.txt构build脚本。

 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和你走了。 您还需要注意,由于现在在Android NDK中不推荐使用gcc,所以NDK正在转向叮当声。

Android Studio清理和生成集成 – DEPRECATED

其他的答案指出了防止自动创buildAndroid.mk文件的正确方法,但是他们没能走上与Android Studio更好地集成的额外步骤。 我已经添加了从源代码进行实际清理和构build的function,无需转到命令行。 你的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文件位置到jni目录的相对位置。

Gradle – 对于那些有问题的人

也检查这个堆栈溢出的答案 。

您的gradle版本和一般设置是正确的真的很重要。 如果您有一个较旧的项目,我强烈build议使用最新的Android Studio创build一个新项目,并查看Google认为标准项目的内容。 另外,使用gradlew 。 这保护了开发者免受gradle版本的不匹配。 最后,gradle插件必须正确configuration。

你问什么是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生成gradlew文件和gradle/wrapper子目录。 这是一个大问题。

ndkDirectory

这已经出现了很多次,但android.ndkDirectory是1.1之后获取文件夹的正确方法。 将Gradle项目迁移到版本1.0.0 。 如果您使用的是插件的实验版本或古代版本,则可能会有所不同。

gradle支持ndk编译通过生成另一个Android.mk文件与您的来源的绝对path。 NDK支持绝对path,因为OSX上的r9,Windows上的r9c,所以你需要升级你的NDK到r9 +。

由于gradle的NDK支持是初步的,您可能会遇到其他麻烦。 如果是这样的话,你可以通过设置来停用gradle的ndk编译:

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

能够自己调用ndk-build并从libs /中集成libs。

顺便说一句,你有任何问题编译为x86? 我看你没有把它包含在你的APP_ABI中。

在我的情况下,我在Windows上,根据上面的Cameron的回答,只有在使用ndk-build.cmd的ndk-build的全名时才有效。 我必须清理和重build项目 ,然后重新启动模拟器才能使应用程序工作(其实我从NDK导入示例HelloJni到Android Studio)。 但是,请确保NDK的path不包含空格

最后,我的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版本。 Gradle忽略了我的Android.mk。 所以,为了覆盖这个选项,并使用我的make,我input了这一行:

sourceSets.main.jni.srcDirs = []

build.gradle中的android标签内。

我浪费了很多时间在这个!

Android Studio 2.2推出了使用ndk-build和cMake的function。 尽pipe如此,我们不得不等待2.2.3的Application.mk支持。 我试过了,它可以工作…但是,我的variables没有显示在debugging器中。 我仍然可以通过命令行查询它们。

你需要做这样的事情:

 externalNativeBuild{ ndkBuild{ path "Android.mk" } } defaultConfig { externalNativeBuild{ 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

注意: externalNativeBuilddefaultConfig的额外嵌套是Android Studio 2.2 Preview 5(2016年7月8日)引入的突破性更改。 请参阅上述链接的发行说明。

在模块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() 

但是这些都没有工作,直到我把它改为我实际导入的插件。