SlideShare ist ein Scribd-Unternehmen logo
1 von 97
Downloaden Sie, um offline zu lesen
Android
Développement natif avec le NDK
antislashn.org Android avancé - NDK 2 / 97
NDK
● Native Development Kit
● ensemble d'outils permettant de coder en C/C++ pour la
plateforme Android
● Google met en avant que ce type dé développement
devrait-être exceptionnel
source : Google
antislashn.org Android avancé - NDK 3 / 97
NDK
● Le NDK est une suite d'outils
● compilateur
– cross-compiler : ARM,x86, MIPS
● Java Native Interface headers
● librairies C
– Math, POSIX threads,ZLib
● librairies Android
– logging, pixel buffer, native application APIs
● librairies multimédia
– OpenGL, OpenSL, OpenMAX
antislashn.org Android avancé - NDK 4 / 97
NDK - support C++
● Le support de C++ par Android est minimal
● ne prend pas en compte
– la librairie standard C++
● sauf les .h les plus communs
● pas de STL
– les exceptions
– RTTI (Run-Time Type Information)
● un ensemble de bibliothèques supplémentaires est
utilisable
– "helper runtimes"
– cf. http://developer.android.com/ndk/guides/cpp-support.html
antislashn.org Android avancé - NDK 5 / 97
NDK - support C++
● Helper Runtimes
antislashn.org Android avancé - NDK 6 / 97
Structure du NDK
● Le répertoire du NDK est soit :
● le répertoire où le NDK a été
décompressé
● le répertoire <répertoire-sdk>/ndk-bundle
si le NDK a été téléchargé par le SDK
Manager
antislashn.org Android avancé - NDK 7 / 97
Structure du NDK
● Composants principaux
● ndk-build : script principal du système de build du NDK
● ndk-gdb : script pour le débogage du code natif, utilise le
débogueur gdb
● ndk-stack : exécutable d'analyse des traces de pile créées
lors du plantage du code natif
antislashn.org Android avancé - NDK 8 / 97
Structure du NDK
● Répertoires
● build : contient les modules nécessaires pour la chaîne de
build
● platforms : contient le fichiers .h pour chaque version
Android
● samples : exemples d'application native
● sources : bibliothèques tiers pouvant être importées dans
les projets NDK
● toolchains : utilisé par le cross-compiler
antislashn.org Android avancé - NDK 9 / 97
ABI
● Application Binary Interface
● Définit l'interaction du code avec le système
● jeu d'instruction du CPU
● type de mémoire (endian)
● format du binaire
● alignements mémoire, ...
● Un ABI doit être défini pour chaque CPU cible
● actuellement : ARM, x86, MIPS
● cf. : http://developer.android.com/ndk/guides/abis.html
antislashn.org Android avancé - NDK 10 / 97
Android Studio
● Le NDK est géré par le SDK Manager
antislashn.org Android avancé - NDK 11 / 97
JNI
● Java Native Interface
● effectue le lien entre le code natif C/C++ et le code Java
● Pour écrire un code compatible JNI, il faut :
● créer des classes java dont certaines méthodes seront
implémentées en C/C++
– ces méthodes ont la signature
● public native return-type method-name (params-list)
– chaque méthode correspondra à une fonction C
● qui sera exposée dans une fichier .h
antislashn.org Android avancé - NDK 12 / 97
JNI
Application
Java
Classe
Méthodes
natives
Wrapper
C/C++
Bibliothèque
C/C++
antislashn.org Android avancé - NDK 13 / 97
Android Studio
● Créer la méthode native
public class MainActivity extends AppCompatActivity {
static{
System.loadLibrary("hello-jni");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView view = (TextView) findViewById(R.id.jni);
String msg = stringFromJNI();
view.setText(msg);
}
public native String stringFromJNI();
}
antislashn.org Android avancé - NDK 14 / 97
Android Studio
● Créer le fichier .h
● en mode console - dans le terminal d'Android Studio
– se positionner dans le répertoire java
– lancer la commande javah suivante
– le fichier .h a été généré dans le répertoire jni
javah -d ..jni org.antislashn.jni.hello.MainActivity
antislashn.org Android avancé - NDK 15 / 97
Android Studio
● Fichier .h généré
● org_antislashn_jni_hello_MainActivity.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_antislashn_jni_hello_MainActivity */
#ifndef _Included_org_antislashn_jni_hello_MainActivity
#define _Included_org_antislashn_jni_hello_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_antislashn_jni_hello_MainActivity
* Method: stringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_antislashn_jni_hello_MainActivity_stringFromJNI(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
antislashn.org Android avancé - NDK 16 / 97
Android Studio
● Codage en langage C
● le source est mis dans le répertoire jni
– nota : dans l'exemple suivant les fichiers .h et .c ont été renommés hello-jni
#include "hello-jni.h"
#include "string.h"
JNIEXPORT jstring JNICALL Java_org_antislashn_jni_hello_MainActivity_stringFromJNI
(JNIEnv* env, jobject thiz)
{
return (*env)->NewStringUTF(env,"Hello from JNI");
}
antislashn.org Android avancé - NDK 17 / 97
Android Studio
● Invocation de la méthode native
● la librairie doit être chargée
public class MainActivity extends AppCompatActivity {
static{
System.loadLibrary("hello-jni");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView view = (TextView) findViewById(R.id.jni);
String msg = stringFromJNI();
view.setText(msg);
}
public native String stringFromJNI();
}
chargement de la librairie
seul le nom du module est
précisé
invocation de la méthode native
antislashn.org Android avancé - NDK 18 / 97
Intégration des librairies C/C++
● Deux types d'intégrations
● les librairies C/C++ ont déjà été compilées pour les
différentes cibles
– répertoire libs du module
● contient les sous-répertoires correspondants aux ABIs
● le code source C/C++ doit être compilé
– les sources sont dans le répertoire jni du module
antislashn.org Android avancé - NDK 19 / 97
Étapes de création
● Créer un projet Android
● ou modifier un projet existant
● Écriture des méthodes natives Java
● Invocation de l'utilitaire javah pour créer le fichier .h
● Écriture des fonctions C
● Compilation vers les différentes plateformes (ABI)
● avec l'utilitaire ndk-build
– script qui utilise la commande make
– nécessite des fichiers .mk
antislashn.org Android avancé - NDK 20 / 97
Android Studio
● Structure de répertoire
● ajouter un répertoire jni au projet
– passer en vue "Project" pour
ajouter le répertoire
– répertoire par défaut des sources
pour gradle
● les fichiers .h et .c seront placés
dans ce répertoire
antislashn.org Android avancé - NDK 21 / 97
Android Studio
● Compilation : plusieurs possibilités
● compilation directe par ndk-build
– nécessite les fichiers *.mk
– dans le terminal Android Studio
● compilation automatique via Gradle
– pas besoin de fichier *.mk
– attention aux versions d'Android Studio
● compilation par un l'exécution d'un script Gradle
– nécessite les fichiers *.mk
– à partir de Android Studio 1.5.1
antislashn.org Android avancé - NDK 22 / 97
Logs
● Utiliser le système de log Android en natif
● inclure android/log.h
● ajouter la librairie au linker ld
– Android.mk
– build.gradle
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c calcul.c
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)
ndk {
moduleName "hello-jni"
ldLibs "log"
}
antislashn.org Android avancé - NDK 23 / 97
Logs
● Niveaux de log
● définis dans un enum
– extrait du log.h
typedef enum android_LogPriority {
ANDROID_LOG_UNKNOWN = 0,
ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO,
ANDROID_LOG_WARN,
ANDROID_LOG_ERROR,
ANDROID_LOG_FATAL,
ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
} android_LogPriority;
antislashn.org Android avancé - NDK 24 / 97
Logs
● L'utilisation du framwork de log nécessite de préciser
● le niveau de log
● le tag du log
– identificateur de l'émetteur du log
● le message de log
antislashn.org Android avancé - NDK 25 / 97
Logs
● Fonctions
● __android_log_write : pour un simple message
● __android_log_print : pour un message formaté
comme avec le printf du langage C
● __android_log_vprint : pour un message formaté
comme avec le printf du langage C
– les paramètres sont récupérés par va_list
● __android_log_assert : pour logger des échecs
d'assertion
antislashn.org Android avancé - NDK 26 / 97
Logs
● Exemple
● les logs sont affichés dans la vue "logcat"
__android_log_write(ANDROID_LOG_INFO,"JNI",">>> simple message");
__android_log_print(ANDROID_LOG_INFO,"JNI",">>> titre : %s",str);
__android_log_print(ANDROID_LOG_INFO,"JNI",">>> NB_MEMOS : %i",nbMemos);
logInfo("JNI",">>> titre : %s et NB_MEMOS : %d",str,nbMemos);
if(!ok)
__android_log_assert("!ok","JNI","ok vaut %d",ok);
void logInfo(const char* tag, const char* fmt, ...){
va_list args;
va_start(args,fmt);
__android_log_vprint(ANDROID_LOG_INFO,tag,fmt,args);
va_end(args);
}
antislashn.org Android avancé - NDK 27 / 97
Déboguer
● Android NDK permet de déboguer une application
● fonctionne à partir de la version Android 2.2 (Froyo)
● Étapes sous Android Studio (version 1.5.1)
● ajouter dans build.gradle le support du debug
● si ce n'est pas fait, créer une configuration Android Native
– vérifier que la configuration ne soit pas en erreur
● mettre les points d'arrêt dans le source C
● lancer la configuration native en mode debug
antislashn.org Android avancé - NDK 28 / 97
Déboguer
● Ajouter le support du débogage dans build.gralde
...
buldTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug{
debuggable=true
jniDebuggable=true
}
}
...
antislashn.org Android avancé - NDK 29 / 97
Déboguer
● Créer un configuration Android Native
● Run → Edit configuration ou
● si nécessaire ajouter une configuration
antislashn.org Android avancé - NDK 30 / 97
Déboguer
● Mettre les points d'arrêt nécessaires dans les sources
● Lancer l'application native en mode debug
● le démarrage de l'application peut être assez long
● l'onglet Debug s'affiche
antislashn.org Android avancé - NDK 31 / 97
JNI - Implémentation de la méthode native
● La fonction native prend au moins deux paramètres
● même si la méthode Java n'a aucun paramètre
public class Calcul {
public native void foo();
public native static void bar();
}
JNIEXPORT void JNICALL Java_org_antislashn_jni_hello_Calcul_foo (JNIEnv *, jobject);
JNIEXPORT void JNICALL Java_org_antislashn_jni_hello_Calcul_bar (JNIEnv *, jclass);
javah
antislashn.org Android avancé - NDK 32 / 97
JNI - Implémentation de la méthode native
● JNIEnv est un pointeur vers une structure
correspondant à l'interface de la JVM
● C++ : le déférencement est effectué par env->
● C : le déférencement est effectué par (*env)->
antislashn.org Android avancé - NDK 33 / 97
JNI - Implémentation de la méthode native
● Le second paramètre correspond à l'instance de la
classe ou la classe elle-même
● méthode statique : paramètre de type jclass
● méthode d'instance : paramètre de type jobject
● Les paramètres supplémentaires correspondent aux
paramètres de la méthode native Java
● deux types de paramètres
– les types primitifs
– les références
antislashn.org Android avancé - NDK 34 / 97
JNI - Types primitifs
● Les types primitifs ont une correspondance directe
avec les types C/C++
Java JNI C/C++ Taille
boolean jboolean unsigned char unsigned 8 bits
byte jbyte char signed 8 bits
char jchar unsigned short unsigned 16 bits
short jshort short signed 16 bits
int jint int signed 32 bits
long jlong long long signed 64 bits
float jfloat float 32 bits
double jdouble double 64 bits
antislashn.org Android avancé - NDK 35 / 97
JNI - les références
Types Java Types Natifs
java.lang.Class jclass
java.lang.Throwable jtrhowable
java.lang.String jstring
autres objets jobject
java.lang.Object[] jobjectArray
boolean[] jbooleanArray
byte[] jbyteArray
char[] jcharArray
short[] jshortArray
int[] jintArray
long[] jlongArray
float[] jfloatArray
double jdoubleArray
antislashn.org Android avancé - NDK 36 / 97
JNI - les références
● Les références sont passées à la méthodes natives
● elles ne peuvent pas être directement modifiées
● le garbage-collector utilise les références pour libérer la
mémoire
● JNI propose trois types de références
– référence local (local reference)
– référence globale (global reference)
– référence faible (weak reference)
antislashn.org Android avancé - NDK 37 / 97
JNI - référence locale
● Les références locales sont libérées au retour de la
fonction native
● la référence, pas l'objet qui est référencé
– les références passées au fonctions natives sont locales
– la plupart des références retournées par JNI sont locales
● une référence locale ne doit pas être sauvegardée d'un
appel de méthode à l'autre
– le code ci-dessous n'est donc pas valide
static jobject myReference;
JNIEXPORT void JNICALL Java_org_antislashn_jni_hello_Calcul_foo
(JNIEnv *env, jobject thiz, jobject lRef){
myReference = lRef;
}
antislashn.org Android avancé - NDK 38 / 97
JNI - référence locale
● Les références locales peuvent être supprimées
● La spécification impose à la JVM de garder au moins
16 références en même temps
● la JVM peut refuser d'en créer d'autres
● il peut être nécessaire de préciser explicitement le nombre
de références
(*env)->DeleteLocalRef(myReference);
(*env)->EnsureLocalCapacity(40);
antislashn.org Android avancé - NDK 39 / 97
JNI - référence globale
● Une référence globale garde une référence sur un
objet
● le garbage-collector tient compte de cette référence
● Une références globale peut être créée sur une
référence locale
● Une référence globale peut-être supprimée
jclass localClazz;
jclass globalClazz;
localClazz = (*env)->FindClass(env, "java/lang/String");
globalClazz = (*env)->NewGlobalRef(env,localClazz);
(*env)->DeleteGlobalRef(env,globalClazz);
antislashn.org Android avancé - NDK 40 / 97
JNI - référence faible
● Une référence faible peut-être utilisée d'une méthode
native à une autre méthode native
● comme pour une référence globale
● Une référence faible ne permet pas de garantir que
l'objet référencé ne supprimé par le GC
● à l'inverse d'une référence globale
antislashn.org Android avancé - NDK 41 / 97
JNI - référence faible
● Création d'une référence faible
● Vérification de la validité
● Suppression
jclass localClazz;
jclass weakClazz;
localClazz = (*env)->FindClass(env, "java/lang/String");
weakClazz = (*env)->NewWeakGlobalRef(env,localClazz);
if((*env)->IsSameObject(env,weakClazz,NULL) == JNI_TRUE){
// le GC a supprimé l'objet, l'objet ne peut pas être utilisé
}
else{
// l'objet est toujours valide, il peut-être utilisé
}
(*env)->DeleteWeakGlobalRef(env,weakClazz);
antislashn.org Android avancé - NDK 42 / 97
JNI
● Les pages suivantes présentent quelques opérations
de base
● création d'objets, conversion vers C, destruction, …
● Toutes ces opérations sont accessibles via le
pointeur vers JNIEnv
● voir la documentation
– http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html
antislashn.org Android avancé - NDK 43 / 97
JNI - opérations sur String
● Profonde différence entre les chaînes de caractères
Java et C
● JNI support Unicode et UTF-8
– les méthodes diffèrent par l'ajout de "UTF" dans leur nom
● Création
● retourne NULL si la construction a échouée
jstring javaString;
javaString = (*env)->NewStringUTF(env,"hello, world");
antislashn.org Android avancé - NDK 44 / 97
JNI - opérations sur String
● Conversion vers C
● isCopy indique si une copie a été effectuée
– peut-être NULL
● Destruction d'une chaîne C retournée par une
fonction JNI
jstring javaString;
const jbyte * str;
jboolean isCopy;
javaString = (*env)->NewStringUTF(env,"hello, world");
str = (*env)->GetStringUTFChars(env,javaString,$isCopy);
(*env)->ReleaseStringUTFChars(env,javaString,str);
antislashn.org Android avancé - NDK 45 / 97
JNI - opérations sur les tableaux
● Création
● Les différentes signatures sont du type NewXXXArray
– où XXX est Int, Char, Byte,...
– renvoie NULL si la création n'a pas été possible
● Conversion vers C
jintArray ints;
ints = (*env)->NewIntArray(env,10);
jintArray javaArray;
javaArray = (*env)->NewIntArray(env,10);
jint nativeArray[10];
(*env)->GetIntArrayRegion(env, javaArray,0,10, nativeArray);
antislashn.org Android avancé - NDK 46 / 97
JNI - opérations sur les tableaux
● Utilisation d'un pointeur
● fonctions GetXXXArrayElements
● le pointeur retourné doit être libérer
– fonctions ReleaseXXXArrayElements
jint* pJint = (*env)->GetIntArrayElements(env,javaArray);
(*env)->ReleaseIntArrayElements(env,javaArray,pJint,0);
release mode
Release Mode Action
0 Recopie contenu et libère le tableau natif
JNI_COMMIT Recopie le contenu mais ne libère pas le tableau natif
Le tableau Java peut-être mis à jour
JNI_ABORT Libère le tableau natif sans recopier son contenu
antislashn.org Android avancé - NDK 47 / 97
JNI - NIO
● Fonctions JNI pour utiliser les buffers NIO
● un "direct buffer" est un tableau d'octets
● Création
● Récupération
unsigned char* buffer = (unsigned char*) malloc(1024);
jobject directBuffer = (*env)->NewDirectByteBuffer(env,buffer,1024);
unsigned char * buf = (unsigned char*) (*env)->GetDirectBufferAddress(env,directBuffer);
antislashn.org Android avancé - NDK 48 / 97
JNI - membres d'une classe Java
● Deux types de membre
● méthode ou propriété d'instance
● méthode ou propriété de classe - propriété statique
● L'accès aux membres d'une instance (ou d'une
classe) passe par le type jclass
jclass clazz = (*env)->GetObjectClass(env,instance);
antislashn.org Android avancé - NDK 49 / 97
JNI - membres d'une classe Java
● Les extraits de code des pages suivantes utilisent la
classe Memo
public class Memo {
private static int NB_MEMOS = 0;
private int urgence = 0;
private String titre;
private String descriptif;
public Memo() {
NB_MEMOS++;
}
public Memo(String titre, String descriptif) {
this.titre = titre;
this.descriptif = descriptif;
NB_MEMOS++;
}
// Liste des getteurs / setteurs
...
}
antislashn.org Android avancé - NDK 50 / 97
JNI - signature des types
● La manipulation des propriétés et des méthodes passe par
l'utilisation des signatures de type de la JVM
Type Java Signature
boolean Z
byte B
char C
short S
int I
long J
float F
double D
classe ex: java.lang.String Ljava/lang/String;
type[] [type
méthode (arg-type) ret-type
retour void V
antislashn.org Android avancé - NDK 51 / 97
JNI - signature des types
● Exemple
● une méthode int foo(int n, String s, int[] ints);
– est associée au descripteur (ILjava/lang/String;[I)J
● une méthode int bar();
– est associée au descripteur ()I
● une méthode void foo(String s);
– est associée au descripteur (Ljava/lang/String;)V
antislashn.org Android avancé - NDK 52 / 97
JNI - signature des types
● L'outil javap aide à trouver les signatures
javap -classpath .debug -p -s org.antislashn.jni.hello.Memo
...
public int getUrgence();
descriptor: ()I
public void setUrgence(int);
descriptor: (I)V
public java.lang.String getTitre();
descriptor: ()Ljava/lang/String;
public void setTitre(java.lang.String);
descriptor: (Ljava/lang/String;)V
...
antislashn.org Android avancé - NDK 53 / 97
JNI - propriétés d'une classe Java
● Accès aux propriétés
● d'abord récupérer le jfieldID de la propriété
– méthodes de JNIEnv : GetFieldId ou GetStaticFieldId
● lire la valeur du champ
– méthodes GetXxxField pour les propriétés d'instance
– méthodes GetStaticXxxField pour les propriétés de classe
– où Xxx est Int, Boolean, Short, Object, …
● mettre à jour la valeur du champ
– méthodes SetXxxField pour les propriétés d'instance
– méthodes SetStaticXxxField pour les propriétés de classe
– où Xxx est Int, Boolean, Short, Object, …
antislashn.org Android avancé - NDK 54 / 97
JNI - propriétés d'une classe Java
● Accès aux propriétés : extrait de code
...
jclass clazz = (*env)->GetObjectClass(env,instance);
jfieldID instanceFieldID = (*env)->GetFieldID(env,clazz,"titre","Ljava/lang/String;");
jfieldID staticFieldId = (*env)->GetStaticFieldID(env,clazz,"NB_MEMOS","I");
jstring titre = (*env)->GetObjectField(env,instance,instanceFieldID);
jint nb = (*env)->GetStaticIntField(env,clazz,staticFieldId);
(*env)->SetStaticIntField(env,clazz,staticFieldId,35);
...
statique donc de
type jclass
instance de Memo reçue comme
paramètre de la méthode
nouvelle valeur pour la propriété
statique de Memo
type de la propriété
antislashn.org Android avancé - NDK 55 / 97
JNI - méthodes d'une classe Java
● Comme pour les propriétés
● deux types de méthodes
– statique
– ou d'instance
● Mêmes principes que pour accéder aux propriétés
● récupération du l'identifiant de type jmethodID
– méthodes de JNIEnv : GetMethodID, GetStaticMethodID
● puis appel de la méthode
– méthodes CallStaticXxxMethod, CallXxxMethod,..
● cf. la documentation pour l'ensemble des méthodes d'invocation
antislashn.org Android avancé - NDK 56 / 97
JNI - méthodes d'une classe Java
● Invocation d'une méthode Java, extrait de code
...
jmethodID setTitreID = (*env)->GetMethodID(env,clazz,"setTitre","(Ljava/lang/String;)V");
jstring newTitle = (*env)->NewStringUTF(env,"Nouveau titre");
(*env)->CallVoidMethod(env,instance,setTitreID,newTitle);
jmethodID getTitreID = (*env)->GetMethodID(env,clazz,"getTitre","()Ljava/lang/String;");
jstring t = (*env)->CallObjectMethod(env,instance,getTitreID);
...
paramètre de type jstring
antislashn.org Android avancé - NDK 57 / 97
Multithreading
● Un thread Java peut lancer du code natif
● aisé à coder, le code Java interagit avec les instances des
classes java.lang.Thread
● pas d'impact sur le code natif
● le code natif peut communiquer avec le code Java via
JNIEnv
antislashn.org Android avancé - NDK 58 / 97
Multithreading
● L'utilisation des threads Java doit prendre en
considération les points suivants
● le code natif est-il thread-safe ?
● le code natif ne peut pas bénéficier de la programmation
concurrente Java
● le code natif exécuté dans des threads Java différents
– ne peuvent pas communiquer
– ne peuvent pas partager des ressources
antislashn.org Android avancé - NDK 59 / 97
Multithreading
● Exemple de code
● le code Java crée des threads
● le code natif est exécuté par le thread Java
...
private void javaThreads(int threads, final int iterarions){
// Création d'un thread Java pour chaque worker natif
for(int i=0 ; i<threads ; i++){
final int id = i;
Thread thread = new Thread(){
@Override
public void run() {
nativeWorker(id,iterarions);
}
};
thread.start();
}
}
...
antislashn.org Android avancé - NDK 60 / 97
POSIX Thread
● POSIX : norme technique de l'IEEE
● IEEE : Institute of Electrical an Electronics Engineers
● POSIX : Portable Operating System Interface X
● POSIX Thread est aussi nommé Pthreads
● Utilisation de Pthread
● inclure la librairie pthread.h
– l'implémentation fait partie de Bionic
– pas de lien supplémentaire pour le linker
● Les pages suivantes présentent les principes de base de
PThread
● voir le man pour une documentation complète
antislashn.org Android avancé - NDK 61 / 97
POSIX Thread
● Création d'un thread : fonction pthread_create
● arguments
– pthread_t* thread : pointeur mis à jour par la fonction pour
retourner le nouveau thread
– pthread_attr_t const* attr : attributs nécessaires à la
création du thread (base de la pile, taille de la pile, etc...)
– void* (*start_routine)(void*) : pointeur vers fonction
de la routine devant être exécutée par le thread
– void* arg : arguments passés à la fonction, peut être NULL
● retour
– int : 0 si le thread est créé, ou code d'erreur
antislashn.org Android avancé - NDK 62 / 97
POSIX Thread
● Les pthreads ne font pas partie de la plateforme Java
● ils doivent être attachés à la JVM pour interagir avec la
partie Java
● une fois attaché le pthread doit invoquer une méthode
callback pour interagir avec l'IHM
– le pthread doit donc avoir une référence vers l'activité
● utilisation de références globales comme cache
● utilisation de la fonction JNI_OnLoad
– fonction appelée par la JVM lorsque la librairie est chargée
– l'appel de la fonction fournit comme premier paramètre un pointeur
vers la JVM
– le pthread est détaché lorsque la tâche est finie
antislashn.org Android avancé - NDK 63 / 97
POSIX Thread
● Exemple de code
● la référence vers la JVM est mise en cache
– les références globales devront être supprimées
...
static jmethodID gOnNativeMessage = NULL;
static JavaVM* gVm = NULL;
static jobject gObj = NULL;
jint JNI_OnLoad(JavaVM* vm, void* resserved){
gVm = vm;
return JNI_VERSION_1_2;
}
...
antislashn.org Android avancé - NDK 64 / 97
POSIX Thread
● Le pthread doit être créé, puis attaché à la JVM
● création par pthread_create
● la routine exécutée par pthread devra
– attacher le pthread à la JVM
– exécuter la tâche
– détacher le pthread à la JVM
antislashn.org Android avancé - NDK 65 / 97
POSIX Thread
● Extraits de code
...
pthread_t thread;
// Create a new thread
int result = pthread_create(&thread,NULL,nativeWorkerThread,static_cast<void*>(nativeWorkerArgs));
if (0 != result) {
...
création du pthread
fonction exécutée dans le pthread
pointeur sur les paramètres
passés à la fonction qui sera
exécutée dans le pthread
antislashn.org Android avancé - NDK 66 / 97
POSIX Thread
● Code de la fonction exécutée dans le pthread
static void* nativeWorkerThread(void* args) {
JNIEnv *env = NULL;
// On attache le thread courant à la JVM
// et on récupère un pointeur vers JNIEv
if (gVm->AttachCurrentThread(&env, NULL) == 0) {
NativeWorkerArgs* nArgs = static_cast<NativeWorkerArgs*>(args);
// Excéution du worker natif dans le context du thread
Java_org_antislashn_threads_MainActivity_nativeWorker(env, gObj, nArgs->id, nArgs->iterations);
delete nArgs;
// on détache le thread courant de la JVM
gVm->DetachCurrentThread();
}
return (void*)1;
}
tâche réellement exécutée dans le pthread
la tâche est attachée avant son exécution
puis détachée à la fin de son exécution
antislashn.org Android avancé - NDK 67 / 97
POSIX Thread
● Contrairement aux threads Java, les threads POSIX
peuvent renvoyer un résultat
● une fonction de type join est utilisée pour attendre la fin
du Pthread et récupérer le résultat
– int pthread_join(pthread_t thread, void** ret_val)
● cette fonction est bloquante jusqu'à la fin du pthread
● paramètres
– pthread_t thread : thread retourné par pthread_create
– void** ret_val : pointeur vers le résultat (de type void*)
retourné par le tâche du pthread
antislashn.org Android avancé - NDK 68 / 97
POSIX Thread
● Extrait de code
...
pthread_t* handles = new pthread_t[nbThreads];
...
// Attente de la fin des tâches exécutées par les pthreads
for(jint i=0 ; i< nbThreads ; i++){
void* result = NULL;
int r=0;
if((r=pthread_join(handles[i],&result)) != 0){
...
}
else{
char message[50];
sprintf(message,"Worker %d returned %d", i, result);
jstring messageString = env->NewStringUTF(message);
env->CallVoidMethod(thizz, gOnNativeMessage, messageString);
if (NULL != env->ExceptionOccurred())
{
return;
}
}
}
...
antislashn.org Android avancé - NDK 69 / 97
POSIX Thread
● Synchronisation des pthreads par mutexes
● type pthread_mutex_t
● Fonctions de base
● initialisation d'un mutex
– fonction pthread_mutex_init
– macro PTHREAD_MUTEX_INITIALIZER
● blocage d'un mutex
– fonction pthread_mutext_lock
● déblocage d'un mutex
– fonction pthread_mutex_unlock
antislashn.org Android avancé - NDK 70 / 97
POSIX Thread
● Initialisation d'un mutex
● il est nécessaire de créer un variable de type
pthread_mutext_t
– ici en variable statique
● puis appel de la fonction d'initialisation
– le second paramètre étant NULL, création d'un mutex par défaut
...
static pthread_mutex_t mutex;
...
void Java_org_antislashn_threads_MainActivity_nativeInit(JNIEnv *env, jobject thizz) {
if(pthread_mutex_init(&mutex,NULL)!=0){
jclass exceptionClazz = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exceptionClazz, "Unable to initialize mutex");
return;
}
...
antislashn.org Android avancé - NDK 71 / 97
POSIX Thread
● Le worker du pthread peut acquérir le mutex en début de tâche et
le libérer lorsque la tâche est terminée
● la fonction pthread_mutext_lock est bloquante tant que le
mutex n'est pas disponible
...
void Java_org_antislashn_threads_MainActivity_nativeWorker(JNIEnv *env, jobject thizz, jint id,
jint iterations) {
if(pthread_mutex_lock(&mutex) !=0){
jclass exceptionClazz = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exceptionClazz, "Unable to lock mutex");
return;
}
...
if (pthread_mutex_unlock(&mutex) != 0)
{
jclass exceptionClazz = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exceptionClazz, "Unable to unlock mutex");
return;
}
}
...
antislashn.org Android avancé - NDK 72 / 97
POSIX Thread
● Lorsque le mutex n'est plus utilisé il doit être détruit
● ici dans la fonction native, invoquée par onDestroy()
de l'activité
...
void Java_org_antislashn_threads_MainActivity_nativeFree(JNIEnv *env, jobject thizz) {
...
if(pthread_mutex_destroy(&mutex) != 0){
jclass exceptionClazz = env->FindClass("java/lang/RuntimeException");
env->ThrowNew(exceptionClazz, "Unable to destroy mutex");
}
}
...
antislashn.org Android avancé - NDK 73 / 97
Fichier Android.mk
● Fichier de type makefile utilisé par la chaîne de build
● Permet de regrouper les sources en modules de type
librairie statique ou dynamique
● le fichier Android.mk peut définir plusieurs modules
● seules les librairies dynamiques peuvent être incluent
dans l'apk final
● Cf. la documentation de référence
● http://android.mk/
antislashn.org Android avancé - NDK 74 / 97
Fichier Android.mk
● Fichier minimal type
● LOCAL_PATH directive de début de fichier
– indique l'endroit où se trouve les sources
– my-dir renvoie le répertoire courant (celui où est Android.mk)
● CLEAR-VARS nettoie les varaiables LOCAL_XXX
– LOCAL_MODULE, LOCAL_SRC_FILE, …
– sauf LOCAL_PATH
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
antislashn.org Android avancé - NDK 75 / 97
Fichier Android.mk
● LOCAL_MODULE définit le nom d'un module
● ce nom doit être unique, et ne doit pas contenir d'espace
– si le module est nommé foo, la librairie générée sera libfoo.so
● LOCAL_SRC_FILES liste des fichiers C/C++ qui seront
assemblés dans le module
● juste les fichier .c et .cpp
– séparés par un espace
● si les extensions sont différentes utiliser la variable
LOCAL_CPP_EXTENSION
antislashn.org Android avancé - NDK 76 / 97
Fichier Android.mk
● include $(BUILD_SHARED_LIBRARY)
● permet la génération de la librairie dynamique
● BUID_STATIC_LIBRARY génère une librairie statique
● LOCAL_STATIC_LIBRARIES ajoute des librairies
statiques au modules
antislashn.org Android avancé - NDK 77 / 97
Fichier Android.mk
● Génération de plusieurs librairies dynamiques
LOCAL_PATH := $(call my-dir)
#
# Module 1
#
include $(CLEAR_VARS)
LOCAL_MODULE := module1
LOCAL_SRC_FILES := module1.c
include $(BUILD_SHARED_LIBRARY)
#
# Module 2
#
include $(CLEAR_VARS)
LOCAL_MODULE := module2
LOCAL_SRC_FILES := module2.c
include $(BUILD_SHARED_LIBRARY)
antislashn.org Android avancé - NDK 78 / 97
Fichier Android.mk
● Génération de librairies statiques
LOCAL_PATH := $(call my-dir)
#
# 3rd party AVI library
#
include $(CLEAR_VARS)
LOCAL_MODULE := avilib
LOCAL_SRC_FILES := avilib.c platform_posix.c
include $(BUILD_STATIC_LIBRARY)
#
# Native module
#
include $(CLEAR_VARS)
LOCAL_MODULE := module
LOCAL_SRC_FILES := module.c
LOCAL_STATIC_LIBRARIES := avilib
include $(BUILD_SHARED_LIBRARY)
antislashn.org Android avancé - NDK 79 / 97
Fichier Android.mk
● Partager une librairie C/C++ entre plusieurs projets NDK
● les librairies à partager dont mises dans un répertoire
spécifique
– hors de tout projet NDK
● le nom du répertoire de la librairie correspond au nom du module
– avec leurs propres fichier .mk
● ils seront invoqués lors de la construction du projet
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := calculs
LOCAL_SRC_FILES := calculs.c
include $(BUILD_SHARED_LIBRARY)
contient
antislashn.org Android avancé - NDK 80 / 97
Fichier Android.mk
● Partager une librairie C/C++ entre plusieurs projets NDK
● le projet NDK qui utilise la librairie partagée déclare celle-
ci dans son fichier Android.mk
● il faut positionner la variable d'environnement
NDK_MODULE_PATH avant d'invoquer ndk-build
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := module
LOCAL_SRC_FILES := module.c
LOCAL_SHARED_LIBRARIES := calculs
include $(BUILD_SHARED_LIBRARY)
$(call import-module,calculs)
antislashn.org Android avancé - NDK 81 / 97
Android Studio - compilation automatique
● Par défaut Gradle construit les librairies .so si un
répertoires jni est présent
● la compilation est effectuée à la construction de l'apk
● les fichiers .mk ne sont pas nécessaires
– ils ne seront pas pris en compte
● les librairies sont construites dans le répertoire libs du
projet
– le nom par défaut de la librairie est app
● les fichiers générés pour les différentes cibles seront nommés : libapp.so
–
antislashn.org Android avancé - NDK 82 / 97
Android Studio - compilation automatique
● Il est aussi possible de paramétrer gradle pour
compiler et générer les fichiers .so au moment de la
création de l'apk
● dans le fichier build.gradle du module
– dans la section defaultConfig
● il faut que le répertoire du NDK soit positionné dans le
fichier local.properties
...
ndk {
moduleName "hello-jni"
}
...
ndk.dir=C:DEVELOPPEMENTSAndroidsdkndk-bundle
sdk.dir=C:DEVELOPPEMENTSAndroidsdk
antislashn.org Android avancé - NDK 83 / 97
Android Studio - compilation automatique
● Selon la version d'Android Studio il peut être
nécessaire d'ajouter dans le fichier gradle.properties
la ligne
● une erreur apparaît lors de la construction de l'apk
● L'ensemble des macros et variables du fichier make
sont configurables par gradle
android.useDeprecatedNdk=true
ndk {
moduleName "mymodule"
ldLibs "log"
stl "gnustl_static"
cFlags "-std=c++11 -fexceptions"
}
antislashn.org Android avancé - NDK 84 / 97
● Il faut désélectionner l'appel automatique de
ndk build‑ par gradle
● dans le fichier build.gradle
– annulation de la déclaration des répertoires JNI
Android Studio - par ndk-build
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
sourceSets{
main{
jniLibs.srcDirs "src/main/libs"
jni.srcDirs = []
}
}
...
antislashn.org Android avancé - NDK 85 / 97
Android Studio - par ndk-build
● Compilation dans le terminal
● ndk-build utilise make, il est nécessaire d'ajouter dans le
répertoire jni
– un fichier Android.mk pour l'unité de compilation
● cf. http://developer.android.com/ndk/guides/android_mk.html
– un fichier Application.mk pour les cibles
● cf. http://developer.android.com/ndk/guides/application_mk.html
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
Android.mk
APP_ABI := all
Application.mk
antislashn.org Android avancé - NDK 86 / 97
Android Studio - par ndk-build
● Compilation dans le terminal
● dans le terminal
– se positionner dans le répertoire jni
– invoquer la commande ndk-build
● Les librairies des différentes cibles
sont générées dans le répertoire
main/libs
antislashn.org Android avancé - NDK 87 / 97
Android Studio - par script gradle
● Il est aussi possible d'automatiser l'appel de ndk build‑ par un
script gradle, dans le fichier build.gradle du module
● il faut éviter l'invocation automatique de ndk build‑
– dans android.sourceSets.main
● et ajouter en fin de fichier, en fait en dehors du bloc
android{...}
jni.srcDirs = []
task ndkBuild(type:Exec) {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine 'ndk-build.cmd', '-C', file('src/main').absolutePath
} else {
commandLine 'ndk-build', '-C', file('src/main').absolutePath
}
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
antislashn.org Android avancé - NDK 88 / 97
SWIG
● SWIG est un outil permettant de connecter du code
C/C++ avec d'autres langages
● ne fait pas partie d'Android
● n'est pas dédié à Java
● SWIG nécessite l'écriture d'une interface afin de
produire le code Java
● Site officiel : http://www.swig.org/
● installation sous windows, linux, Mac
antislashn.org Android avancé - NDK 89 / 97
SWIG - exemple de base
● Comme introduction à Swig nous allons utiliser la
fonction getuid
● cf. http://linux.die.net/man/2/getuid
● Etapes
● écrire l"interface SWIG
● généré le proxy Java
● ajouter les sources générées par SWIG dans Android.mk
● utiliser le proxy généré par SWIG
antislashn.org Android avancé - NDK 90 / 97
SWIG - interface
● Ce fichier déclare
● les prototypes de fonctions
● les déclarations de classes
● les déclarations de variables
● Syntaxe similaire à un header C/C++
● Le fichier interface s’appellera unix.i
● mis dans le répertoire jni
antislashn.org Android avancé - NDK 91 / 97
SWIG - interface
● Interface Unix.i
/* Module name is unix. */
%module unix
%{
/* Include the POSIX operating system APIs. */
#include < unistd.h>
%}
/* Tell SWIG about uid_t. */
typedef unsigned int uid_t;
/* Ask SWIG to wrap getuid function. */
extern uid_t getuid(void);
antislashn.org Android avancé - NDK 92 / 97
SWIG - génération du proxy Java
● Auparavant il faut créer le package java de la classe
proxy
● ici : org.antislashn.swig.proxy
● Puis lancer la commande swig
● Génération :
● un fichier Unix_wrap.c
● deux classes Java
– Unix.java
– UnixJNI.java
swig -java -package org.antislashn.swig.proxy -outdir java/org/antislashn/swig/proxy jni/unix.i
antislashn.org Android avancé - NDK 93 / 97
SWIG - utilisation
● Deux classes Java ont été générées
● L'utilisation est triviale
public class Unix {
public static long getuid() {
return UnixJNI.getuid();
}
}
public class UnixJNI {
public final static native long getuid();
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.uid);
tv.setText(Long.toString(Unix.getuid()));
}
}
antislashn.org Android avancé - NDK 94 / 97
Web
● http://developer.android.com/ndk/index.html
● http://developer.android.com/tools/building/configuring-gradle.html
● http://tools.android.com/tech-docs/new-build-system/user-guide
● http://tools.android.com/tech-docs/new-build-system/gradle-experimental
● http://android.mk/
● http://mobilepearls.com/labs/native-android-api/
● http://developer.android.com/ndk/guides/cpp-support.html
● http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html
● http://linux.die.net/man/7/pthreads
antislashn.org Android avancé - NDK 95 / 97
Bibliographie
● Apress
● Pro Android C++ with th NDK
● Beginning Android C++ Game Developement
● Packt Publishing
● Android Native Development Kit Cookbook
● Android NDK
● Gradle for Android
antislashn.org Titre support 96 / 97
copyleft
Support de formation créé par
Franck SIMON
http://www.franck-simon.com
antislashn.org Titre support 97 / 97
copyleft
Cette œuvre est mise à disposition sous licence
Attribution
Pas d'Utilisation Commerciale
Partage dans les Mêmes Conditions 3.0 France.
Pour voir une copie de cette licence, visitez
http://creativecommons.org/licenses/by-nc-sa/3.0/fr/
ou écrivez à
Creative Commons, 444 Castro Street, Suite 900,
Mountain View, California, 94041, USA.

