Studio Android, gradle et NDK

153

Je suis très nouveau dans tout ce support gradle et Android Studio. J'ai réussi à convertir mon projet Android en gradle en utilisant l'option d'exportation.

Mais je recherche de la documentation ou un point de départ sur la façon d'intégrer la construction NDK dans le processus de construction gradle.

Si possible, j'ai également besoin d'une sorte d'étape «après» qui copie les binaires de construction (fichiers .so) dans le répertoire des ressources.

plaisthos
la source
J'ai publié ma réponse dans le lien ci-dessous: stackoverflow.com/questions/20900814/…
Ahmad Ali Nasir
24
Nouveaux lecteurs: sachez que cette question a été initialement posée pendant la période bêta d'Android Studio; la réponse a changé avec le temps. Faites attention à la version Gradle mentionnée dans les réponses, ainsi qu'à la date à laquelle les réponses ont été réellement publiées.
Sean Beach du
Si quelque chose change vraiment, je modifierai la question pour refléter le statut
plaisthos
Android Studio 1.3 sur le canal Canary prend entièrement en charge NDK. Référence: tools.android.com/download/studio/canary/latest
Vikasdeep Singh
18 juin 2015: Android Studio 1.3 Beta est maintenant disponible dans la version beta! Désolé, cette version ne contient pas encore le support C / C ++; source: tools.android.com/recent/androidstudio13betaavailable
fastr.de

Réponses:

85

Nous avons publié une première version de l'intégration en avant-première dans la version 1.3: http://tools.android.com/tech-docs/android-ndk-preview

L'intégration restera un aperçu même après que la version 1.3 devienne définitive. Pas d'ETA actuelle quant à la date de sa fin (à partir du 10/07/2015).

Plus d'informations ici: http://tools.android.com/tech-docs/android-ndk-preview

Xavier Ducrohet
la source
2
Ce serait génial si je pouvais utiliser NDK et l'achèvement des commandes avec le débogage sous Android Studio (et le support Gradle)
Powder366
1
@GREnvoy - Comment configurer le bon constructeur NDK dans Android Studio? Pouvez-vous me donner les étapes? :)
Shravan
7
@DirtyBeach Pourquoi est-il obsolète? Il n'y a toujours pas d'intégration du NDK dans Studio. Nous y travaillons mais pas d'ETA pour le moment.
Xavier Ducrohet
2
Mon action était basée sur la façon dont je définissais «l'intégration». J'ai compris que cela signifiait "une façon d'utiliser le NDK avec gradle" qui existe maintenant, même si aucune d'entre elles n'est une solution fantastique. Cependant, sur la base de votre commentaire, il semble que votre équipe ait autre chose en tête pour ce que pourrait être une véritable intégration. Je retire ma déclaration précédente.
Sean Beach le
2
L'intégration de NDK a été annoncée lors de Google IO 2015. Elle est disponible dans Android Studio 1.3 (l'aperçu peut être téléchargé bientôt. Je publierai un lien lorsqu'il sera disponible).
Cypress Frankenfeld
43

MISE À JOUR: Le studio Android avec prise en charge NDK est maintenant disponible: http://tools.android.com/tech-docs/android-ndk-preview

Pour construire avec un script, la solution gradle ci-dessous devrait fonctionner:

J'utilise mon script de construction et je l'ai ajouté à mon fichier (semble fonctionner pour 0.8+): Cela semble être équivalent à la solution ci-dessous (mais semble plus agréable dans le fichier gradle):

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

La construction n'échoue malheureusement pas si le répertoire n'est pas présent ou ne contient aucun .sofichier.

