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
指向ndkBuild
path参数,或将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
注意: externalNativeBuild
在defaultConfig
的额外嵌套是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()
但是这些都没有工作,直到我把它改为我实际导入的插件。