sqlite-jdbc icon indicating copy to clipboard operation
sqlite-jdbc copied to clipboard

library "libsqlitejdbc.so" not found on Android

Open jrjohn opened this issue 3 years ago • 12 comments

Describe the bug Run on the android platform will issue this bug

To Reproduce Connect SQLite DB with sqlite-jdbc from the Android platform.

Logs 2022-10-12 11:27:01.122 16877-16877/com.demo.sqlite E/AndroidRuntime: FATAL EXCEPTION: main Process: com.demo.sqlite, PID: 16877 java.lang.UnsatisfiedLinkError: dlopen failed: library "libsqlitejdbc.so" not found at java.lang.Runtime.loadLibrary0(Runtime.java:1077) at java.lang.Runtime.loadLibrary0(Runtime.java:998) at java.lang.System.loadLibrary(System.java:1656) at org.sqlite.core.NativeDB.(NativeDB.java:40) at org.sqlite.core.NativeDB.load(NativeDB.java:60) at org.sqlite.SQLiteConnection.open(SQLiteConnection.java:281) at org.sqlite.SQLiteConnection.(SQLiteConnection.java:68) at org.sqlite.jdbc3.JDBC3Connection.(JDBC3Connection.java:28) at org.sqlite.jdbc4.JDBC4Connection.(JDBC4Connection.java:19) at org.sqlite.JDBC.createConnection(JDBC.java:104) at org.sqlite.SQLiteConfig.createConnection(SQLiteConfig.java:108)

Environment (please complete the following information): OS: [Android 12] CPU architecture: [aarch64] sqlite-jdbc version [3.39.3.0]

Additional context About Android ABI description: https://developer.android.com/ndk/guides/abis

image

The android native library directory name needs to be corrected. /org/sqlite/native/Linux-Android aarch64 -> arm64-v8a arm -> armeabi-v7a x86 x86_64

I have tested it, It's working now on Android.

jrjohn avatar Oct 17 '22 02:10 jrjohn

The android native library directory name needs to be corrected. /org/sqlite/native/Linux-Android aarch64 -> arm64-v8a arm -> armeabi-v7a x86 x86_64

I have tested it, It's working now on Android.

Can you clarify, i don't understand

gotson avatar Oct 17 '22 02:10 gotson

About android native library https://developer.android.com/studio/projects/add-native-code image need rename directory aarch64 to arm64-v8a and rename directory arm to armeabi-v7a

Then android loads the native library from arm64-v8a if the android MCU is aarch64 type. The android system will not load the native library from aarch64 directory.

The source from sqlite-jdbc GitHub android native directory as follow: jrjohn@Chiende-MacBook-Pro-3 Linux-Android % pwd /Users/jrjohn/Downloads/org/sqlite/native/Linux-Android jrjohn@Chiende-MacBook-Pro-3 Linux-Android % ls aarch64 arm x86 x86_64 jrjohn@Chiende-MacBook-Pro-3 Linux-Android %

jrjohn avatar Oct 17 '22 02:10 jrjohn

The link you provided doesn't explain anything about the directories.

The directory names in sqlite-jdbc are used to perform a lookup depending on the OS/arch detected, then the corresponding native library is copied to a temp directory.

I don't see how changing the directories where the native lib is stored would change anything.

gotson avatar Oct 17 '22 03:10 gotson

https://developer.android.com/ndk/guides/abis#gradle

ABI management on the Android platform This section provides details about how the Android platform manages native code in APKs.

Native code in app packages Both the Play Store and Package Manager expect to find NDK-generated libraries on filepaths inside the APK matching the following pattern:

/lib/"abi name"/lib.so. <====== this is reason

Here, is one of the ABI names listed under Supported ABIs, and is the name of the library as you defined it for the LOCAL_MODULE variable in the Android.mk file. Since APK files are just zip files, it is trivial to open them and confirm that the shared native libraries are where they belong.

jrjohn avatar Oct 17 '22 03:10 jrjohn

image Current ABI name-only support:

armeabi-v7a arm64-v8a x86 x86_64

jrjohn avatar Oct 17 '22 03:10 jrjohn

I don't think the issue Android UnsatisfiedLinkError #248 is done.

jrjohn avatar Oct 17 '22 03:10 jrjohn

In that case the problem is more about how the lib is loaded for Android than just the directory name.

The articles you provide describe native libs that are within the project, but not really about native libs that are within a dependency though.

gotson avatar Oct 17 '22 03:10 gotson

So currently if i use

dependencies {

    implementation 'androidx.appcompat:appcompat:1.4.2'
    implementation 'com.google.android.material:material:1.6.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'androidx.navigation:navigation-fragment:2.3.5'
    implementation 'androidx.navigation:navigation-ui:2.3.5'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    implementation 'org.xerial:sqlite-jdbc:3.39.3.0'

image

I need to add jniLibs to myapp source:

app
____src
_____|- main
________|-  jniLibs
_______________|-   armeabi-v7a
___________________|-   libsqlitejdbc.so
_______________|-  arm64-v8a
____________________|-   libsqlitejdbc.so
_______________|- x86
____________________|-   libsqlitejdbc.so
_______________|- x86_64
____________________|-  libsqlitejdbc.so 

I think this should be included in the jar file.

jrjohn avatar Oct 17 '22 03:10 jrjohn

I was checking this in Android Studio, and i think the problem lies elsewhere.

When i opened the APK generated by Android Studio, i can see the Mac and Windows native libraries in /org/sqlite/native, but not the other libraries for Linux.

I have a feeling that they are excluded by Gradle automatically because they are .so.

gotson avatar Oct 17 '22 05:10 gotson

I couldn't fathom how the library loading worked, and i just found out that specific bit of code for Android.

When Android is detected, it uses System.loadLibrary instead of the SQLiteJDBCLoader.

My understanding is that

  • Gradle dependencies cannot have .so files in it. If they do, those are stripped in the resulting APK (as i found out in the previous comment).
  • System.loadLibrary will find the libraries without having to provide the full path, but that requires the libraries to be added to the jniLibs directory in Android Studio

I feel like this is not an issue, but should be properly documented.

There's no way the jar can provide the android libraries in the right folder AFAIK. If you can find a way for a third-party dependency to provide native libs for Android, we can evaluate a change.

gotson avatar Oct 17 '22 08:10 gotson

I also found this: https://developer.android.com/studio/releases/gradle-plugin#extractNativeLibs

I haven't found how to keep the .so files in the APK, but it seems it's not the best way to do for Android.

Ideally what we should have is a way to automatically:

  • extract the 4 android libraries from the jar during build
  • strip the other libraries of the jar in order to optimize the apk size

That would be however outside of the scope of this project, and should probably be handled by a dedicated Gradle plugin for Android.

gotson avatar Oct 18 '22 01:10 gotson

I'll try how can finish read .so file from the jar file and report it here. Thanks

jrjohn avatar Oct 18 '22 01:10 jrjohn

🎉 This issue has been resolved in 3.39.4.0 (Release Notes)

github-actions[bot] avatar Nov 07 '22 10:11 github-actions[bot]

The problem does not resolved. image

Android 12

SeregaYakovlev avatar Dec 05 '23 17:12 SeregaYakovlev