plaisthos
la source
5
Cela ne fonctionne plus avec la nouvelle version d'Android Studio, solution de contournement?
poudre366
@ poudre366 Voir ma réponse.
Leandros
2
Un peu de magie Groovy: tasks.withType(com.android.build.gradle.tasks.PackageApplication) { it.jniFolders = [file("libs")] as Set }. Merci les gars pour votre aide!
trnl
Quelle est la procédure pour Android Studio 0.8.9
Pandiri Deepak
1
@plaisthos Merci beaucoup d'avoir indiqué la bonne direction! La deuxième ligne du script gradle jni.srcDirs = [] //disable automatic ndk-buildest très importante car elle empêchera Android Studio de reconstruire le code source C / C ++. J'essaie de comprendre cela depuis deux jours jusqu'à ce que je voie votre message et que cela résout mon problème. Je pense vraiment que la version NDK est mieux construite séparément par le makefile de la ligne de commande Android.mk uniquement, pas par le script gradle puisque C / C ++ a été construit par Makefile depuis plus de 40 ans!
tonga le
40

Avec la mise à jour d'Android Studio vers 1.0, le support de la chaîne d'outils NDK s'est énormément amélioré ( note: veuillez lire mes mises à jour au bas de cet article pour voir l'utilisation avec le nouveau plugin expérimental Gradle et Android Studio 1.5 ).

Android Studio et le NDK sont suffisamment bien intégrés pour qu'il vous suffise de créer un bloc ndk {} dans le build.gradle de votre module et de définir vos fichiers source dans le répertoire (module) / src / main / jni - et vous êtes terminé!

Plus de ndk-build à partir de la ligne de commande.

J'ai tout écrit à ce sujet dans mon article de blog ici: http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/

Les points saillants sont:

Il y a deux choses que vous devez savoir ici. Par défaut, si vous avez des bibliothèques externes que vous souhaitez charger dans l'application Android, elles sont recherchées dans le (module) / src / main / jniLibs par défaut. Vous pouvez modifier cela en utilisant le paramètre sourceSets.main.jniLibs.srcDirs dans build.gradle de votre module. Vous aurez besoin d'un sous-répertoire avec des bibliothèques pour chaque architecture que vous ciblez (par exemple x86, arm, mips, arm64-v8a, etc.)

Le code que vous souhaitez compiler par défaut par la chaîne d'outils NDK sera situé dans (module) / src / main / jni et de la même manière que ci-dessus, vous pouvez le modifier en définissant sourceSets.main.jni.srcDirs dans build.gradle de votre module

et mettez ceci dans build.gradle de votre module:

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'est le processus de compilation de votre code C ++, à partir de là, vous devez le charger et créer des wrappers - mais à en juger par votre question, vous savez déjà comment faire tout cela, donc je ne re-hacherai pas.

De plus, j'ai placé un dépôt Github de cet exemple ici: http://github.com/sureshjoshi/android-ndk-swig-example

MISE À JOUR: 14 juin 2015

Lorsque Android Studio 1.3 sortira, il devrait y avoir une meilleure prise en charge de C ++ via le plugin JetBrains CLion. Je suppose actuellement que cela permettra le développement Java et C ++ à partir d'Android Studio; Cependant, je pense que nous devrons toujours utiliser la section Gradle NDK comme je l'ai indiqué ci-dessus. De plus, je pense qu'il sera toujours nécessaire d'écrire des fichiers wrapper Java <-> C ++, à moins que CLion ne le fasse automatiquement.

MISE À JOUR: 5 janvier 2016

J'ai mis à jour mon blog et mon dépôt Github (dans la branche de développement) pour utiliser Android Studio 1.5 avec le dernier plugin expérimental 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

La construction Gradle pour la section NDK ressemble maintenant à ceci:

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
}

De plus, tout à fait incroyable, Android Studio a une saisie semi-automatique pour C ++ - les wrappers générés par Java à l'aide du mot-clé `` natif '':

Exemple d'auto-complétion de C ++ - wrapper Java

Cependant, ce n'est pas tout à fait rose ... Si vous utilisez SWIG pour envelopper une bibliothèque afin de générer automatiquement du code, puis essayez d'utiliser la génération automatique de mot-clé natif, cela mettra le code au mauvais endroit dans votre Swig _wrap Fichier .cxx ... Vous devez donc le déplacer dans le bloc "extern C":

