.so file not found (unsatisfiedlinkerror), but it exist

1.4k Views Asked by At

I've been struggling with this for a while, and although I have found many having similar problems, their fixes don't seem to work for me. Perhaps I am misunderstanding something though, regarding of where the shared library files go after installing an APK.

Setup: Android, using a build.gradle file, and CMakeLists.txt since I want to run some C++ code using JNI. I followed the tutorial basically from https://developer.android.com/studio/projects/add-native-code, along with other pieces here and there from other websites.

My C++ code works correctly (it only returns a number). The APK generated can be unzipped, and I see all the .so files under the lib directory. Inside /lib there are four directories, each one for a different arquitecture, including my target (ARM). However, when I install the APK and try to run my C++ code portion, it returns an unsatisfiedlinkerror with the message saying "We looked for your .so file on nativeDirs under /system/lib and /vendor/lib, but we didn't find it)."

Now, if I instead push the .so file from the unzipped APK, into the location they mention, everything will run correctly (so at least my code is compiled correctly). Am I misunderstanding something? I was also reading that it appears that the .so files are not extracted from the APK anymore, but still, it's not finding it. I actually can't find the .so file in the system at all, but again, if I extract the APK it will be there.

My CMakeLists.txt simply have the parameters based on: https://developer.android.com/studio/projects/configure-cmake

cmake_minimum_required(VERSION 3.4.1)

add_library(native SHARED
        nativeCode.cpp)

target_link_libraries(native
        android
        log)

I'm loading my library as:

static {
    System.loadLibrary("native");
}

My questions are:

  1. First of all, where should the .so files exist in my device after installing the APK.
  2. Should I specify in any way the location of where the .so files should be under CMakeLists.txt?
  3. If I need to specify a path for the app to look for the .so files, where should this be?

Thank you for your help!

1

There are 1 best solutions below

9
Dev007 On

i'm answering your question one by one...

  1. QUESTION : First of all, where should the .so files exist in my device after installing the APK ?
  • Starting From Android M, it supports uncompressed native libraries in APKs, which allows the platform to read the native libraries directly from the APK without having to extract them.It have the flag android:extractNativeLibs which is default false. This is why you don't see them in the "data/data/packagename/lib/" directory if you're testing on a device on Android M or later.

  • Ultimately for testing purpose you can use android:extractNativeLibs="true" in Application tag of AndroidManifest.xml, to see in "data/data/packagename/lib/" folder.

         <application
          android:extractNativeLibs="true">
            ...
         </application>
    
  1. QUESTION: Should I specify in any way the location of where the .so files should be under CMakeLists.txt?
  • Considering your nativecode.cpp in rootPath/app/src/main/cpp/nativecode.cpp, and your CMakeList.txt under roothPath/app , your CmakeList.txt add_library should be like below,

      add_library( # Sets the name of the library.
      nativecode
      # Sets the library as a shared library.
      SHARED
      # Provides a relative path to your source file(s).
      src/main/cpp/nativecode.cpp)
    

If you notice, i added relative path and i don't know about case Sensitive. please try with smallcase.

  • I noticed, you mentioned your lib name as "nativeCode" , but in Code you taken only (System.loadLibrary("native")), it should be nativeCode. make sure the name matches for your library.

  • Add path of your CMakeList.txt in build.gradle (App Level)

    android{

      ...
    
      externalNativeBuild {
          cmake {
              path "CMakeLists.txt" //consider this CMakeLists.txt inside rootPath/app/CMakeLists.txt
          }
      }
    
  1. QUESTION : If I need to specify a path for the app to look for the .so files, where should this be?
  • If you follow above steps it will work, You no need to specify which is modern and easy way., but if you wish manually i'm sure it bit complex compared to above(atleast for me)

  • First you have to create .so files from your .cpp file. (for that,we can do with Android.mk and Application.mk)

  • Then, you can add following line in build.gradle app level.

    android{
       ...
       ...
      sourceSets {
        main {
           jniLibs.srcDir 'jniLibs' //consider this jniLibs folder under rootPath\app\src\main\jniLibs
        }
      }
    }
    
  • Then, you have to add *.so files in rootPath/app/jniLibs/**/*.so. You have to generate *.so files for all supported ARM like, ("x86", "x86_64", "armeabi", "armeabi-v7a", "arm64-v8a")

then your folder path something like ,

  1. rootPath\app\src\main\jniLibs\arm64-v8a\libnativecode.so,
  2. rootPath\app\src\main\jniLibs\arm64-v7a\libnativecode.so and so on...

Hope, these clear your issues and your doubts aswell .