代码之家  ›  专栏  ›  技术社区  ›  Wout_bb

将更新的共享本机库(.so文件)添加到Android Studio应用程序会导致不满意的链接错误

  •  2
  • Wout_bb  · 技术社区  · 7 年前

    我有一个android应用程序,是用android Studio 3.0.1编写的,带有CompileSDK版本26。此应用程序依赖于用本机代码(c++)编写的模块。模块中的本机代码依赖于第三方共享库(.so)文件。在Cmake文件中,使用标准方法包括该第三方库,例如:

    add_library( my-module-lib
    
                 SHARED
    
                 src/main/cpp/file1.cpp
                 src/main/cpp/file2.cpp )
    
    add_library( libthird_party_library SHARED IMPORTED )
    set_target_properties( libthird_party_library PROPERTIES IMPORTED_LOCATION ${pathToProject}/src/main/jniLibs/${ANDROID_ABI}/libthird_party_library.so)
    
    target_link_libraries( my-module-lib libthird_party_library )
    

    然后将My module作为依赖项添加到主应用程序,并使用以下方式加载本机代码:

    System.loadLibrary("my-module-lib");
    

    这一切都很好,但我需要更新第三方库。我认为这就像更换旧的一样简单。所以新的文件。但这会导致一个不令人满意的链接错误:

    java.lang.UnsatisfiedLinkError: dlopen failed: library "libthird_party_library.so.2" not found
                                                                                              at java.lang.Runtime.loadLibrary0(Runtime.java:989)
                                                                                              at java.lang.System.loadLibrary(System.java:1567)
    

    需要注意的是,android现在搜索的是“.so.2”文件,而不是“.so”文件。所以我认为,出于某种原因,旧的一个仍然包含在某个地方,并且由于名称冲突,新的一个被重命名为“*.2”。所以我尝试了以下方法来摆脱它:

    1) [不工作]删除所有内容,重新编译所有内容

    只需删除所有内容,即:

    • 这个我的模块的externalNativeBuild文件夹
    • 我的模块的生成文件夹
    • 我的应用程序的生成文件夹

    重建一切,即:

    • 构建(>);清理项目
    • 构建(>);使模块成为“我的模块”
    • 构建(>);刷新链接的C++项目
    • 构建(>);重建项目

    但这仍然会导致同样的不满意链接错误

    2) [不起作用]更改服务器的名称。so文件

    将更新库的名称更改为 “libthird\u party\u library\u NEW.so” 以及更改cmake文件:

    set_target_properties( libthird_party_library PROPERTIES IMPORTED_LOCATION ${pathToProject}/src/main/jniLibs/${ANDROID_ABI}/libthird_party_library_NEW.so)
    

    相同错误

    3) [有效,不是一个好的解决方案]重命名旧的“.so”文件并包括新文件

    一个可行的“解决方案”是使用 重构(>);重命名 大概是 “libthird\u party\u library\u OLD.so” 然后使用标准名称复制新的第三方库 “libthird\u party\u library.so” . 但这当然不是一个很好的解决方案,因为旧的不需要的库将包含在apk中。

    1 回复  |  直到 7 年前
        1
  •  3
  •   Wout_bb    7 年前

    结果证明,在android studio中链接版本化的共享库时出现了问题。与中类似 this question 如前所述 here .

    问题是“的内部版本号” libthird\u party\u库。所以 “实际上是” libthird\u party\u库。所以2. “。这可以通过在linux下在.so文件上运行objdump找到,即:

    objdump -p libthird_party_library.so | grep so
    

    其输出:

    libthird_party_library.so:     file format elf64-little
      NEEDED               libm.so
      NEEDED               libc.so
      NEEDED               libdl.so
      SONAME               libthird_party_library.so.2
      required from libdl.so:
      required from libm.so:
      required from libc.so:
    

    因为android看到的文件名是“ libthird\u party\u库。所以 “android尝试加载” libthird\u party\u库。所以2. “它显然找不到所需的库。

    解决方案

    一个显而易见的解决方案是将文件名改为“ libthird\u party\u库。所以2. ,但这不起作用,因为android studio只包括以结尾的库。所以在apk中(aaargh)。

    解决方案是将内部版本号更改为“ libthird\u party\u library\u 2。所以 ,将文件重命名为 libthird\u party\u library\u 2。所以 “并更改Cmake文件以反映此更改。

    1) 在linux下,可以通过以下方式更改内部版本号:

    rpl -R -e libthird_party_library.so.2 libthird_party_library_2.so libthird_party_library.so
    

    其中第一个参数是内部版本号,第二个参数是我们需要将其更改为的版本号,第三个参数是文件名。确保旧内部版本号的长度与新版本号的长度相同!!

    2) 将文件名更改为“ libthird\u party\u library\u 2。所以 “使用您最喜欢的工具

    3) 将CMake文件中的此行更改为

    set_target_properties( libthird_party_library PROPERTIES IMPORTED_LOCATION ${pathToProject}/src/main/jniLibs/${ANDROID_ABI}/libthird_party_library_2.so)
    

    希望这有帮助!