C ++ - Le wrapper Java a été déplacé vers l'emplacement correct

MISE À JOUR: 15 octobre 2017

Je m'en voudrais de ne pas mentionner qu'Android Studio 2.2 et les versions ultérieures ont essentiellement un support `` natif '' (sans jeu de mots) pour la chaîne d'outils NDK via Gradle et CMake. Maintenant, lorsque vous créez un nouveau projet, sélectionnez simplement le support C ++ et vous êtes prêt à partir.

Vous devrez toujours générer votre propre code de couche JNI ou utiliser la technique SWIG que j'ai mentionnée ci-dessus, mais l'échafaudage d'un projet C ++ dans Android est désormais trivial.

Les modifications dans le fichier CMakeLists (où vous placez vos fichiers source C ++) seront récupérées par Android Studio, et il recompilera automatiquement toutes les bibliothèques associées.

SJoshi
la source
1
mettre le * .so dans (module) / src / main / jniLibs
fawkes
pourquoi NDEBUG est-il toujours défini lors de l'utilisation d'Android Studio, même sur les versions de débogage
pt123
35

Dans Google IO 2015, Google a annoncé l'intégration complète de NDK dans Android Studio 1.3.

Il est désormais hors aperçu et accessible à tous: https://developer.android.com/studio/projects/add-native-code.html

Ancienne réponse: Gradle appelle automatiquement ndk-buildsi vous avez un jnirépertoire dans les sources de votre projet.

Cela fonctionne sur le studio Android 0.5.9 (version Canary).

  1. Téléchargez le NDK

  2. Ajoutez ANDROID_NDK_HOMEà vos variables d'environnement ou ajoutez ndk.dir=/path/to/ndkà votre local.propertiesdans votre projet Android Studio. Cela permet au studio Android d'exécuter automatiquement le ndk.

  3. Téléchargez les derniers exemples de projets Gradle pour voir un exemple de projet ndk. (Ils sont au bas de la page). Un bon exemple de projet est ndkJniLib.

  4. Copiez le à gradle.buildpartir des exemples de projets NDK. Cela ressemblera à quelque chose comme ça. Cela gradle.buildcrée un apk différent pour chaque architecture. Vous devez sélectionner l'architecture souhaitée à l'aide du build variantsvolet. volet des variantes de construction

    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
        }
    
    }

Notez que cela ignorera vos fichiers Android.mk et Application.mk. Pour contourner ce problème, vous pouvez demander à gradle de désactiver l'appel ndk-build atuomatic, puis spécifier manuellement le répertoire des sources 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
}

De plus, vous voudrez probablement appeler explicitement ndk-build dans votre script de construction gradle, car vous venez de désactiver l'appel automatique.

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

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn ndkBuild
}
Cyprès Frankenfeld
la source
Oui. Mais cela ne fonctionne que sous les plates-formes Unix et également limité si vous avez une configuration / makefiles ndk plus complexe que très simple.
plaisthos
Oui, il générera automatiquement des fichiers makefiles pour les éléments limités que vous pouvez définir dans le fichier de construction gradle, mais il existe une solution de contournement. Je l'ai ajouté à ma réponse.
Cypress Frankenfeld
1
L'appel à ndk-build ne fonctionnera que sur la ligne de commande et non depuis Android Studio.
Cameron Lowell Palmer
Bien que ce ne soit pas la réponse la plus récente, elle semble probablement la plus précise. Portez une attention particulière à l'étape 3: «Téléchargez les derniers exemples de projets Gradle».
Sean Beach
4
J'utilise ce hack au lieu de désactiver src dir afin de pouvoir éditer les fichiers c / c ++ dans l'idetasks.all { task -> if (task.name.contains('Ndk')) task.enabled = false }
sherpya
23

J'ai trouvé que "gradle 1.11 com.android.tools.build:gradle:0.9.+" prend en charge la pré-construction ndk maintenant, vous pouvez simplement mettre le * .so dans le dir src / main / jniLibs. lors de la construction, gradle emballera le ndk au bon endroit.

