Bibliothèque native Android faisant le lien avec une autre bibliothèque native de aar

J’ai une question curieuse. J’ai une bibliothèque aar, qui contient et utilise la bibliothèque native .so. Maintenant, je veux écrire une autre bibliothèque, qui dépend de cette bibliothèque et possède également une partie native dépendant de la bibliothèque native de la première bibliothèque. La bibliothèque dépendante utilise à la fois le code natif et les wrappers Java de la première bibliothèque.

Je me demande, est-il possible, comment faire cela par dépendance de gradle standard (avec les fichiers d’en-tête copiés à partir de la première bibliothèque)? Ou dois-je construire la deuxième bibliothèque directement à partir des sources?

Pourquoi j’ai besoin de ça: Nous avons une bibliothèque multiplateforme avec des fonctionnalités de base, pour Android comme ailleurs. Cette lib peut être utilisée dans une application Android standard et nous l’utilisons dans plusieurs projets, qui n’ont pas d’autre code natif.

Mais dans une application, nous souhaitons écrire du code pour une application partagée multiplateforme, en fonction de cette bibliothèque et je souhaite que ces bibliothèques soient séparées.

Merci!

Voici un exemple pratique basique sur OpenCV , vous pouvez faire de même pour votre first lib .

Préparer la première lib comme suit

OpenCV4Android/opencv/build.gradle le fichier jar , *.so et les en- headers exportés (voir le fichier OpenCV4Android/opencv/build.gradle dans le projet lié pour savoir comment append les en-têtes à aar).

Vous obtenez d’ first.aar par exemple de la construction de la first lib .

Utiliser la première lib dans vos autres projets

Ajoutez le first.aar dans vos autres projets lorsque vous en avez besoin.

 allprojects { repositories { jcenter() flatDir { dirs '/path/to/aar' } } } // in your app's build.gradle dependencies { // ... comstack 'com.example:example-with-header@aar' // ... } 

Liez votre bibliothèque native au first.aar partir de votre système de construction natif.

