UnsatisfiedLinkError on Android

So, with minifyEnabled true in android app, I am getting the following error message.

Caused by: java.lang.UnsatisfiedLinkError: JNI_ERR returned from JNI_OnLoad in "/data/app/~~nD5rJ8fF4oh5UytfJVSksw==/<app.package.identifier>-J1uVTDlERLlIofq73xu0IA==/lib/arm64/libLiteCoreJNI.so"
	at java.lang.Runtime.loadLibrary0(Runtime.java:1077)
	at java.lang.Runtime.loadLibrary0(Runtime.java:998)
	at java.lang.System.loadLibrary(System.java:1661)
	at com.couchbase.lite.internal.CouchbaseLiteInternal.init(CouchbaseLiteInternal.java:93)
	at com.couchbase.lite.CouchbaseLite.init(CouchbaseLite.java:62)
	at com.couchbase.lite.CouchbaseLite.init(CouchbaseLite.java:46)
	at com.couchbase.lite.CouchbaseLite.init(CouchbaseLite.java:37)

From the above error, it looks like couchbase lite is looking for arm64 folder (instead of arm64-v8a). Could that be a problem? is there a way to tell couchbase to use arm64-v8a instead of arm64?

The test device is Pixel 3a running Android 32. The screenshot of the lib folder in the generated apk file is below.

We utilize third-party libraries that include native components, and we have successfully loaded them despite enabling minification. I have followed the steps outlined here to enable minification. However, it seems that none of these rules are directly related to the issue at hand.

Hmmm… this is confusing. It seems that you are running the JVM code on an Android system?

Is there a directory named:

/data/app/~~nD5rJ8fF4oh5UytfJVSksw==/<app.package.identifier>-J1uVTDlERLlIofq73xu0IA==/lib/arm64

on the device running your app? Does it contains the files libLiteCoreJNI.so and libLiteCore.so?

Is there a directory named:

/data/app/~~nD5rJ8fF4oh5UytfJVSksw==/<app.package.identifier>-> J1uVTDlERLlIofq73xu0IA==/lib/arm64

on the device running your app? Does it contains the files libLiteCoreJNI.so and libLiteCore.so?

It appears that the apk file contains the mentioned files in the lib folder, and these directory names might be generated by Proguard during the build process.

When Proguard is disabled, the app runs without any issues. However, the statement “It seems that you are running the JVM code on an Android system” is puzzling to me.

Yes, the apk file contains the named files. The android version of the code will load those libraries correctly.

For some reason, however, you seem to be using the JVM (not Android) version of the code. It must load the libraries from the file system. Unless those files are in the directory I named, of course, they will not be loaded.

I am using the couchbase lite android ktx 3.1.0 version. I double checked it.

Is there a sample app with proguard enabled where it is working?

We use Fresco too and it loads its native libraries fine. This issue seems to be a problem only with Couchbase Lite. If I copy the Android version of the libraries in a lib folder, would it be of any help?

I am 100% sure the dependencies I have in my Android project is couchbase lite android ktx 3.1.0 version.

Can you create a small demonstration case? I have never seen that error message before… but it seems at least possible that the file path is the path to the apk file (as it should be)

Directory names are most certainly not being generated by Proguard.

FWIW, the code that loads that library looks like this:

    private static final String LITECORE_JNI_LIBRARY = "LiteCoreJNI";

    public static void init(...) {
        ...
        System.loadLibrary(LITECORE_JNI_LIBRARY);

I’m mystified as to how Proguard would affect it.

Wait… the error message says that the system is failing to load:

…/lib/arm64/libLiteCoreJNI.so"

Indeed, as you can see in your screenshot, there is no such folder. Your pixel is not identifying itself as any of our supported architectures.

That’s exactly my thought too. “arm64” folder isn’t available at all. So if pixel is falling to identify itself with a supported architecture, How does Fresco work?

I’ll try to create a sample app. In our setup, we have a library where couchbase lite is used and an app which uses the aar to compile an apk.

So, I retested this again by doing an invalidation and restart to make sure this isn’t a heisenbug. It isn’t.

Here is the setup I will be trying to create. (Note to self because I am unsure when I can get to this)

  1. An android library project which use couchbase lite android 3.1.0 ktx version with the following android defaultConfig
        compileSdk 33
        // CBLite 2.6 & above needs a minSdk of 22
        minSdk 22
        targetSdk 33
  1. An app project that depends on the library project with same default config
  2. IMPORTANT: Enable minification using the below configuration
    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
       }
    }

Build a release apk and test it on Pixel 3a.

Note: if minifyEnabled is false, it just works.

Yeah… I, of course, have no idea how Fresco works.

Before I go trying to support this odd architecture, is there any way you can find the path to the library it is trying to load, when it succeeds (no minification)?

I can supply you with a version of the lib that will print that out, if it will help.

Yes. Please send it across. I don’t know how to find the path.

Will do. May not get to it today, but will have it for you ASAP. Do you have somewhere I can put it? No biggie if not… I can find something. If you have a convenient location, though…

I can DM you my email address if that works.

When you share it, please also share the steps I need to follow to include them. ATM, all these native library stuff is being handled by the cblite android dependency.

NVM. I found it. This is my bad. I’ll get you a new proguard file shortly.

ADDED: Try this. Let me know how it goes.

-dontwarn edu.umd.cs.findbugs.annotations.SuppressFBWarnings

-keep class com.couchbase.lite.ConnectionStatus { <init>(...); }
-keep class com.couchbase.lite.LiteCoreException { static <methods>; }
-keep class com.couchbase.lite.internal.replicator.CBLTrustManager {
    public java.util.List checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String, java.lang.String);
}
-keep class com.couchbase.lite.internal.fleece.FLSliceResult {
    <fields>; 
    <init>(...);
}
-keep class com.couchbase.lite.internal.ReplicationCollection {
    static <methods>;
    <fields>;
}
-keep class com.couchbase.lite.internal.core.C4* {
    static <methods>;
    <fields>;
    <init>(...);
 }

Are you saying that you found the root cause of the issue?

Below is the error I am getting now. Looks like it is different from before.

Caused by: java.lang.UnsatisfiedLinkError: JNI_ERR returned from JNI_OnLoad in "/data/app/~~Ci1bDZcP8-uIg75HjS5vZg==/<app-id>-woZW3ZTB9cbxADWijOTHYg==/lib/arm64/libLiteCoreJNI.so"
	at java.lang.Runtime.loadLibrary0(Runtime.java:1077)
	at java.lang.Runtime.loadLibrary0(Runtime.java:998)
	at java.lang.System.loadLibrary(System.java:1661)
	at com.couchbase.lite.internal.h.f(SourceFile:43)
	at j6.t.c(Unknown Source:0)
	at j6.t.b(Unknown Source:15)
	at j6.t.a(Unknown Source:1)
	at za.c.<init>(SourceFile:8)
	at za.c.<init>(SourceFile:1)

Ok. I thought I had it. I need to do some testing. Back to you soon.

Is there any chance of getting the logcat log during the failure?

Also would like to see the contents of proguard-android.txt

Also would like to see the contents of proguard-android.txt

https://gist.github.com/pramodshri-tgsys/f3d910c1df01f3b012698e7d30fd7bca

There has been a lot of misdirection in this issue… not the least of it my fault.

Still, I wonder why, in your OP, com.couchbase.lite.CouchbaseLite was not optimized as it is being optimize in your most recent stack trace.

How did you add my new rules? I don’t see them in your proguard-android.txt