voici mon projet

Projet:
| --src
| - | --main
| - | - | --java
| - | - | --jniLibs
| - | - | - | --armeabi
| - | - | - | - | -. so fichiers
| --libs
| - | --other.jar
Eric Woo
la source
18

Comme l'a dit Xavier, vous pouvez mettre vos préconfigurations dans / src / main / jniLibs / si vous utilisez gradle 0.7.2+

extrait de: https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/ctDp9viWaxoJ

Naxos
la source
Comment pouvons-nous voir l'exemple mentiuoned dans 0.7.2 ndkJniLib?
Ryan Heitner
Utile pour utiliser des bibliothèques telles que SqlCipher
personne3000
16

Pour le moment (Android Studio v0.8.6), c'est assez simple. Voici les étapes pour créer une application de type "Hello world":

  1. Téléchargez le NDK Android et placez le dossier racine dans un endroit sain - au même emplacement que le dossier SDK, peut-être.

  2. Ajoutez ce qui suit à votre local.propertiesfichier: ndk.dir=<path-to-ndk>

  3. Ajoutez ce qui suit à votre fichier build.gradle à l'intérieur de la defaultConfigfermeture, juste après la versionNameligne:ndk { moduleName="hello-world" }

  4. Dans le mainrépertoire de votre module d'application , créez un nouveau dossier appelé jni.

  5. Dans ce dossier, créez un fichier appelé hello-world.c, que vous verrez ci-dessous.

  6. Voir l'exemple de Activitycode ci-dessous pour un exemple de la façon d'appeler une méthode (ou est-ce une fonction?) Dans 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'])
}

Trouvez le code source complet d'une application très similaire ici (moins le NDK).

Matt Logan
la source
Je fais exactement comme indiqué dans mon projet actuel, mais les éléments NDK ne sont toujours pas construits. Des idées? On dirait qu'il construit tout le reste, mais il suffit de sauter les trucs jni.
alice.harrison
@NannuoLei merci, j'ai essayé mais je reçois un problème où les .so ne sont pas générés. Tout le reste semble fonctionner, mais lorsque j'exécute l'apkg dans l'émulateur, il se plaint de ne pas pouvoir charger l'objet partagé.
aaa90210
@ aaa90210 votre émulateur est-il basé sur une image x86? Par défaut, NDK produira simplement une bibliothèque ARMEABI, si vous voulez créer une image x86, vous pouvez ajouter cette ligne dans Application.mk: APP_ABI: = armeabi x86
Leo prend en charge Monica Cellio
1
cela a fonctionné avec moi. PS: tous ceux qui voient cette réponse, n'oubliez pas de changer Java_me_mattlogan_ndktest_MainActivity_stringFromJNIpour la vôtre :)
AbdulMomen عبدالمؤمن
8

Si vous êtes sous unix, la dernière version (0.8) ajoute ndk-build. Voici comment l'ajouter:

android.ndk {
    moduleName "libraw"
}

Il s'attend à trouver le JNI sous 'src / main / jni', sinon vous pouvez le définir avec:

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

Depuis le 28 JAN 2014 avec la version 0.8, la build est interrompue sous Windows, vous devez désactiver la build avec:

sourceSets.main {
    jni.srcDirs = [] //disable automatic ndk-build call (currently broken for windows)
}
Anthony
la source
1
Existe-t-il une documentation sur cette fonctionnalité? Je n'ai pas pu en trouver. Pour le moment, cela semble complètement ignorer mon Android.mk/Application.mk.
plaisthos
Je n'en ai trouvé aucun. Il s'est peut-être glissé dans la construction à moitié cuit. Je suis sous Windows, donc je ne peux que confirmer que cela échoue en essayant d'appeler le script unix ndk-build. Il n'y aurait pas d'autre raison d'appeler cela que d'intégrer la compilation native dans gradle. Êtes-vous sous Unix?
Anthony
il s'attend en fait à trouver des fichiers * .so préconstruits dans jniLibs.srcDirs
Alpine
Je ne suis pas d'accord sur la base du fait qu'il plante en appelant ndk-build, ce qui n'est absolument pas nécessaire s'il nécessite des bibliothèques intégrées. Je ne peux pas confirmer car je n'ai pas le temps de vm Linux pour le moment.
Anthony
7