Weitere ähnliche Inhalte

Was ist angesagt?

GWT Principes & Techniques
GWT Principes & TechniquesGWT Principes & Techniques
GWT Principes & TechniquesRachid NID SAID
 
Introduction à Android
Introduction à AndroidIntroduction à Android
Introduction à AndroidYoann Gotthilf
 
01 programmation mobile - android - (introduction)
01 programmation mobile - android - (introduction)01 programmation mobile - android - (introduction)
01 programmation mobile - android - (introduction)TECOS
 
Presentation of GWT 2.4 (PDF version)
Presentation of GWT 2.4 (PDF version)Presentation of GWT 2.4 (PDF version)
Presentation of GWT 2.4 (PDF version)Celinio Fernandes
 
5 android web_service
5 android web_service5 android web_service
5 android web_serviceSaber LAJILI
 
PAUG 03/05/2016 : Rechercher et analyser les fuites mémoires dans une applica...
PAUG 03/05/2016 : Rechercher et analyser les fuites mémoires dans une applica...PAUG 03/05/2016 : Rechercher et analyser les fuites mémoires dans une applica...
PAUG 03/05/2016 : Rechercher et analyser les fuites mémoires dans une applica...Ludovic ROLAND
 
Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika
Présentation Gradle au LyonJUG par Grégory Boissinot - ZenikaPrésentation Gradle au LyonJUG par Grégory Boissinot - Zenika
Présentation Gradle au LyonJUG par Grégory Boissinot - ZenikaZenika
 
