Les bibliothèques natives Android disparaissent une fois l’application installée

Après avoir basculé sur Android Studio, j’ai commencé à voir le redouté

java.lang.UnsatisfiedLinkError: dlopen failed: library '/data/app-lib/com.myapp.test-1/libmylib.so' not found 

Erreur. Lorsque je décompresse l’apk, je peux voir libmylib.so ainsi que toutes les autres bibliothèques natives (libmyotherlib.so et libtest.so) dans le dossier lib / armeabi, l’emballage ne devrait donc pas être le problème … J’ai décidé de root mon périphérique de test et consultez le contenu réel du dossier de mon application sous / data / app-lib, où ses bibliothèques natives doivent se trouver après l’installation. J’ai constaté qu’une des bibliothèques natives de mon application (libmylib.so) était manquante après l’application. est installé sur un périphérique. libmylib.so et libmyotherlib.so sont des fichiers .so prédéfinis, placés dans src / main / jniLibs, et libtest.so est compilé à partir de test.c dans src / main / jni.

Cela n’a commencé qu’après que je suis passé à Android Studio; J’ai vérifié que les apks construits à partir du même code dans Eclipse ADT avaient toutes les bibliothèques requirejses présentes sous /data/app-lib/com.myapp.test-1 après l’installation.

Build.gradle pertinent pour Android Studio:

 apply plugin: 'com.android.application' android { comstackSdkVersion 23 buildToolsVersion "21.1.2" defaultConfig { applicationId "com.myapp.test" minSdkVersion 17 targetSdkVersion 23 versionCode 1 versionName "1.0" ndk{ moduleName "test"//testing ndk integration } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } repositories { // You can also use jcenter if you prefer mavenCentral() } dependencies { comstack fileTree(dir: 'libs', include: ['*.jar']) testComstack 'junit:junit:4.12' //android support libs etc. comstack 'com.android.support:appcompat-v7:23.1.0' comstack 'com.android.support:support-v13:23.1.0' } 

Fichier gradle.properties pertinent

 android.useDeprecatedNdk=true 

Sous src / main / jni je n’ai que test.c

 #include  int main(){ return 0; } 

et sous src / main / jniLibs / armeabi j’ai

 libmylib.so libmyotherlib.so 

Android.mk pertinent pour Eclipse ADT build:

 include $(CLEAR_VARS) LOCAL_MODULE := test LOCAL_SRC_FILES += test.c include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := myotherlib LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libmyotherlib.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := mylib LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libmylib.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include include $(PREBUILT_SHARED_LIBRARY) 

Contenu pertinent / data / app-lib après l’installation de l’application créée par Android Studio:

 root@SOLONE SL-K40:/ # ls /data/app-lib/com.myapp.test-1 libmyotherlib.so libtest.so 

Contenu pertinent / data / app-lib après l’installation de l’application créée par Eclipse ADT:

 root@SOLONE SL-K40:/ # ls /data/app-lib/com.myapp.test-1 libmylib.so libmyotherlib.so libtest.so 

J’ai découvert accidentellement qu’en ajoutant

 sourceSets { main { jni.srcDirs = [] } } 

À mon build.gradle, je peux faire en sorte que libmylib.so apparaisse à nouveau après l’installation, mais cela empêche d’avoir du code source NDK dans mon projet.

Première question: Une idée de ce qui pourrait se passer ici? Se pourrait-il que mylib ait été compilé pour un abi autre qu’armeabi et qu’Android le rejette car son abi ne correspond pas au dossier dans lequel il est entré dans l’apk (je n’ai pas le code source de mylib)? Mon problème semble similaire à celui traité ici , mais cette personne semblait ne voir qu’une bibliothèque partagée dans l’application finale installée. Je vois toutes mes bibliothèques partagées sauf une.

Deuxième question: Quelle est la méthode correcte actuelle pour inclure des fichiers .so déjà générés dans une version d’Android Studio? Les indices autour du réseau semblent varier énormément selon la version d’Android Studio (j’utilise Android Studio 1.5, Gradle version 2.4, plug-in Android version 1.3.0) Est-il toujours nécessaire de redirect la variable jniLibs.srcDir vers src / main / les libs?

Oui, la meilleure approche consiste à définir jniLibs.srcDir de manière à ce que toutes les bibliothèques prédéfinies puissent être copiées à partir de cet emplacement .

Oui, l’ABI est la source la plus probable du problème. Si la bibliothèque préconfigurée a été construite pour armeabi mais que le périphérique (comme la grande majorité des périphériques actuels) prend en charge armeabi-v7a , le programme d’installation copiera avec plaisir les versions … v7a de vos bibliothèques non préconstruites dans / data / app-lib / com. .myapp.test-1 , et le chargeur se plaindra plus tard que libmylib.so est manquant.

Vous devez indiquer à Android Studio de ne créer qu’un seul ABI. Si vous n’avez pas fait quelque chose de spécial dans Eclipse, c’est probablement armeabi .

La façon d’instruire AS dépend de la version du plugin Gradle.

Pour le plugin ‘com.android.tools.build:gradle:1.5.0’ , j’utilise quelque chose comme

 android { defaultConfig.ndk { … abiFilter 'armeabi' } splits { abi { enable true reset() include 'armeabi' } } } 

Pour … gradle-experimental: 0.2.0 , j’utilise

 model { android.ndk { … abiFilters += 'armeabi' } } 

Je n’avais pas besoin d’activer les scissions sur le plug-in expérimental , je ne vous induirai donc pas en erreur sur les modifications de syntaxe.