Une solution de contournement élégante est présentée dans https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/Z5yWAvCh4h4J .

Fondamentalement, vous créez un fichier jar contenant "lib / armeabi / yourlib.so", puis vous incluez le fichier jar dans la construction.

Aleb
la source
Ouais. Cela ne fonctionne bien que si vous ne modifiez pas souvent votre code natif. Et vous devrez inclure des fichiers jar binaires dans le référentiel. Sinon, vous vous retrouvez avec un script de construction qui crée un pot à la volée.
plaisthos
1
J'ai modifié l'exemple Hello-JNI d'Android avec un simple script bash qui encapsule ndk-build, génère des .jars pour chacun .soet les place dans le chemin de construction de gradle pour soulager cette douleur. Vérifiez-le.
dbro
4

Une bonne réponse automatisant l'empaquetage de .sofichiers -fichiers facilement compilés est donnée dans un autre thread (fermé) . Pour que cela fonctionne, j'ai dû changer la ligne:

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

dans:

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

Sans cette modification, les .sofichiers n'ont pas été trouvés et la tâche de les empaqueter ne serait donc jamais exécutée.

HYS
la source
Mise à jour: veuillez noter que dans les studios Android plus récents (au moins dans la version 1.5), le code natif est bien mieux intégré et il n'est pas nécessaire de faire cette tâche distincte pour empaqueter votre code.
HYS
4

La réponse de @plaisthos a éclaté dans la dernière version de Gradle, mais il y a toujours un moyen de le faire. Créez un native-libsrépertoire à la racine de votre répertoire de projet et copiez toutes vos bibliothèques dans ce répertoire.

Ajoutez les lignes suivantes à votre build.gradle. Construisez et soyez heureux.

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'
Leandros
la source
3

C'est le code que j'utilise pour créer en utilisant android-ndk de gradle. Pour cela, ajoutez le chemin du répertoire ndk dans gradle.propertiesie. ajouter ndkdir=/home/user/android-ndk-r9det de mettre tous les fichiers JNI dans un dossier nativeen src/main/tant que vous pouvez voir à partir du code affiché ci - dessous. Il créera un fichier jar avec des bibliothèques natives que vous pouvez utiliser normalement comme dansSystem.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'
sujithvm
la source
3

J'ai utilisé le code suivant pour compiler des bibliothèques de dropbox natives, j'utilise 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)
}
Sam
la source
2

J'ai utilisé ndk.dir=/usr/shareData/android-ndk-r11b // chemin de ndk

dans le fichier local.properties dans le projet Android Studio. et ajoutez cette ligne:
android.useDeprecatedNdk=true

dans le fichier gradle.properties dans le projet android studio.

Plus d'informations ici: http://tools.android.com/tech-docs/android-ndk-preview

Praveen Kumar Verma
la source
1