Presentation of GWT 2.4 (PowerPoint version)
Presentation of GWT 2.4 (PowerPoint version)Presentation of GWT 2.4 (PowerPoint version)
Presentation of GWT 2.4 (PowerPoint version)Celinio Fernandes
 
Présentation du retour d'expérience sur Git
Présentation du retour d'expérience sur GitPrésentation du retour d'expérience sur Git
Présentation du retour d'expérience sur GitIppon
 
Anniversaire Paris JUG - Deja 10 ans - retour vers le futur avec JMX
Anniversaire Paris JUG -  Deja 10 ans - retour vers le futur avec JMXAnniversaire Paris JUG -  Deja 10 ans - retour vers le futur avec JMX
Anniversaire Paris JUG - Deja 10 ans - retour vers le futur avec JMXJean-Michel Doudoux
 
20081113 - Nantes Jug - Apache Maven
20081113 - Nantes Jug - Apache Maven20081113 - Nantes Jug - Apache Maven
20081113 - Nantes Jug - Apache MavenArnaud Héritier
 
Voxxeddays lux 2018 apres java 8, java 9 et 10
Voxxeddays lux 2018 apres java 8, java 9 et 10Voxxeddays lux 2018 apres java 8, java 9 et 10
Voxxeddays lux 2018 apres java 8, java 9 et 10Jean-Michel Doudoux
 