Si vous utilisez CMake , il devrait ressembler à ceci

 add_library(first SHARED IMPORTED) set_target_properties( first PROPERTIES IMPORTED_LOCATION ../../../../build/intermediates/exploded-aar/org.example/example-debug/jni/${ANDROID_ABI}/libfirst.so # use find command to figure out the location of the first lib before use it, not sure if it's different in different build environment # for android studio gradle plugin latest version use # ../../../../build/intermediates/transforms/mergeJniLibs/debug/folders/2000/1f/main/lib/${ANDROID_ABI}/libfirst.so ) # also use find command to figure the actual location of the exported header from aar # this might be different in your environment for different version of gradle plugin include_directories(build/intermediates/exploded-aar/com.example/example-debug/cpp/include) target_link_libraries( # Specifies the target library. native-lib # Links the target library to the log library # included in the NDK. first ${log-lib} ) 

Comme vous avez mentionné Gradle, je suppose que vous utilisez le dernier Android Studio. J’utilise 1.2.2 et j’ai trouvé facile de construire les projets NDK simples à partir des nombreux didacticiels flottants, mais frustrant, de construire un projet NDK de toute complexité. Je vais résumer ce que j’ai trouvé, mais je suggère fortement de lire ce blog et ce StackOverflow .

Mon projet est similaire au vôtre mais pas exactement. Le truc pour moi était de trouver comment utiliser Android Studio avec mon Android.mk, puis de trouver les variables de makefile appropriées. Espérons que cela aidera.

Android Studio stock ignorera complètement tout fichier Android.mk personnalisé que vous créez et générera plutôt le sien. Pour corriger cela, vous devez d’abord pirater le script build.gradle de votre projet, situé dans project/app/build.gradle . Vous pouvez probablement pirater le build.gradle de niveau supérieur, si vous le souhaitez.

Ceci est mon build.gradle piraté. Je construis sur une machine Windows, donc je ne l’ai piraté que pour Windows. Décommentez les lignes si vous utilisez OSX ou Linux.

project / app / build.gradle:

 //import org.apache.tools.ant.taskdefs.condition.Os apply plugin: 'com.android.application' android { comstackSdkVersion 22 buildToolsVersion "22.0.1" defaultConfig { applicationId "com.sample.app" minSdkVersion 15 targetSdkVersion 22 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } //ENABLE CUSTOM ANDROID.MK >> sourceSets.main.jni.srcDirs= [] //Disable automatic ndk-build. sourceSets.main.jniLibs.srcDir 'src/main/libs' //Call regular ndk-build script from app directory task ndkBuild(type: Exec) { workingDir file('src/main') commandLine getNdkBuildCmd() } tasks.withType(JavaComstack) { comstackTask -> comstackTask.dependsOn ndkBuild } task cleanNative(type: Exec) { workingDir file('src/main') commandLine getNdkBuildCmd(), 'clean' } clean.dependsOn cleanNative } //ENABLE CUSTOM ANDROID.MK << dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.2.0' compile 'com.google.android.gms:play-services:7.5.0' } //ENABLE CUSTOM ANDROID.MK >> def getNdkDir() { if (System.env.ANDROID_NDK_ROOT != null) return System.env.ANDROID_NDK_ROOT Properties properties = new Properties() properties.load(project.rootProject.file('local.properties').newDataInputStream()) def ndkdir = properties.getProperty('ndk.dir', null) if (ndkdir == null) throw new GradleException("NDK location not found. Define location with ndk.dir in the local.properties file") return (ndkdir) } def getNdkBuildCmd() { def ndkbuild = getNdkDir() + "/ndk-build.cmd" // def ndkbuild = getNdkDir() + "/ndk-build" // if (Os.isFamily(Os.FAMILY_WINDOWS)) // ndkbuild += ".cmd" return ndkbuild } //ENABLE CUSTOM ANDROID.MK << 

Maintenant, je peux créer mon multi-bibliothèque Android.mk. Cela crée deux bibliothèques de liens statiques, puis les bibliothèques et liens finaux des liens dynamics dans les deux premiers. Les répertoires impliqués sont:

Répertoires:

 project/ app/ build.gradle src/ main/ java/ jni/ Android.mk include/ libmp3lame/ MiniMp3/ mp3_jni.c mpglib/ 

Android.mk:

 TOP_PATH := $(call my-dir) LOCAL_PATH := $(TOP_PATH)/libmp3lame include $(CLEAR_VARS) LOCAL_C_INCLUDES := $(TOP_PATH)/include LOCAL_CFLAGS := -DSTDC_HEADERS LOCAL_MODULE := libmp3lame LOCAL_SRC_FILES := \ bitstream.c \ ... version.c include $(BUILD_STATIC_LIBRARY) MY_LOCAL_STATIC_LIBRARIES += libmp3lame LOCAL_PATH := $(TOP_PATH)/mpglib include $(CLEAR_VARS) LOCAL_C_INCLUDES := $(TOP_PATH)/include LOCAL_C_INCLUDES += $(TOP_PATH)/libmp3lame LOCAL_CFLAGS := -DSTDC_HEADERS LOCAL_MODULE := mpglib LOCAL_SRC_FILES := \ common.c \ ... tabinit.c include $(BUILD_STATIC_LIBRARY) MY_LOCAL_STATIC_LIBRARIES += mpglib LOCAL_PATH := $(TOP_PATH) include $(CLEAR_VARS) LOCAL_C_INCLUDES := $(TOP_PATH)/include LOCAL_CFLAGS := -DSTDC_HEADERS LOCAL_MODULE := Mp3 LOCAL_STATIC_LIBRARIES := $(MY_LOCAL_STATIC_LIBRARIES) LOCAL_LDLIBS := -llog LOCAL_SRC_FILES := \ ./mp3_jni.c include $(BUILD_SHARED_LIBRARY) 

Vous devrez modifier le fichier Android.mk.