Pour développer ce que Naxos a dit (merci Naxos de m'avoir envoyé dans la bonne direction!), J'ai beaucoup appris des exemples NDK récemment publiés et j'ai posté une réponse dans une question similaire ici.

Comment configurer NDK avec le plugin Android Gradle 0.7

Cet article contient des détails complets sur la liaison des bibliothèques natives prédéfinies dans votre application pour les différentes architectures, ainsi que des informations sur la façon d'ajouter la prise en charge NDK directement au script build.gradle. Pour la plupart, vous ne devriez plus avoir à faire le travail autour du zip et de la copie.

réactif-core
la source
1

Voici les étapes que j'ai utilisées pour faire fonctionner le NDK dans mon projet Android Studio. J'ai utilisé ce tutoriel pour m'aider https://software.intel.com/en-us/videos/using-the-ndk-with-android-studio

Pour utiliser NDK, vous devez ajouter une ligne NDK à local.properties. Alors sous votre sdk.dir ajoutez

ndk.dir=C\:\\MyPathToMyNDK\ndk

Dans mes applications build.gradle, j'ai le code suivant

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

moduleName est le nom que vous souhaitez donner à votre code natif. Je crois que c'est ainsi que s'appellera la bibliothèque partagée. ldLibs me permet de me connecter à LogCat, stl est le stl que vous souhaitez importer. Il existe de nombreuses options, comme l'Eclipse NDK. ( http://www.kandroid.org/ndk/docs/CPLUSPLUS-SUPPORT.html )

Les cFlags sont encore pour moi une certaine quantité de magie noire. Je n'ai pas trouvé une bonne source pour toutes les options et ce qu'elles me donnent. Recherchez dans StackOverflow tout ce dont vous avez besoin, c'est là que je l'ai trouvé. Je sais que le c ++ 11 me permet d'utiliser le nouveau standard c ++ 11.

Voici un exemple de la façon dont je me connecte à LogCat à partir du code natif

__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());
Envoyé GR
la source
1

configurer le projet dans android studio depuis eclipse: vous devez importer le projet eclipse ndk vers android studio sans exporter vers gradle et cela fonctionne, vous devez également ajouter le chemin de ndk dans local.properties , si affiche une erreur, ajoutez

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

dans le fichier build.gradle , puis créez un dossier et un fichier jni à l' aide du terminal et exécutez-le fonctionnera

Amit Singh Tomar
la source
1
Voir voir ma propre réponse. C'est la solution de contournement que j'utilise actuellement, mais ce n'est pas vraiment une solution.
plaisthos
1

Maintenant qu'Android Studio est dans le canal stable, il est assez simple d' exécuter les exemples android-ndk . Ces exemples utilisent le plugin expérimental ndk et sont plus récents que ceux liés à la documentation en ligne Android NDK. Une fois que vous savez qu'ils fonctionnent, vous pouvez étudier les fichiers build.gradle, local.properties et gradle-wrapper.properties et modifier votre projet en conséquence. Voici les étapes pour les faire fonctionner.

  1. Accédez aux paramètres, apparence et comportement, paramètres système, Android SDK, sélectionnez l'onglet Outils SDK et vérifiez la version 1.0.0 d'Android NDK au bas de la liste. Cela téléchargera le NDK.

  2. Pointez sur l'emplacement du NDK nouvellement téléchargé. Notez qu'il sera placé dans le répertoire sdk / ndk-bundle. Pour ce faire, sélectionnez Fichier, Structure du projet, Emplacement du SDK (à gauche) et indiquez un chemin sous l'emplacement NDK Android. Cela ajoutera une entrée ndk à local.properties semblable à ceci:

    Mac / Linux: ndk.dir = / Android / sdk / ndk-bundle
    Windows: ndk.dir = C: \ Android \ sdk \ ndk-bundle

J'ai construit et déployé avec succès tous les projets dans le référentiel de cette façon, à l'exception de gles3gni, native-codec et builder. J'utilise ce qui suit:

Android Studio 1.3 build AI-141.2117773
échantillons android-ndk publiés le 28 juillet 2015 (lien ci-dessus)
SDK Tools 24.3.3
NDK r10e extrait vers C: \ Android \ sdk \ ndk-bundle
Gradle 2.5
Gradle plugin 0.2.0
Windows 8.1 64 bit

Nate
la source
1

NDK Builds et gradle (basique)

En général, la construction avec le NDK est aussi simple que de spécifier correctement un chemin ndkBuild vers Android.mk ou un chemin cmake vers CMakeLists.txt. Je recommande CMake par rapport à l'ancien Android.mk car le support C / C ++ d'Android Studio est basé sur CLion et utilise CMake comme format de projet. Cela, d'après mon expérience, a eu tendance à rendre l'EDI plus réactif sur des projets plus importants. Tout ce qui est compilé dans votre projet sera construit et copié automatiquement dans l'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'])
}