Lyon JUG 2018 - Java le changement c'est maintenant
Lyon JUG 2018 - Java le changement c'est maintenantLyon JUG 2018 - Java le changement c'est maintenant
Lyon JUG 2018 - Java le changement c'est maintenantJean-Michel Doudoux
 
20080311 - Paris Vi Master STL TA - Initiation Maven
20080311 - Paris Vi Master STL TA - Initiation Maven20080311 - Paris Vi Master STL TA - Initiation Maven
20080311 - Paris Vi Master STL TA - Initiation MavenArnaud Héritier
 

Was ist angesagt? (20)

GWT Principes & Techniques
GWT Principes & TechniquesGWT Principes & Techniques
GWT Principes & Techniques
 
Présentation1
Présentation1Présentation1
Présentation1
 
Introduction à Android
Introduction à AndroidIntroduction à Android
Introduction à Android
 
01 programmation mobile - android - (introduction)
01 programmation mobile - android - (introduction)01 programmation mobile - android - (introduction)
01 programmation mobile - android - (introduction)
 
Presentation of GWT 2.4 (PDF version)
Presentation of GWT 2.4 (PDF version)Presentation of GWT 2.4 (PDF version)
Presentation of GWT 2.4 (PDF version)
 
5 android web_service
5 android web_service5 android web_service
5 android web_service
 
PAUG 03/05/2016 : Rechercher et analyser les fuites mémoires dans une applica...
PAUG 03/05/2016 : Rechercher et analyser les fuites mémoires dans une applica...PAUG 03/05/2016 : Rechercher et analyser les fuites mémoires dans une applica...
PAUG 03/05/2016 : Rechercher et analyser les fuites mémoires dans une applica...
 
Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika
Présentation Gradle au LyonJUG par Grégory Boissinot - ZenikaPrésentation Gradle au LyonJUG par Grégory Boissinot - Zenika
Présentation Gradle au LyonJUG par Grégory Boissinot - Zenika
 
Presentation of GWT 2.4 (PowerPoint version)
Presentation of GWT 2.4 (PowerPoint version)Presentation of GWT 2.4 (PowerPoint version)
Presentation of GWT 2.4 (PowerPoint version)
 
Présentation du retour d'expérience sur Git
Présentation du retour d'expérience sur GitPrésentation du retour d'expérience sur Git
Présentation du retour d'expérience sur Git
 
UKO-JAVA1001-slides
UKO-JAVA1001-slidesUKO-JAVA1001-slides
UKO-JAVA1001-slides
 
Cours Android
Cours AndroidCours Android
Cours Android
 
Jenkins
JenkinsJenkins
Jenkins
 
Anniversaire Paris JUG - Deja 10 ans - retour vers le futur avec JMX
Anniversaire Paris JUG -  Deja 10 ans - retour vers le futur avec JMXAnniversaire Paris JUG -  Deja 10 ans - retour vers le futur avec JMX
Anniversaire Paris JUG - Deja 10 ans - retour vers le futur avec JMX
 
20081113 - Nantes Jug - Apache Maven
20081113 - Nantes Jug - Apache Maven20081113 - Nantes Jug - Apache Maven
20081113 - Nantes Jug - Apache Maven
 
Voxxeddays lux 2018 apres java 8, java 9 et 10
Voxxeddays lux 2018 apres java 8, java 9 et 10Voxxeddays lux 2018 apres java 8, java 9 et 10
Voxxeddays lux 2018 apres java 8, java 9 et 10
 
Tutorial android
Tutorial androidTutorial android
Tutorial android
 
Lyon JUG 2018 - Java le changement c'est maintenant
Lyon JUG 2018 - Java le changement c'est maintenantLyon JUG 2018 - Java le changement c'est maintenant
Lyon JUG 2018 - Java le changement c'est maintenant
 
Tutoriel GIT
Tutoriel GITTutoriel GIT
Tutoriel GIT
 
20080311 - Paris Vi Master STL TA - Initiation Maven
20080311 - Paris Vi Master STL TA - Initiation Maven20080311 - Paris Vi Master STL TA - Initiation Maven
20080311 - Paris Vi Master STL TA - Initiation Maven
 

Andere mochten auch

Facebook, même pas peur !
Facebook, même pas peur !Facebook, même pas peur !
Facebook, même pas peur !ateliere2m
 
Curso práctico sobre contratación laboral
Curso práctico sobre contratación laboralCurso práctico sobre contratación laboral
Curso práctico sobre contratación laboralCenproexFormacion
 
World trade report15_f
World trade report15_fWorld trade report15_f
World trade report15_fDaniel Dufourt
 
Design beleven, opties gebruiken, individualiteit creëren, met Bosse Nucleon
Design beleven, opties gebruiken, individualiteit creëren, met Bosse NucleonDesign beleven, opties gebruiken, individualiteit creëren, met Bosse Nucleon
Design beleven, opties gebruiken, individualiteit creëren, met Bosse NucleonHAGELE kantoormeubilair
 
Smo Manuel Roulaud Aveclogo 20110821
Smo Manuel Roulaud Aveclogo 20110821Smo Manuel Roulaud Aveclogo 20110821
Smo Manuel Roulaud Aveclogo 20110821ROULAUD
 
10 les-meilleurs-effets-optiques4
10 les-meilleurs-effets-optiques410 les-meilleurs-effets-optiques4
10 les-meilleurs-effets-optiques4Dominique Pongi
 
L’Enjeu Des Programmes Adr Pour Les Entreprises EuropéEnnes
L’Enjeu Des Programmes Adr Pour Les Entreprises EuropéEnnesL’Enjeu Des Programmes Adr Pour Les Entreprises EuropéEnnes
L’Enjeu Des Programmes Adr Pour Les Entreprises EuropéEnnesgnoiry
 
Calendrier droit-francais-13
Calendrier droit-francais-13Calendrier droit-francais-13
Calendrier droit-francais-13essa1988
 
Julien Verhaeghe - API REST : Le module Services de Drupal - Drupal Meetup Ro...
Julien Verhaeghe - API REST : Le module Services de Drupal - Drupal Meetup Ro...Julien Verhaeghe - API REST : Le module Services de Drupal - Drupal Meetup Ro...
Julien Verhaeghe - API REST : Le module Services de Drupal - Drupal Meetup Ro...Normandie Web Xperts
 
Ppw Final presentation Oxfam work ( EPHEC, end of 2nd grade)
Ppw Final presentation Oxfam work ( EPHEC, end of 2nd grade)Ppw Final presentation Oxfam work ( EPHEC, end of 2nd grade)
Ppw Final presentation Oxfam work ( EPHEC, end of 2nd grade)mrloicsimon
 
Taller de informática.
Taller de informática. Taller de informática.
Taller de informática. Laura Valentina
 

Andere mochten auch (20)

Facebook, même pas peur !
Facebook, même pas peur !Facebook, même pas peur !
Facebook, même pas peur !
 
Ismaelestanga
IsmaelestangaIsmaelestanga
Ismaelestanga
 
Curso práctico sobre contratación laboral
Curso práctico sobre contratación laboralCurso práctico sobre contratación laboral
Curso práctico sobre contratación laboral
 
