J'essaie d'ajouter du code natif à mon application. J'ai tout dans ../main/jni
comme dans mon projet Eclipse. J'ai ajouté ndk.dir=...
à mon local.properties
. Je n'ai encore rien fait (je ne sais pas quoi d'autre est vraiment nécessaire, donc si j'ai oublié quelque chose, faites-le-moi savoir). Lorsque j'essaie de construire, j'obtiens cette erreur:
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.
Qu'est-ce que je dois faire?
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
En essayant d'éviter les expérimentations et franchement marre du NDK et de tout son hackery, je suis heureux que la version 2.2.x de Gradle Build Tools soit sortie et qu'elle fonctionne maintenant. La clé est la externalNativeBuild
et pointe ndkBuild
argument de chemin sur un Android.mk
ou change ndkBuild
en cmake
et pointe l'argument de chemin à un CMakeLists.txt
construire un script.
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'
//}
}
}
Pour plus de détails, consultez page de Google sur l'ajout de code natif .
Une fois que cela est configuré correctement, vous pouvez ./gradlew installDebug
et vous pouvez partir. Vous devez également savoir que le NDK passe à clang, car gcc est maintenant obsolète dans le Android NDK.
Les autres réponses indiquent la manière correcte d’empêcher la création automatique de fichiers Android.mk
, mais ne parviennent pas à intégrer l’intégration avec Android Studio. J'ai ajouté la possibilité de nettoyer et de compiler à partir des sources sans avoir à passer en ligne de commande. Votre fichier local.properties
devra avoir 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'
}
Le répertoire src/main/jni
suppose une présentation standard du projet. Ce doit être le rapport entre cet emplacement de fichier build.gradle
et le répertoire jni
.
Vérifiez également ceci réponse de débordement de pile .
Il est vraiment important que votre version et configuration générale soient correctes. Si vous avez un projet plus ancien, je vous recommande vivement de créer un nouveau projet avec le dernier Android Studio et de voir ce que Google considère comme le projet standard. Utilisez également gradlew
. Cela protège le développeur d'une incompatibilité de version. Enfin, le plugin Gradle doit être configuré correctement.
Et vous demandez quelle est la dernière version du plugin Gradle? Consultez la page des outils et éditez la version en conséquence.
// 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()
}
}
Assurez-vous que gradle wrapper
génère le fichier gradlew
et le sous-répertoire gradle/wrapper
. Ceci est un gros gotcha.
Cela est arrivé un certain nombre de fois, mais Android.ndkDirectory
est le moyen correct d’obtenir le dossier après la 1.1. Migration de projets Gradle vers la version 1.0. . Si vous utilisez une version expérimentale ou ancienne du plugin, votre kilométrage peut varier.
gradle prend en charge la compilation ndk en générant un autre fichier Android.mk avec des chemins absolus vers vos sources. NDK prend en charge les chemins absolus depuis r9 sous OSX, r9c sous Windows, vous devez donc mettre à niveau votre NDK vers r9 +.
Vous pouvez rencontrer d’autres problèmes car le support de NDK par niveau est préliminaire. Si c'est le cas, vous pouvez désactiver la compilation ndk de gradle en définissant:
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir 'src/main/libs'
}
pour pouvoir appeler vous-même ndk-build et intégrer des libs à partir de libs /.
d'ailleurs, vous avez un problème de compilation pour x86? Je vois que vous ne l'avez pas inclus dans votre APP_ABI.
Dans mon cas, je suis sous Windows et je ne fais que suivre la réponse de Cameron ci-dessus si vous utilisez le nom complet du ndk-build qui est ndk-build.cmd. Je dois nettoyer et reconstruire le projet, puis redémarrer l'émulateur avant de faire fonctionner l'application (en fait, j'ai importé l'exemple HelloJni de NDK dans Android Studio). Cependant, assurez-vous que le chemin d'accès à NDK ne contient pas d'espace.
Enfin, mon build.gradle est complet énuméré ci-dessous:
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'
}
Mon problème sur OSX était la version suivante. Gradle ignorait mon Android.mk. Donc, afin de remplacer cette option et d’utiliser plutôt ma marque, j’ai saisi cette ligne:
sourceSets.main.jni.srcDirs = []
à l'intérieur de la balise Android
dans build.gradle
.
J'ai perdu beaucoup de temps à ce sujet!
Android Studio 2.2 est sorti avec la possibilité d'utiliser ndk-build et cMake. Cependant, nous avons dû attendre jusqu’à la 2.2.3 pour obtenir le support Application.mk. J'ai essayé, ça marche ... mais mes variables ne sont pas affichées dans le débogueur. Je peux quand même les interroger via la ligne de commande.
Vous devez faire quelque chose comme ça:
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"
}
}
}
Voir http://tools.Android.com/tech-docs/external-c-builds
NB: L'imbrication supplémentaire de externalNativeBuild
à l'intérieur de defaultConfig
était un changement radical introduit avec Android Studio 2.2. Extrait 5 (8 juillet 2016). Voir les notes de version sur le lien ci-dessus.
Dans le module build.gradle, dans le champ de tâche, j'obtiens une erreur sauf si j'utilise:
def ndkDir = plugins.getPlugin('com.Android.application').sdkHandler.getNdkFolder()
Je vois des gens qui utilisent
def ndkDir = Android.plugin.ndkFolder
et
def ndkDir = plugins.getPlugin('com.Android.library').sdkHandler.getNdkFolder()
mais aucun de ceux-ci n'a fonctionné jusqu'à ce que je l'aie changé pour le plugin que j'importais réellement.