0. Problem
I've create an Android library (aar) which contains some so files.
After successfully loaded the aar file in my Android application project, I try to load the so files (from the aar classes) but failed with a java.lang.UnsatisfiedLinkError
.
I think the Android application is not looking inside the aar in order to load the so files, but looking at the lib folder which is inside the Android application.
(I know I can copy those shared-libraries directly in the android application, but I don't want to do that)
1. Create the Android library (aar)
build.gradle
apply plugin: 'com.android.library'
android {
compileSdkVersion 29
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
}
}
packagingOptions {
pickFirst 'lib/x86_64/libnanolcms.so'
pickFirst 'lib/x86/libnanolcms.so'
pickFirst 'lib/armeabi-v7a/libnanolcms.so'
pickFirst 'lib/arm64-v8a/libnanolcms.so'
pickFirst 'lib/x86_64/liblcms2.so'
pickFirst 'lib/x86/liblcms2.so'
pickFirst 'lib/armeabi-v7a/liblcms2.so'
pickFirst 'lib/arm64-v8a/liblcms2.so'
}
}
buildTypes {
release {
minifyEnabled false
debuggable false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
jniDebuggable = true
}
debug {
minifyEnabled false
debuggable false
jniDebuggable = true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
version '3.6.0'
path "src/main/jni/CMakeLists.txt"
}
}
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jnilibs']
jni.srcDirs = [] //disable automatic ndk-build call
}
}
}
repositories {
flatDir {
dirs 'libs'
}
// to be able to compile opencv
maven { url "https://jitpack.io" }
}
dependencies {
implementation fileTree(include: ['*.jar','*.so'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.1.0'
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation(name: 'openCV-3.3.1', ext: 'aar')
implementation "com.getkeepsafe.relinker:relinker:1.4.0"
}
code from the android library project
if (useReLinker) {
ReLinker.recursively().log(logcatLogger).loadLibrary(CXColorcatchManager.getInstance().getWeakContext().get(), libraryName, new ReLinker.LoadListener() {
@Override
public void success() {
CXLogger.verbose("Library " + libraryName + " successfully loaded");
libraryLoaderListener.onLibraryLoaded(true);
}
@Override
public void failure(Throwable t) {
CXLogger.verbose("Unable to load " + libraryName + " library \n");
libraryLoaderListener.onLibraryLoaded(false);
}
});
} else {
try {
System.loadLibrary(libraryName);
libraryLoaderListener.onLibraryLoaded(true);
} catch (Exception e) {
CXLogger.verbose("Unable to load " + libraryName + " library \n " + e);
libraryLoaderListener.onLibraryLoaded(false);
}
}
}
As you can see on the following picture, the aar file contains the so files. They are in the jni folder which is the correct folder following the documentation
my-library.aar
2. Android application project
I created an Android application project, added the aar file as a dependency (it works fine).
I call the Singleton class I created from the aar file, then I try to load the so file from library class using System.loadlibrary()
or Relinker.
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
defaultConfig {
applicationId "com.colorix.spike.nano"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jnilibs']
}
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test:runner:1.3.0-alpha03'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha03'
// my library
implementation files('libs/my_library.aar')
implementation "com.getkeepsafe.relinker:relinker:1.4.0"
}
Unfortunately, with System.loadlibrary()
it doesn't find the library : java.lang.UnsatisfiedLinkError
Using Relinker, I use recursive() method in order to check every folder :
V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Loading the library normally failed: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk"],nativeLibraryDirectories=[/data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/lib/x86, /system/lib]]] couldn't find "libnanolcms.so"
at java.lang.Runtime.loadLibrary0(Runtime.java:1012)
at java.lang.System.loadLibrary(System.java:1669)
at com.getkeepsafe.relinker.SystemLibraryLoader.loadLibrary(SystemLibraryLoader.java:24)
at com.getkeepsafe.relinker.ReLinkerInstance.loadLibraryInternal(ReLinkerInstance.java:163)
at com.getkeepsafe.relinker.ReLinkerInstance.access$000(ReLinkerInstance.java:31)
at com.getkeepsafe.relinker.ReLinkerInstance$1.run(ReLinkerInstance.java:142)
at java.lang.Thread.run(Thread.java:764)
V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: nanolcms (null) was not loaded normally, re-linking...
V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/x86/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/armeabi-v7a/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
[LibraryLoadingTask.log()-32]: Looking for lib/armeabi/libnanolcms.so in APK /data/app /com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
[LibraryLoadingTask.log()-32]: Looking for lib/x86/libnanolcms.so in APK /data/app /com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
[LibraryLoadingTask.log()-32]: Looking for lib/armeabi-v7a/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/armeabi/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
[LibraryLoadingTask.log()-32]: Looking for lib/x86/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
[LibraryLoadingTask.log()-32]: Looking for lib/armeabi-v7a/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/armeabi/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/x86/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
[LibraryLoadingTask.log()-32]: Looking for lib/armeabi-v7a/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
[LibraryLoadingTask.log()-32]: Looking for lib/armeabi/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/x86/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/armeabi-v7a/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
V/ReLinkerInstance: [LibraryLoadingTask.log()-32]: Looking for lib/armeabi/libnanolcms.so in APK /data/app/com.colorix.spike.nano-YmXglPRjs_msSVzvsySnZA==/base.apk...
W/orix.spike.nan: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (light greylist, reflection)
W/orix.spike.nan: Accessing hidden method Landroid/view /ViewGroup;->makeOptionalFitsSystemWindows()V (light greylist, reflection)
V/ReLinkerInstance: [LibraryLoadingTask.failure()-54]: Unable to load nanolcms library
As you can see, the library is not in lib/<architecture/...
but inside the aar, which is in jni folder.
If I understand the android documentation, lib folder is the folder of the android application and not the folder of the android library (aar).
If someone knows how to load the so file which are inside the aar file without, please let me know. If you need more information, let me know.
Solution (but I don't want that)
I can copy the .so files in the jniLibs folder of the application. It will works properly. But that's no what I want.