Dirección Pyme
Dirección PymeDirección Pyme
Dirección Pyme
 
World trade report15_f
World trade report15_fWorld trade report15_f
World trade report15_f
 
Web2 02
Web2 02Web2 02
Web2 02
 
Design beleven, opties gebruiken, individualiteit creëren, met Bosse Nucleon
Design beleven, opties gebruiken, individualiteit creëren, met Bosse NucleonDesign beleven, opties gebruiken, individualiteit creëren, met Bosse Nucleon
Design beleven, opties gebruiken, individualiteit creëren, met Bosse Nucleon
 
Smo Manuel Roulaud Aveclogo 20110821
Smo Manuel Roulaud Aveclogo 20110821Smo Manuel Roulaud Aveclogo 20110821
Smo Manuel Roulaud Aveclogo 20110821
 
Primera Guerra Mundial
Primera Guerra Mundial Primera Guerra Mundial
Primera Guerra Mundial
 
10 les-meilleurs-effets-optiques4
10 les-meilleurs-effets-optiques410 les-meilleurs-effets-optiques4
10 les-meilleurs-effets-optiques4
 
Deux cadeaux
Deux cadeauxDeux cadeaux
Deux cadeaux
 
L’Enjeu Des Programmes Adr Pour Les Entreprises EuropéEnnes
L’Enjeu Des Programmes Adr Pour Les Entreprises EuropéEnnesL’Enjeu Des Programmes Adr Pour Les Entreprises EuropéEnnes
L’Enjeu Des Programmes Adr Pour Les Entreprises EuropéEnnes
 
Kevin richardson
Kevin richardsonKevin richardson
Kevin richardson
 
Fibs600
Fibs600Fibs600
Fibs600
 
Calendrier droit-francais-13
Calendrier droit-francais-13Calendrier droit-francais-13
Calendrier droit-francais-13
 
dérive des continents
dérive des continentsdérive des continents
dérive des continents
 
Julien Verhaeghe - API REST : Le module Services de Drupal - Drupal Meetup Ro...
Julien Verhaeghe - API REST : Le module Services de Drupal - Drupal Meetup Ro...Julien Verhaeghe - API REST : Le module Services de Drupal - Drupal Meetup Ro...
Julien Verhaeghe - API REST : Le module Services de Drupal - Drupal Meetup Ro...
 
Ppw Final presentation Oxfam work ( EPHEC, end of 2nd grade)
Ppw Final presentation Oxfam work ( EPHEC, end of 2nd grade)Ppw Final presentation Oxfam work ( EPHEC, end of 2nd grade)
Ppw Final presentation Oxfam work ( EPHEC, end of 2nd grade)
 
Trop mignon
Trop mignonTrop mignon
Trop mignon
 
Taller de informática.
Taller de informática. Taller de informática.
Taller de informática.
 

Ähnlich wie Android NDK

Open Wide : Les outils pour le développement des systemes embarques
Open Wide : Les outils pour le développement des systemes embarquesOpen Wide : Les outils pour le développement des systemes embarques
Open Wide : Les outils pour le développement des systemes embarquesAlexandre LAHAYE
 
Drupal7 - Bonnes Pratiques (Partie 1)
Drupal7 - Bonnes Pratiques (Partie 1)Drupal7 - Bonnes Pratiques (Partie 1)
Drupal7 - Bonnes Pratiques (Partie 1)Alexandre Marie
 
Introduction_Android_-_Complet.pdf
Introduction_Android_-_Complet.pdfIntroduction_Android_-_Complet.pdf
Introduction_Android_-_Complet.pdfmed_univ78
 
Cours android
Cours androidCours android
Cours androidAd Hafsa
 
Intégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIIntégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIHugo Hamon
 
cours Android.pptx
cours Android.pptxcours Android.pptx
cours Android.pptxYaminaGh1
 
Installer et configurer NAGIOS sous linux
Installer et configurer NAGIOS sous linuxInstaller et configurer NAGIOS sous linux
Installer et configurer NAGIOS sous linuxZakariyaa AIT ELMOUDEN
 
cours-android.pdf
cours-android.pdfcours-android.pdf
cours-android.pdfmed_univ78
 
WordCamp Lyon 2015 - WordPress, Git et l'intégration continue
 WordCamp Lyon 2015 - WordPress, Git et l'intégration continue WordCamp Lyon 2015 - WordPress, Git et l'intégration continue
WordCamp Lyon 2015 - WordPress, Git et l'intégration continueStéphane HULARD
 
Prérequis au développement google android
Prérequis au développement google androidPrérequis au développement google android
Prérequis au développement google androidThierry Gayet
 
Composants d-une application Android.ppt
Composants d-une application Android.pptComposants d-une application Android.ppt
Composants d-une application Android.pptmahamaalej3
 

Ähnlich wie Android NDK (20)

1-android.pdf
1-android.pdf1-android.pdf
1-android.pdf
 
openFrameworks
openFrameworksopenFrameworks
openFrameworks
 
Native script
Native scriptNative script
Native script
 
Infrastructure as code drupal
Infrastructure as code drupalInfrastructure as code drupal
Infrastructure as code drupal
 
Catalogue PFE 2019
Catalogue PFE 2019Catalogue PFE 2019
Catalogue PFE 2019
 
Open Wide : Les outils pour le développement des systemes embarques
Open Wide : Les outils pour le développement des systemes embarquesOpen Wide : Les outils pour le développement des systemes embarques
Open Wide : Les outils pour le développement des systemes embarques
 
Installation open erp
Installation open erpInstallation open erp
Installation open erp
 
Drupal7 - Bonnes Pratiques (Partie 1)
Drupal7 - Bonnes Pratiques (Partie 1)Drupal7 - Bonnes Pratiques (Partie 1)
Drupal7 - Bonnes Pratiques (Partie 1)
 
introduction au CPP
introduction au CPPintroduction au CPP
introduction au CPP
 
Introduction_Android_-_Complet.pdf
Introduction_Android_-_Complet.pdfIntroduction_Android_-_Complet.pdf
Introduction_Android_-_Complet.pdf
 
Développement Sous Android
Développement Sous AndroidDéveloppement Sous Android
Développement Sous Android
 
Cours android
Cours androidCours android
Cours android
 
Intégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CIIntégration Continue PHP avec Jenkins CI
Intégration Continue PHP avec Jenkins CI
 
cours Android.pptx
cours Android.pptxcours Android.pptx
cours Android.pptx
 
Installer et configurer NAGIOS sous linux
Installer et configurer NAGIOS sous linuxInstaller et configurer NAGIOS sous linux
Installer et configurer NAGIOS sous linux
 
cours-android.pdf
cours-android.pdfcours-android.pdf
cours-android.pdf
 
WordCamp Lyon 2015 - WordPress, Git et l'intégration continue
 WordCamp Lyon 2015 - WordPress, Git et l'intégration continue WordCamp Lyon 2015 - WordPress, Git et l'intégration continue
WordCamp Lyon 2015 - WordPress, Git et l'intégration continue
 
Android pour l'industrie
Android pour l'industrieAndroid pour l'industrie
Android pour l'industrie
 
Prérequis au développement google android
Prérequis au développement google androidPrérequis au développement google android
Prérequis au développement google android
 
Composants d-une application Android.ppt
Composants d-une application Android.pptComposants d-une application Android.ppt
Composants d-une application Android.ppt
 

Mehr von Franck SIMON

Java 8 - interfaces
Java 8 - interfacesJava 8 - interfaces
Java 8 - interfacesFranck SIMON
 
Java 8 - collections et stream
Java 8 - collections et streamJava 8 - collections et stream
Java 8 - collections et streamFranck SIMON
 
Description d'un fichier de prélèvements SEPA minimum
Description d'un fichier de prélèvements SEPA minimumDescription d'un fichier de prélèvements SEPA minimum
Description d'un fichier de prélèvements SEPA minimumFranck SIMON
 
Tomcat and apache httpd training
Tomcat and apache httpd trainingTomcat and apache httpd training
Tomcat and apache httpd trainingFranck SIMON
 
JBoss - chapitre JMX
JBoss - chapitre JMXJBoss - chapitre JMX
JBoss - chapitre JMXFranck SIMON
 
Java - programmation concurrente
Java - programmation concurrenteJava - programmation concurrente
Java - programmation concurrenteFranck SIMON
 
Architectures distribuées
Architectures distribuéesArchitectures distribuées
Architectures distribuéesFranck SIMON
 

Mehr von Franck SIMON (12)

Java 9 modules
Java 9    modulesJava 9    modules
Java 9 modules
 
Java 8 - lambda
Java 8 - lambdaJava 8 - lambda
Java 8 - lambda
 
Java 8 - interfaces
Java 8 - interfacesJava 8 - interfaces
Java 8 - interfaces
 
Java 8 - DateTime
Java 8 - DateTimeJava 8 - DateTime
Java 8 - DateTime
 
Java 8 - collections et stream
Java 8 - collections et streamJava 8 - collections et stream
Java 8 - collections et stream
 
Description d'un fichier de prélèvements SEPA minimum
Description d'un fichier de prélèvements SEPA minimumDescription d'un fichier de prélèvements SEPA minimum
Description d'un fichier de prélèvements SEPA minimum
 
Tomcat and apache httpd training
Tomcat and apache httpd trainingTomcat and apache httpd training
Tomcat and apache httpd training
 
JBoss - chapitre JMX
JBoss - chapitre JMXJBoss - chapitre JMX
JBoss - chapitre JMX
 
Java - programmation concurrente
Java - programmation concurrenteJava - programmation concurrente
Java - programmation concurrente
 
Squid
SquidSquid
Squid
 
Architectures distribuées
Architectures distribuéesArchitectures distribuées
Architectures distribuées
 
jQuery
jQueryjQuery
jQuery
 

