Reputation: 1719
After switching to Android Studio, I began seeing the dreaded
java.lang.UnsatisfiedLinkError: dlopen failed: library
'/data/app-lib/com.myapp.test-1/libmylib.so' not found
error. When I unpack the apk, I can see libmylib.so along with all the other native libraries (libmyotherlib.so and libtest.so) under the lib/armeabi folder, so packaging shouldn't be the problem... I decided to root my test device and check out the actual contents of my app's folder under /data/app-lib, where its native libraries should be after install -- I found that one of my app's native libraries (libmylib.so) was missing after the app is installed on a device. libmylib.so and libmyotherlib.so are pre-built .so files placed in src/main/jniLibs, and libtest.so is compiled from test.c in src/main/jni.
This only started after I switched to Android Studio; I've verified that apks built from the same code in Eclipse ADT have all the required libraries present under /data/app-lib/com.myapp.test-1 after installation.
Relevant build.gradle for Android Studio build:
apply plugin: 'com.android.application'
android {
compileSdkVersion 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 {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
//android support libs etc.
compile 'com.android.support:appcompat-v7:23.1.0'
compile 'com.android.support:support-v13:23.1.0'
}
Relevant gradle.properties file
android.useDeprecatedNdk=true
Under src/main/jni I have only test.c
#include <jni.h>
int main(){
return 0;
}
and under src/main/jniLibs/armeabi I have
libmylib.so
libmyotherlib.so
Relevant Android.mk for 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)
Relevant /data/app-lib contents after installing app built by Android Studio:
root@SOLONE SL-K40:/ # ls /data/app-lib/com.myapp.test-1
libmyotherlib.so
libtest.so
Relevant /data/app-lib contents after installing app built by Eclipse ADT:
root@SOLONE SL-K40:/ # ls /data/app-lib/com.myapp.test-1
libmylib.so
libmyotherlib.so
libtest.so
I accidentally found that by adding
sourceSets {
main {
jni.srcDirs = []
}
}
to my build.gradle I can get libmylib.so to show up again after installation, but this precludes having any NDK source code in my project.
First Question: Any idea what might be going on here? Could it be that mylib was actually compiled for an abi other than armeabi and Android is discarding it because its actual abi doesn't match the folder it came in inside the apk (I don't have the source code for mylib)? My problem sounds similar to one discussed here, but that person seemed to see only one shared library in the final installed app; I'm seeing all but one of my shared libraries.
Second Question: What is the current correct way to include pre-built .so files in an Android Studio build? Clues around the 'net seem to vary wildly by Android Studio version (I'm using Android Studio 1.5, Gradle version 2.4, Android plugin version 1.3.0) Is there still a need to redirect the jniLibs.srcDir variable to src/main/libs?
Upvotes: 1
Views: 3180
Reputation: 57163
Yes, the best approach is to define jniLibs.srcDir such that all prebuilt libraries can be copied from there.
Yes, the ABI is the most probable source of the problem. If the prebuilt library was built for armeabi but the device (as the vast majority of devices today) supports armeabi-v7a, then the installer will happily copy the …v7a versions of your not-prebuilt libraries to /data/app-lib/com.myapp.test-1, and the loader will later complain that libmylib.so is missing.
You should instruct Android Studio to only build one ABI. If you did not do something special in Eclipse build, then this is most likely armeabi.
The way to instruct AS depends on the version of gradle plugin.
For 'com.android.tools.build:gradle:1.5.0' plugin, I use something like
android {
defaultConfig.ndk {
…
abiFilter 'armeabi'
}
splits {
abi {
enable true
reset()
include 'armeabi'
}
}
}
For …gradle-experimental:0.2.0, I use
model {
android.ndk {
…
abiFilters += 'armeabi'
}
}
I didn't have a need to enable splits on the experimental plugin, so I will not mislead you about the syntax changes there.
Upvotes: 2