Ajout de bibliothèques prédéfinies au projet (avancé)

Les bibliothèques statiques (.a) de votre build NDK seront automatiquement incluses, mais les bibliothèques dynamiques prédéfinies (.so) devront être placées dans jniLibs. Cela peut être configuré en utilisant sourceSets, mais vous devez adopter la norme. Vous N'AVEZ PAS BESOIN de commandes supplémentaires build.gradlelors de l'inclusion de bibliothèques prédéfinies.

La disposition de jniLibs

Vous pouvez trouver plus d'informations sur la structure dans le Guide de l'utilisateur du plugin Android Gradle .

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

Vous pouvez ensuite valider l'APK résultant contenant vos fichiers .so, généralement sous build/outputs/apk/, en utilisant unzip -l myApp.apkpour lister le contenu.

Construire des bibliothèques partagées

Si vous créez une bibliothèque partagée dans le NDK, vous n'avez rien d'autre à faire. Il sera correctement regroupé dans l'APK.

Cameron Lowell Palmer
la source
0

Ajoutez simplement ces lignes à l'application 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)
}
sagus_helgy
la source
Je pense que l'approche jniLibs.srcDirs est plus propre que cela puisque vous pouvez utiliser abiFilter / flavours, mais votre approche devrait également fonctionner.
plaisthos
0

maintenant, je peux charger le si succès!

1. ajoutez le fichier .so à ce chemin

Project:

| --src | - | --main | - | - | --java | - | - | --jniLibs | - | - | - | --armeabi | - | - | - | - | -. so fichiers

2. ajoutez ce code à gradle.build

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

}

3.System.loadLibrary("yousoname");

  1. bonne chance pour vous, c'est ok avec gradle 1.2.3
xiaoyuan hu
la source
0
  1. Si votre projet a été exporté depuis eclipse, ajoutez les codes ci-dessous dans le fichier gradle :

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

2.Si vous créez un projet dans le studio Android:

créez un dossier nommé jniLibs dans src / main / , et placez vos fichiers * .so dans le dossier jniLibs.

Et copiez le code comme ci-dessous dans votre fichier gradle :

android {
    sourceSets{  
       main{  
         jniLibs.srcDir['jniLibs']  
      }  
    }
}
Yachao
la source
0

Bien que je pense que SJoshi (oracle guy) a la réponse la plus complète, le projet SWIG est un cas particulier, intéressant et utile, mais pas généralisé pour la majorité des projets qui ont bien fonctionné avec les projets SDK standard basés sur les fourmis + NDK. Nous aimerions tous utiliser le studio Android maintenant très probablement, ou voulons une chaîne d'outils de construction plus conviviale pour les CI pour mobile, ce que gradle propose théoriquement.

J'ai publié mon approche, empruntée à quelque part (j'ai trouvé cela sur SO, mais j'ai publié un résumé de l'application build.gradle: https://gist.github.com/truedat101/c45ff2b69e91d5c8e9c7962d4b96e841 ). En un mot, je recommande ce qui suit:

  • Ne mettez pas à niveau votre projet vers la dernière version de Gradle
  • Utilisez com.android.tools.build:gradle:1.5.0 dans la racine de votre projet
  • Utilisez com.android.application dans votre projet d'application
  • Assurez-vous que gradle.properties a: android.useDeprecatedNdk = true (au cas où il se plaindrait)
  • Utilisez l'approche ci-dessus pour vous assurer que vos heures et vos heures d'efforts à créer des fichiers Android.mk ne seront pas jetées. Vous contrôlez les arches cibles à construire. Et ces instructions sont gentilles pour les utilisateurs de Windows, qui devraient théoriquement pouvoir construire sur Windows sans problèmes particuliers.

Gradle pour Android a été un gâchis à mon avis, tout comme j'aime les concepts maven empruntés et la structure opiniâtre des répertoires pour un projet. Cette fonctionnalité NDK est "à venir" depuis presque 3+ ans.

truedat101
la source