Android NDK

  • 2. antislashn.org Android avancé - NDK 2 / 97 NDK ● Native Development Kit ● ensemble d'outils permettant de coder en C/C++ pour la plateforme Android ● Google met en avant que ce type dé développement devrait-être exceptionnel source : Google
  • 3. antislashn.org Android avancé - NDK 3 / 97 NDK ● Le NDK est une suite d'outils ● compilateur – cross-compiler : ARM,x86, MIPS ● Java Native Interface headers ● librairies C – Math, POSIX threads,ZLib ● librairies Android – logging, pixel buffer, native application APIs ● librairies multimédia – OpenGL, OpenSL, OpenMAX
  • 4. antislashn.org Android avancé - NDK 4 / 97 NDK - support C++ ● Le support de C++ par Android est minimal ● ne prend pas en compte – la librairie standard C++ ● sauf les .h les plus communs ● pas de STL – les exceptions – RTTI (Run-Time Type Information) ● un ensemble de bibliothèques supplémentaires est utilisable – "helper runtimes" – cf. http://developer.android.com/ndk/guides/cpp-support.html
  • 5. antislashn.org Android avancé - NDK 5 / 97 NDK - support C++ ● Helper Runtimes
  • 6. antislashn.org Android avancé - NDK 6 / 97 Structure du NDK ● Le répertoire du NDK est soit : ● le répertoire où le NDK a été décompressé ● le répertoire <répertoire-sdk>/ndk-bundle si le NDK a été téléchargé par le SDK Manager
  • 7. antislashn.org Android avancé - NDK 7 / 97 Structure du NDK ● Composants principaux ● ndk-build : script principal du système de build du NDK ● ndk-gdb : script pour le débogage du code natif, utilise le débogueur gdb ● ndk-stack : exécutable d'analyse des traces de pile créées lors du plantage du code natif
  • 8. antislashn.org Android avancé - NDK 8 / 97 Structure du NDK ● Répertoires ● build : contient les modules nécessaires pour la chaîne de build ● platforms : contient le fichiers .h pour chaque version Android ● samples : exemples d'application native ● sources : bibliothèques tiers pouvant être importées dans les projets NDK ● toolchains : utilisé par le cross-compiler
  • 9. antislashn.org Android avancé - NDK 9 / 97 ABI ● Application Binary Interface ● Définit l'interaction du code avec le système ● jeu d'instruction du CPU ● type de mémoire (endian) ● format du binaire ● alignements mémoire, ... ● Un ABI doit être défini pour chaque CPU cible ● actuellement : ARM, x86, MIPS ● cf. : http://developer.android.com/ndk/guides/abis.html
  • 10. antislashn.org Android avancé - NDK 10 / 97 Android Studio ● Le NDK est géré par le SDK Manager
  • 11. antislashn.org Android avancé - NDK 11 / 97 JNI ● Java Native Interface ● effectue le lien entre le code natif C/C++ et le code Java ● Pour écrire un code compatible JNI, il faut : ● créer des classes java dont certaines méthodes seront implémentées en C/C++ – ces méthodes ont la signature ● public native return-type method-name (params-list) – chaque méthode correspondra à une fonction C ● qui sera exposée dans une fichier .h
  • 12. antislashn.org Android avancé - NDK 12 / 97 JNI Application Java Classe Méthodes natives Wrapper C/C++ Bibliothèque C/C++
  • 13. antislashn.org Android avancé - NDK 13 / 97 Android Studio ● Créer la méthode native public class MainActivity extends AppCompatActivity { static{ System.loadLibrary("hello-jni"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView view = (TextView) findViewById(R.id.jni); String msg = stringFromJNI(); view.setText(msg); } public native String stringFromJNI(); }
  • 14. antislashn.org Android avancé - NDK 14 / 97 Android Studio ● Créer le fichier .h ● en mode console - dans le terminal d'Android Studio – se positionner dans le répertoire java – lancer la commande javah suivante – le fichier .h a été généré dans le répertoire jni javah -d ..jni org.antislashn.jni.hello.MainActivity
  • 15. antislashn.org Android avancé - NDK 15 / 97 Android Studio ● Fichier .h généré ● org_antislashn_jni_hello_MainActivity.h /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class org_antislashn_jni_hello_MainActivity */ #ifndef _Included_org_antislashn_jni_hello_MainActivity #define _Included_org_antislashn_jni_hello_MainActivity #ifdef __cplusplus extern "C" { #endif /* * Class: org_antislashn_jni_hello_MainActivity * Method: stringFromJNI * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_org_antislashn_jni_hello_MainActivity_stringFromJNI(JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
  • 16. antislashn.org Android avancé - NDK 16 / 97 Android Studio ● Codage en langage C ● le source est mis dans le répertoire jni – nota : dans l'exemple suivant les fichiers .h et .c ont été renommés hello-jni #include "hello-jni.h" #include "string.h" JNIEXPORT jstring JNICALL Java_org_antislashn_jni_hello_MainActivity_stringFromJNI (JNIEnv* env, jobject thiz) { return (*env)->NewStringUTF(env,"Hello from JNI"); }
  • 17. antislashn.org Android avancé - NDK 17 / 97 Android Studio ● Invocation de la méthode native ● la librairie doit être chargée public class MainActivity extends AppCompatActivity { static{ System.loadLibrary("hello-jni"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView view = (TextView) findViewById(R.id.jni); String msg = stringFromJNI(); view.setText(msg); } public native String stringFromJNI(); } chargement de la librairie seul le nom du module est précisé invocation de la méthode native
  • 18. antislashn.org Android avancé - NDK 18 / 97 Intégration des librairies C/C++ ● Deux types d'intégrations ● les librairies C/C++ ont déjà été compilées pour les différentes cibles – répertoire libs du module ● contient les sous-répertoires correspondants aux ABIs ● le code source C/C++ doit être compilé – les sources sont dans le répertoire jni du module
  • 19. antislashn.org Android avancé - NDK 19 / 97 Étapes de création ● Créer un projet Android ● ou modifier un projet existant ● Écriture des méthodes natives Java ● Invocation de l'utilitaire javah pour créer le fichier .h ● Écriture des fonctions C ● Compilation vers les différentes plateformes (ABI) ● avec l'utilitaire ndk-build – script qui utilise la commande make – nécessite des fichiers .mk
  • 20. antislashn.org Android avancé - NDK 20 / 97 Android Studio ● Structure de répertoire ● ajouter un répertoire jni au projet – passer en vue "Project" pour ajouter le répertoire – répertoire par défaut des sources pour gradle ● les fichiers .h et .c seront placés dans ce répertoire
  • 21. antislashn.org Android avancé - NDK 21 / 97 Android Studio ● Compilation : plusieurs possibilités ● compilation directe par ndk-build – nécessite les fichiers *.mk – dans le terminal Android Studio ● compilation automatique via Gradle – pas besoin de fichier *.mk – attention aux versions d'Android Studio ● compilation par un l'exécution d'un script Gradle – nécessite les fichiers *.mk – à partir de Android Studio 1.5.1
  • 22. antislashn.org Android avancé - NDK 22 / 97 Logs ● Utiliser le système de log Android en natif ● inclure android/log.h ● ajouter la librairie au linker ld – Android.mk – build.gradle LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c calcul.c LOCAL_LDLIBS += -llog include $(BUILD_SHARED_LIBRARY) ndk { moduleName "hello-jni" ldLibs "log" }
  • 23. antislashn.org Android avancé - NDK 23 / 97 Logs ● Niveaux de log ● définis dans un enum – extrait du log.h typedef enum android_LogPriority { ANDROID_LOG_UNKNOWN = 0, ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */ ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */ } android_LogPriority;
  • 24. antislashn.org Android avancé - NDK 24 / 97 Logs ● L'utilisation du framwork de log nécessite de préciser ● le niveau de log ● le tag du log – identificateur de l'émetteur du log ● le message de log
  • 25. antislashn.org Android avancé - NDK 25 / 97 Logs ● Fonctions ● __android_log_write : pour un simple message ● __android_log_print : pour un message formaté comme avec le printf du langage C ● __android_log_vprint : pour un message formaté comme avec le printf du langage C – les paramètres sont récupérés par va_list ● __android_log_assert : pour logger des échecs d'assertion
  • 26. antislashn.org Android avancé - NDK 26 / 97 Logs ● Exemple ● les logs sont affichés dans la vue "logcat" __android_log_write(ANDROID_LOG_INFO,"JNI",">>> simple message"); __android_log_print(ANDROID_LOG_INFO,"JNI",">>> titre : %s",str); __android_log_print(ANDROID_LOG_INFO,"JNI",">>> NB_MEMOS : %i",nbMemos); logInfo("JNI",">>> titre : %s et NB_MEMOS : %d",str,nbMemos); if(!ok) __android_log_assert("!ok","JNI","ok vaut %d",ok); void logInfo(const char* tag, const char* fmt, ...){ va_list args; va_start(args,fmt); __android_log_vprint(ANDROID_LOG_INFO,tag,fmt,args); va_end(args); }
  • 27. antislashn.org Android avancé - NDK 27 / 97 Déboguer ● Android NDK permet de déboguer une application ● fonctionne à partir de la version Android 2.2 (Froyo) ● Étapes sous Android Studio (version 1.5.1) ● ajouter dans build.gradle le support du debug ● si ce n'est pas fait, créer une configuration Android Native – vérifier que la configuration ne soit pas en erreur ● mettre les points d'arrêt dans le source C ● lancer la configuration native en mode debug
  • 28. antislashn.org Android avancé - NDK 28 / 97 Déboguer ● Ajouter le support du débogage dans build.gralde ... buldTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug{ debuggable=true jniDebuggable=true } } ...
  • 29. antislashn.org Android avancé - NDK 29 / 97 Déboguer ● Créer un configuration Android Native ● Run → Edit configuration ou ● si nécessaire ajouter une configuration
  • 30. antislashn.org Android avancé - NDK 30 / 97 Déboguer ● Mettre les points d'arrêt nécessaires dans les sources ● Lancer l'application native en mode debug ● le démarrage de l'application peut être assez long ● l'onglet Debug s'affiche
  • 31. antislashn.org Android avancé - NDK 31 / 97 JNI - Implémentation de la méthode native ● La fonction native prend au moins deux paramètres ● même si la méthode Java n'a aucun paramètre public class Calcul { public native void foo(); public native static void bar(); } JNIEXPORT void JNICALL Java_org_antislashn_jni_hello_Calcul_foo (JNIEnv *, jobject); JNIEXPORT void JNICALL Java_org_antislashn_jni_hello_Calcul_bar (JNIEnv *, jclass); javah
  • 32. antislashn.org Android avancé - NDK 32 / 97 JNI - Implémentation de la méthode native ● JNIEnv est un pointeur vers une structure correspondant à l'interface de la JVM ● C++ : le déférencement est effectué par env-> ● C : le déférencement est effectué par (*env)->
  • 33. antislashn.org Android avancé - NDK 33 / 97 JNI - Implémentation de la méthode native ● Le second paramètre correspond à l'instance de la classe ou la classe elle-même ● méthode statique : paramètre de type jclass ● méthode d'instance : paramètre de type jobject ● Les paramètres supplémentaires correspondent aux paramètres de la méthode native Java ● deux types de paramètres – les types primitifs – les références
  • 34. antislashn.org Android avancé - NDK 34 / 97 JNI - Types primitifs ● Les types primitifs ont une correspondance directe avec les types C/C++ Java JNI C/C++ Taille boolean jboolean unsigned char unsigned 8 bits byte jbyte char signed 8 bits char jchar unsigned short unsigned 16 bits short jshort short signed 16 bits int jint int signed 32 bits long jlong long long signed 64 bits float jfloat float 32 bits double jdouble double 64 bits
  • 35. antislashn.org Android avancé - NDK 35 / 97 JNI - les références Types Java Types Natifs java.lang.Class jclass java.lang.Throwable jtrhowable java.lang.String jstring autres objets jobject java.lang.Object[] jobjectArray boolean[] jbooleanArray byte[] jbyteArray char[] jcharArray short[] jshortArray int[] jintArray long[] jlongArray float[] jfloatArray double jdoubleArray
  • 36. antislashn.org Android avancé - NDK 36 / 97 JNI - les références ● Les références sont passées à la méthodes natives ● elles ne peuvent pas être directement modifiées ● le garbage-collector utilise les références pour libérer la mémoire ● JNI propose trois types de références – référence local (local reference) – référence globale (global reference) – référence faible (weak reference)
  • 37. antislashn.org Android avancé - NDK 37 / 97 JNI - référence locale ● Les références locales sont libérées au retour de la fonction native ● la référence, pas l'objet qui est référencé – les références passées au fonctions natives sont locales – la plupart des références retournées par JNI sont locales ● une référence locale ne doit pas être sauvegardée d'un appel de méthode à l'autre – le code ci-dessous n'est donc pas valide static jobject myReference; JNIEXPORT void JNICALL Java_org_antislashn_jni_hello_Calcul_foo (JNIEnv *env, jobject thiz, jobject lRef){ myReference = lRef; }
  • 38. antislashn.org Android avancé - NDK 38 / 97 JNI - référence locale ● Les références locales peuvent être supprimées ● La spécification impose à la JVM de garder au moins 16 références en même temps ● la JVM peut refuser d'en créer d'autres ● il peut être nécessaire de préciser explicitement le nombre de références (*env)->DeleteLocalRef(myReference); (*env)->EnsureLocalCapacity(40);
  • 39. antislashn.org Android avancé - NDK 39 / 97 JNI - référence globale ● Une référence globale garde une référence sur un objet ● le garbage-collector tient compte de cette référence ● Une références globale peut être créée sur une référence locale ● Une référence globale peut-être supprimée jclass localClazz; jclass globalClazz; localClazz = (*env)->FindClass(env, "java/lang/String"); globalClazz = (*env)->NewGlobalRef(env,localClazz); (*env)->DeleteGlobalRef(env,globalClazz);
  • 40. antislashn.org Android avancé - NDK 40 / 97 JNI - référence faible ● Une référence faible peut-être utilisée d'une méthode native à une autre méthode native ● comme pour une référence globale ● Une référence faible ne permet pas de garantir que l'objet référencé ne supprimé par le GC ● à l'inverse d'une référence globale
  • 41. antislashn.org Android avancé - NDK 41 / 97 JNI - référence faible ● Création d'une référence faible ● Vérification de la validité ● Suppression jclass localClazz; jclass weakClazz; localClazz = (*env)->FindClass(env, "java/lang/String"); weakClazz = (*env)->NewWeakGlobalRef(env,localClazz); if((*env)->IsSameObject(env,weakClazz,NULL) == JNI_TRUE){ // le GC a supprimé l'objet, l'objet ne peut pas être utilisé } else{ // l'objet est toujours valide, il peut-être utilisé } (*env)->DeleteWeakGlobalRef(env,weakClazz);
  • 42. antislashn.org Android avancé - NDK 42 / 97 JNI ● Les pages suivantes présentent quelques opérations de base ● création d'objets, conversion vers C, destruction, … ● Toutes ces opérations sont accessibles via le pointeur vers JNIEnv ● voir la documentation – http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html
  • 43. antislashn.org Android avancé - NDK 43 / 97 JNI - opérations sur String ● Profonde différence entre les chaînes de caractères Java et C ● JNI support Unicode et UTF-8 – les méthodes diffèrent par l'ajout de "UTF" dans leur nom ● Création ● retourne NULL si la construction a échouée jstring javaString; javaString = (*env)->NewStringUTF(env,"hello, world");
  • 44. antislashn.org Android avancé - NDK 44 / 97 JNI - opérations sur String ● Conversion vers C ● isCopy indique si une copie a été effectuée – peut-être NULL ● Destruction d'une chaîne C retournée par une fonction JNI jstring javaString; const jbyte * str; jboolean isCopy; javaString = (*env)->NewStringUTF(env,"hello, world"); str = (*env)->GetStringUTFChars(env,javaString,$isCopy); (*env)->ReleaseStringUTFChars(env,javaString,str);
  • 45. antislashn.org Android avancé - NDK 45 / 97 JNI - opérations sur les tableaux ● Création ● Les différentes signatures sont du type NewXXXArray – où XXX est Int, Char, Byte,... – renvoie NULL si la création n'a pas été possible ● Conversion vers C jintArray ints; ints = (*env)->NewIntArray(env,10); jintArray javaArray; javaArray = (*env)->NewIntArray(env,10); jint nativeArray[10]; (*env)->GetIntArrayRegion(env, javaArray,0,10, nativeArray);
  • 46. antislashn.org Android avancé - NDK 46 / 97 JNI - opérations sur les tableaux ● Utilisation d'un pointeur ● fonctions GetXXXArrayElements ● le pointeur retourné doit être libérer – fonctions ReleaseXXXArrayElements jint* pJint = (*env)->GetIntArrayElements(env,javaArray); (*env)->ReleaseIntArrayElements(env,javaArray,pJint,0); release mode Release Mode Action 0 Recopie contenu et libère le tableau natif JNI_COMMIT Recopie le contenu mais ne libère pas le tableau natif Le tableau Java peut-être mis à jour JNI_ABORT Libère le tableau natif sans recopier son contenu
  • 47. antislashn.org Android avancé - NDK 47 / 97 JNI - NIO ● Fonctions JNI pour utiliser les buffers NIO ● un "direct buffer" est un tableau d'octets ● Création ● Récupération unsigned char* buffer = (unsigned char*) malloc(1024); jobject directBuffer = (*env)->NewDirectByteBuffer(env,buffer,1024); unsigned char * buf = (unsigned char*) (*env)->GetDirectBufferAddress(env,directBuffer);
  • 48. antislashn.org Android avancé - NDK 48 / 97 JNI - membres d'une classe Java ● Deux types de membre ● méthode ou propriété d'instance ● méthode ou propriété de classe - propriété statique ● L'accès aux membres d'une instance (ou d'une classe) passe par le type jclass jclass clazz = (*env)->GetObjectClass(env,instance);
  • 49. antislashn.org Android avancé - NDK 49 / 97 JNI - membres d'une classe Java ● Les extraits de code des pages suivantes utilisent la classe Memo public class Memo { private static int NB_MEMOS = 0; private int urgence = 0; private String titre; private String descriptif; public Memo() { NB_MEMOS++; } public Memo(String titre, String descriptif) { this.titre = titre; this.descriptif = descriptif; NB_MEMOS++; } // Liste des getteurs / setteurs ... }
  • 50. antislashn.org Android avancé - NDK 50 / 97 JNI - signature des types ● La manipulation des propriétés et des méthodes passe par l'utilisation des signatures de type de la JVM Type Java Signature boolean Z byte B char C short S int I long J float F double D classe ex: java.lang.String Ljava/lang/String; type[] [type méthode (arg-type) ret-type retour void V
  • 51. antislashn.org Android avancé - NDK 51 / 97 JNI - signature des types ● Exemple ● une méthode int foo(int n, String s, int[] ints); – est associée au descripteur (ILjava/lang/String;[I)J ● une méthode int bar(); – est associée au descripteur ()I ● une méthode void foo(String s); – est associée au descripteur (Ljava/lang/String;)V
  • 52. antislashn.org Android avancé - NDK 52 / 97 JNI - signature des types ● L'outil javap aide à trouver les signatures javap -classpath .debug -p -s org.antislashn.jni.hello.Memo ... public int getUrgence(); descriptor: ()I public void setUrgence(int); descriptor: (I)V public java.lang.String getTitre(); descriptor: ()Ljava/lang/String; public void setTitre(java.lang.String); descriptor: (Ljava/lang/String;)V ...
  • 53. antislashn.org Android avancé - NDK 53 / 97 JNI - propriétés d'une classe Java ● Accès aux propriétés ● d'abord récupérer le jfieldID de la propriété – méthodes de JNIEnv : GetFieldId ou GetStaticFieldId ● lire la valeur du champ – méthodes GetXxxField pour les propriétés d'instance – méthodes GetStaticXxxField pour les propriétés de classe – où Xxx est Int, Boolean, Short, Object, … ● mettre à jour la valeur du champ – méthodes SetXxxField pour les propriétés d'instance – méthodes SetStaticXxxField pour les propriétés de classe – où Xxx est Int, Boolean, Short, Object, …
  • 54. antislashn.org Android avancé - NDK 54 / 97 JNI - propriétés d'une classe Java ● Accès aux propriétés : extrait de code ... jclass clazz = (*env)->GetObjectClass(env,instance); jfieldID instanceFieldID = (*env)->GetFieldID(env,clazz,"titre","Ljava/lang/String;"); jfieldID staticFieldId = (*env)->GetStaticFieldID(env,clazz,"NB_MEMOS","I"); jstring titre = (*env)->GetObjectField(env,instance,instanceFieldID); jint nb = (*env)->GetStaticIntField(env,clazz,staticFieldId); (*env)->SetStaticIntField(env,clazz,staticFieldId,35); ... statique donc de type jclass instance de Memo reçue comme paramètre de la méthode nouvelle valeur pour la propriété statique de Memo type de la propriété
  • 55. antislashn.org Android avancé - NDK 55 / 97 JNI - méthodes d'une classe Java ● Comme pour les propriétés ● deux types de méthodes – statique – ou d'instance ● Mêmes principes que pour accéder aux propriétés ● récupération du l'identifiant de type jmethodID – méthodes de JNIEnv : GetMethodID, GetStaticMethodID ● puis appel de la méthode – méthodes CallStaticXxxMethod, CallXxxMethod,.. ● cf. la documentation pour l'ensemble des méthodes d'invocation
  • 56. antislashn.org Android avancé - NDK 56 / 97 JNI - méthodes d'une classe Java ● Invocation d'une méthode Java, extrait de code ... jmethodID setTitreID = (*env)->GetMethodID(env,clazz,"setTitre","(Ljava/lang/String;)V"); jstring newTitle = (*env)->NewStringUTF(env,"Nouveau titre"); (*env)->CallVoidMethod(env,instance,setTitreID,newTitle); jmethodID getTitreID = (*env)->GetMethodID(env,clazz,"getTitre","()Ljava/lang/String;"); jstring t = (*env)->CallObjectMethod(env,instance,getTitreID); ... paramètre de type jstring
  • 57. antislashn.org Android avancé - NDK 57 / 97 Multithreading ● Un thread Java peut lancer du code natif ● aisé à coder, le code Java interagit avec les instances des classes java.lang.Thread ● pas d'impact sur le code natif ● le code natif peut communiquer avec le code Java via JNIEnv
  • 58. antislashn.org Android avancé - NDK 58 / 97 Multithreading ● L'utilisation des threads Java doit prendre en considération les points suivants ● le code natif est-il thread-safe ? ● le code natif ne peut pas bénéficier de la programmation concurrente Java ● le code natif exécuté dans des threads Java différents – ne peuvent pas communiquer – ne peuvent pas partager des ressources
  • 59. antislashn.org Android avancé - NDK 59 / 97 Multithreading ● Exemple de code ● le code Java crée des threads ● le code natif est exécuté par le thread Java ... private void javaThreads(int threads, final int iterarions){ // Création d'un thread Java pour chaque worker natif for(int i=0 ; i<threads ; i++){ final int id = i; Thread thread = new Thread(){ @Override public void run() { nativeWorker(id,iterarions); } }; thread.start(); } } ...
  • 60. antislashn.org Android avancé - NDK 60 / 97 POSIX Thread ● POSIX : norme technique de l'IEEE ● IEEE : Institute of Electrical an Electronics Engineers ● POSIX : Portable Operating System Interface X ● POSIX Thread est aussi nommé Pthreads ● Utilisation de Pthread ● inclure la librairie pthread.h – l'implémentation fait partie de Bionic – pas de lien supplémentaire pour le linker ● Les pages suivantes présentent les principes de base de PThread ● voir le man pour une documentation complète
  • 61. antislashn.org Android avancé - NDK 61 / 97 POSIX Thread ● Création d'un thread : fonction pthread_create ● arguments – pthread_t* thread : pointeur mis à jour par la fonction pour retourner le nouveau thread – pthread_attr_t const* attr : attributs nécessaires à la création du thread (base de la pile, taille de la pile, etc...) – void* (*start_routine)(void*) : pointeur vers fonction de la routine devant être exécutée par le thread – void* arg : arguments passés à la fonction, peut être NULL ● retour – int : 0 si le thread est créé, ou code d'erreur
  • 62. antislashn.org Android avancé - NDK 62 / 97 POSIX Thread ● Les pthreads ne font pas partie de la plateforme Java ● ils doivent être attachés à la JVM pour interagir avec la partie Java ● une fois attaché le pthread doit invoquer une méthode callback pour interagir avec l'IHM – le pthread doit donc avoir une référence vers l'activité ● utilisation de références globales comme cache ● utilisation de la fonction JNI_OnLoad – fonction appelée par la JVM lorsque la librairie est chargée – l'appel de la fonction fournit comme premier paramètre un pointeur vers la JVM – le pthread est détaché lorsque la tâche est finie
  • 63. antislashn.org Android avancé - NDK 63 / 97 POSIX Thread ● Exemple de code ● la référence vers la JVM est mise en cache – les références globales devront être supprimées ... static jmethodID gOnNativeMessage = NULL; static JavaVM* gVm = NULL; static jobject gObj = NULL; jint JNI_OnLoad(JavaVM* vm, void* resserved){ gVm = vm; return JNI_VERSION_1_2; } ...
  • 64. antislashn.org Android avancé - NDK 64 / 97 POSIX Thread ● Le pthread doit être créé, puis attaché à la JVM ● création par pthread_create ● la routine exécutée par pthread devra – attacher le pthread à la JVM – exécuter la tâche – détacher le pthread à la JVM
  • 65. antislashn.org Android avancé - NDK 65 / 97 POSIX Thread ● Extraits de code ... pthread_t thread; // Create a new thread int result = pthread_create(&thread,NULL,nativeWorkerThread,static_cast<void*>(nativeWorkerArgs)); if (0 != result) { ... création du pthread fonction exécutée dans le pthread pointeur sur les paramètres passés à la fonction qui sera exécutée dans le pthread
  • 66. antislashn.org Android avancé - NDK 66 / 97 POSIX Thread ● Code de la fonction exécutée dans le pthread static void* nativeWorkerThread(void* args) { JNIEnv *env = NULL; // On attache le thread courant à la JVM // et on récupère un pointeur vers JNIEv if (gVm->AttachCurrentThread(&env, NULL) == 0) { NativeWorkerArgs* nArgs = static_cast<NativeWorkerArgs*>(args); // Excéution du worker natif dans le context du thread Java_org_antislashn_threads_MainActivity_nativeWorker(env, gObj, nArgs->id, nArgs->iterations); delete nArgs; // on détache le thread courant de la JVM gVm->DetachCurrentThread(); } return (void*)1; } tâche réellement exécutée dans le pthread la tâche est attachée avant son exécution puis détachée à la fin de son exécution
  • 67. antislashn.org Android avancé - NDK 67 / 97 POSIX Thread ● Contrairement aux threads Java, les threads POSIX peuvent renvoyer un résultat ● une fonction de type join est utilisée pour attendre la fin du Pthread et récupérer le résultat – int pthread_join(pthread_t thread, void** ret_val) ● cette fonction est bloquante jusqu'à la fin du pthread ● paramètres – pthread_t thread : thread retourné par pthread_create – void** ret_val : pointeur vers le résultat (de type void*) retourné par le tâche du pthread
  • 68. antislashn.org Android avancé - NDK 68 / 97 POSIX Thread ● Extrait de code ... pthread_t* handles = new pthread_t[nbThreads]; ... // Attente de la fin des tâches exécutées par les pthreads for(jint i=0 ; i< nbThreads ; i++){ void* result = NULL; int r=0; if((r=pthread_join(handles[i],&result)) != 0){ ... } else{ char message[50]; sprintf(message,"Worker %d returned %d", i, result); jstring messageString = env->NewStringUTF(message); env->CallVoidMethod(thizz, gOnNativeMessage, messageString); if (NULL != env->ExceptionOccurred()) { return; } } } ...
  • 69. antislashn.org Android avancé - NDK 69 / 97 POSIX Thread ● Synchronisation des pthreads par mutexes ● type pthread_mutex_t ● Fonctions de base ● initialisation d'un mutex – fonction pthread_mutex_init – macro PTHREAD_MUTEX_INITIALIZER ● blocage d'un mutex – fonction pthread_mutext_lock ● déblocage d'un mutex – fonction pthread_mutex_unlock
  • 70. antislashn.org Android avancé - NDK 70 / 97 POSIX Thread ● Initialisation d'un mutex ● il est nécessaire de créer un variable de type pthread_mutext_t – ici en variable statique ● puis appel de la fonction d'initialisation – le second paramètre étant NULL, création d'un mutex par défaut ... static pthread_mutex_t mutex; ... void Java_org_antislashn_threads_MainActivity_nativeInit(JNIEnv *env, jobject thizz) { if(pthread_mutex_init(&mutex,NULL)!=0){ jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); env->ThrowNew(exceptionClazz, "Unable to initialize mutex"); return; } ...
  • 71. antislashn.org Android avancé - NDK 71 / 97 POSIX Thread ● Le worker du pthread peut acquérir le mutex en début de tâche et le libérer lorsque la tâche est terminée ● la fonction pthread_mutext_lock est bloquante tant que le mutex n'est pas disponible ... void Java_org_antislashn_threads_MainActivity_nativeWorker(JNIEnv *env, jobject thizz, jint id, jint iterations) { if(pthread_mutex_lock(&mutex) !=0){ jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); env->ThrowNew(exceptionClazz, "Unable to lock mutex"); return; } ... if (pthread_mutex_unlock(&mutex) != 0) { jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); env->ThrowNew(exceptionClazz, "Unable to unlock mutex"); return; } } ...
  • 72. antislashn.org Android avancé - NDK 72 / 97 POSIX Thread ● Lorsque le mutex n'est plus utilisé il doit être détruit ● ici dans la fonction native, invoquée par onDestroy() de l'activité ... void Java_org_antislashn_threads_MainActivity_nativeFree(JNIEnv *env, jobject thizz) { ... if(pthread_mutex_destroy(&mutex) != 0){ jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); env->ThrowNew(exceptionClazz, "Unable to destroy mutex"); } } ...
  • 73. antislashn.org Android avancé - NDK 73 / 97 Fichier Android.mk ● Fichier de type makefile utilisé par la chaîne de build ● Permet de regrouper les sources en modules de type librairie statique ou dynamique ● le fichier Android.mk peut définir plusieurs modules ● seules les librairies dynamiques peuvent être incluent dans l'apk final ● Cf. la documentation de référence ● http://android.mk/
  • 74. antislashn.org Android avancé - NDK 74 / 97 Fichier Android.mk ● Fichier minimal type ● LOCAL_PATH directive de début de fichier – indique l'endroit où se trouve les sources – my-dir renvoie le répertoire courant (celui où est Android.mk) ● CLEAR-VARS nettoie les varaiables LOCAL_XXX – LOCAL_MODULE, LOCAL_SRC_FILE, … – sauf LOCAL_PATH LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c include $(BUILD_SHARED_LIBRARY)
  • 75. antislashn.org Android avancé - NDK 75 / 97 Fichier Android.mk ● LOCAL_MODULE définit le nom d'un module ● ce nom doit être unique, et ne doit pas contenir d'espace – si le module est nommé foo, la librairie générée sera libfoo.so ● LOCAL_SRC_FILES liste des fichiers C/C++ qui seront assemblés dans le module ● juste les fichier .c et .cpp – séparés par un espace ● si les extensions sont différentes utiliser la variable LOCAL_CPP_EXTENSION
  • 76. antislashn.org Android avancé - NDK 76 / 97 Fichier Android.mk ● include $(BUILD_SHARED_LIBRARY) ● permet la génération de la librairie dynamique ● BUID_STATIC_LIBRARY génère une librairie statique ● LOCAL_STATIC_LIBRARIES ajoute des librairies statiques au modules
  • 77. antislashn.org Android avancé - NDK 77 / 97 Fichier Android.mk ● Génération de plusieurs librairies dynamiques LOCAL_PATH := $(call my-dir) # # Module 1 # include $(CLEAR_VARS) LOCAL_MODULE := module1 LOCAL_SRC_FILES := module1.c include $(BUILD_SHARED_LIBRARY) # # Module 2 # include $(CLEAR_VARS) LOCAL_MODULE := module2 LOCAL_SRC_FILES := module2.c include $(BUILD_SHARED_LIBRARY)
  • 78. antislashn.org Android avancé - NDK 78 / 97 Fichier Android.mk ● Génération de librairies statiques LOCAL_PATH := $(call my-dir) # # 3rd party AVI library # include $(CLEAR_VARS) LOCAL_MODULE := avilib LOCAL_SRC_FILES := avilib.c platform_posix.c include $(BUILD_STATIC_LIBRARY) # # Native module # include $(CLEAR_VARS) LOCAL_MODULE := module LOCAL_SRC_FILES := module.c LOCAL_STATIC_LIBRARIES := avilib include $(BUILD_SHARED_LIBRARY)
  • 79. antislashn.org Android avancé - NDK 79 / 97 Fichier Android.mk ● Partager une librairie C/C++ entre plusieurs projets NDK ● les librairies à partager dont mises dans un répertoire spécifique – hors de tout projet NDK ● le nom du répertoire de la librairie correspond au nom du module – avec leurs propres fichier .mk ● ils seront invoqués lors de la construction du projet LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := calculs LOCAL_SRC_FILES := calculs.c include $(BUILD_SHARED_LIBRARY) contient
  • 80. antislashn.org Android avancé - NDK 80 / 97 Fichier Android.mk ● Partager une librairie C/C++ entre plusieurs projets NDK ● le projet NDK qui utilise la librairie partagée déclare celle- ci dans son fichier Android.mk ● il faut positionner la variable d'environnement NDK_MODULE_PATH avant d'invoquer ndk-build LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := module LOCAL_SRC_FILES := module.c LOCAL_SHARED_LIBRARIES := calculs include $(BUILD_SHARED_LIBRARY) $(call import-module,calculs)
  • 81. antislashn.org Android avancé - NDK 81 / 97 Android Studio - compilation automatique ● Par défaut Gradle construit les librairies .so si un répertoires jni est présent ● la compilation est effectuée à la construction de l'apk ● les fichiers .mk ne sont pas nécessaires – ils ne seront pas pris en compte ● les librairies sont construites dans le répertoire libs du projet – le nom par défaut de la librairie est app ● les fichiers générés pour les différentes cibles seront nommés : libapp.so –
  • 82. antislashn.org Android avancé - NDK 82 / 97 Android Studio - compilation automatique ● Il est aussi possible de paramétrer gradle pour compiler et générer les fichiers .so au moment de la création de l'apk ● dans le fichier build.gradle du module – dans la section defaultConfig ● il faut que le répertoire du NDK soit positionné dans le fichier local.properties ... ndk { moduleName "hello-jni" } ... ndk.dir=C:DEVELOPPEMENTSAndroidsdkndk-bundle sdk.dir=C:DEVELOPPEMENTSAndroidsdk
  • 83. antislashn.org Android avancé - NDK 83 / 97 Android Studio - compilation automatique ● Selon la version d'Android Studio il peut être nécessaire d'ajouter dans le fichier gradle.properties la ligne ● une erreur apparaît lors de la construction de l'apk ● L'ensemble des macros et variables du fichier make sont configurables par gradle android.useDeprecatedNdk=true ndk { moduleName "mymodule" ldLibs "log" stl "gnustl_static" cFlags "-std=c++11 -fexceptions" }
  • 84. antislashn.org Android avancé - NDK 84 / 97 ● Il faut désélectionner l'appel automatique de ndk build‑ par gradle ● dans le fichier build.gradle – annulation de la déclaration des répertoires JNI Android Studio - par ndk-build android { compileSdkVersion 23 buildToolsVersion "23.0.2" sourceSets{ main{ jniLibs.srcDirs "src/main/libs" jni.srcDirs = [] } } ...
  • 85. antislashn.org Android avancé - NDK 85 / 97 Android Studio - par ndk-build ● Compilation dans le terminal ● ndk-build utilise make, il est nécessaire d'ajouter dans le répertoire jni – un fichier Android.mk pour l'unité de compilation ● cf. http://developer.android.com/ndk/guides/android_mk.html – un fichier Application.mk pour les cibles ● cf. http://developer.android.com/ndk/guides/application_mk.html LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c include $(BUILD_SHARED_LIBRARY) Android.mk APP_ABI := all Application.mk
  • 86. antislashn.org Android avancé - NDK 86 / 97 Android Studio - par ndk-build ● Compilation dans le terminal ● dans le terminal – se positionner dans le répertoire jni – invoquer la commande ndk-build ● Les librairies des différentes cibles sont générées dans le répertoire main/libs
  • 87. antislashn.org Android avancé - NDK 87 / 97 Android Studio - par script gradle ● Il est aussi possible d'automatiser l'appel de ndk build‑ par un script gradle, dans le fichier build.gradle du module ● il faut éviter l'invocation automatique de ndk build‑ – dans android.sourceSets.main ● et ajouter en fin de fichier, en fait en dehors du bloc android{...} jni.srcDirs = [] task ndkBuild(type:Exec) { if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine 'ndk-build.cmd', '-C', file('src/main').absolutePath } else { commandLine 'ndk-build', '-C', file('src/main').absolutePath } } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild }
  • 88. antislashn.org Android avancé - NDK 88 / 97 SWIG ● SWIG est un outil permettant de connecter du code C/C++ avec d'autres langages ● ne fait pas partie d'Android ● n'est pas dédié à Java ● SWIG nécessite l'écriture d'une interface afin de produire le code Java ● Site officiel : http://www.swig.org/ ● installation sous windows, linux, Mac
  • 89. antislashn.org Android avancé - NDK 89 / 97 SWIG - exemple de base ● Comme introduction à Swig nous allons utiliser la fonction getuid ● cf. http://linux.die.net/man/2/getuid ● Etapes ● écrire l"interface SWIG ● généré le proxy Java ● ajouter les sources générées par SWIG dans Android.mk ● utiliser le proxy généré par SWIG
  • 90. antislashn.org Android avancé - NDK 90 / 97 SWIG - interface ● Ce fichier déclare ● les prototypes de fonctions ● les déclarations de classes ● les déclarations de variables ● Syntaxe similaire à un header C/C++ ● Le fichier interface s’appellera unix.i ● mis dans le répertoire jni
  • 91. antislashn.org Android avancé - NDK 91 / 97 SWIG - interface ● Interface Unix.i /* Module name is unix. */ %module unix %{ /* Include the POSIX operating system APIs. */ #include < unistd.h> %} /* Tell SWIG about uid_t. */ typedef unsigned int uid_t; /* Ask SWIG to wrap getuid function. */ extern uid_t getuid(void);
  • 92. antislashn.org Android avancé - NDK 92 / 97 SWIG - génération du proxy Java ● Auparavant il faut créer le package java de la classe proxy ● ici : org.antislashn.swig.proxy ● Puis lancer la commande swig ● Génération : ● un fichier Unix_wrap.c ● deux classes Java – Unix.java – UnixJNI.java swig -java -package org.antislashn.swig.proxy -outdir java/org/antislashn/swig/proxy jni/unix.i
  • 93. antislashn.org Android avancé - NDK 93 / 97 SWIG - utilisation ● Deux classes Java ont été générées ● L'utilisation est triviale public class Unix { public static long getuid() { return UnixJNI.getuid(); } } public class UnixJNI { public final static native long getuid(); } public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tv = (TextView) findViewById(R.id.uid); tv.setText(Long.toString(Unix.getuid())); } }
  • 94. antislashn.org Android avancé - NDK 94 / 97 Web ● http://developer.android.com/ndk/index.html ● http://developer.android.com/tools/building/configuring-gradle.html ● http://tools.android.com/tech-docs/new-build-system/user-guide ● http://tools.android.com/tech-docs/new-build-system/gradle-experimental ● http://android.mk/ ● http://mobilepearls.com/labs/native-android-api/ ● http://developer.android.com/ndk/guides/cpp-support.html ● http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html ● http://linux.die.net/man/7/pthreads
  • 95. antislashn.org Android avancé - NDK 95 / 97 Bibliographie ● Apress ● Pro Android C++ with th NDK ● Beginning Android C++ Game Developement ● Packt Publishing ● Android Native Development Kit Cookbook ● Android NDK ● Gradle for Android
  • 96. antislashn.org Titre support 96 / 97 copyleft Support de formation créé par Franck SIMON http://www.franck-simon.com
  • 97. antislashn.org Titre support 97 / 97 copyleft Cette œuvre est mise à disposition sous licence Attribution Pas d'Utilisation Commerciale Partage dans les Mêmes Conditions 3.0 France. Pour voir une copie de cette licence, visitez http://creativecommons.org/licenses/by-nc-sa/3.0/fr/ ou écrivez à Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.