我在 google android-ndk group 中问过这个问题,但没有得到任何答案。
我正在尝试通过单击“Is Library”在独立项目中构建一个通用模块是 Eclipse。本项目同时提供c api和java api。虽然其中一些 API 是相关的。(这意味着将它们分成 2 个项目并不是一个好主意)让我们将其命名为 common 和 libcommon.so。
当我在另一个项目中使用这个库时(假设 testcommon),我在项目资源管理器中将公共项目添加为 Eclipse 中的库 - > 属性 - > Android - > 库 - > 添加。但这只会让我有可能在库中使用 java api。
我还在 testcommon 项目的 android.mk 中添加 libcommon.so 作为 PREBUILT_SHARED_LIBRARY,以便我可以访问 c api。( 如下 )
include $(CLEAR_VARS)
LOCAL_MODULE := common-prebuilt
LOCAL_SRC_FILES := ../../common/libs/$(TARGET_ARCH_ABI)/libcommon.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := testCommon
LOCAL_SRC_FILES := testCommon.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../common/jni/include/
LOCAL_SHARED_LIBRARIES := common-prebuilt
include $(BUILD_SHARED_LIBRARY)
这样,ndk-build 是成功的,但是当我运行它时,出现以下错误:
[2012-02-29 15:28:20 - testCommon] Error generating final archive:
Found duplicate file for APK: lib/armeabi/libcommon.so
Origin 1: E:\Code\EclipseWorkspace\testCommon\libs\armeabi\libcommon.so
Origin 2: E:\Code\EclipseWorkspace\Common\libs\armeabi\libcommon.so
我认为这是因为对库和预构建共享库的引用都将 libcommon.so 添加到 testcommon 项目中。事实上,我测试过只引用该库或添加预构建共享库,它们都将 libcommon.so 复制到 testcommon。
问题是,如果我需要一个同时具有 c 和 java apis 的库,我该怎么办。(不仅是代码)
谢谢
阅读后共享库可以调用另一个共享库吗?,我找到了解决这个问题的方法,但仍然不太确定。
在 Android.mk 中使用以下行代替 PREBUILT_SHARED_LIBRARY 也可以使本机部分正常工作,并且不会以这种方式复制库。这样可以修复重复的副本。
LOCAL_LDFLAGS := -L$(LOCAL_PATH)/../../Common/libs/$(TARGET_ARCH_ABI)/ -lcommon
这在我之前的测试中无法工作的原因是即使这样,两个库都应该在 java 中加载,而不仅仅是 libtestCommon。
System.loadLibrary("common"); // I lost this in my before test
System.loadLibrary("testCommon");
我想我现在很清楚了。
LOCAL_SHARED_LIBRARIES 和 -L plus -l 都应该在 NDK 中正常工作。
问题是当我打电话时
System.loadLibrary("testCommon")
它会尝试在 /data/data/$(app path)/lib (System.java::loadLibrary --> Runtime.java::loadLibrary --> DexPathList.java::findLibrary )找到so文件,但是当 libtestCommon 尝试要找到它的依赖项 libCommon.so,它只会在 /vendor/lib 和 /system/lib 中找到它,因为
LD_LIBRARY_PATH=/vendor/lib:/system/lib.
如果我首先调用 System.loadLibrary("common"),dlopen 会将其加载到缓存中(Linker.c::alloc_info)。我猜这使得 libtestCommon.so 加载 libCommon.so 成功。所以一切正常。
我还注意到 ndk-r7 中 SYSTEM-ISSUES.html 末尾的这些词:
- 一个错误会阻止一个应用程序共享库依赖于另一个应用程序共享库。例如,如果您为您的应用程序同时构建 libfoo.so 和 libbar.so,并在 bar/Android.mk 中将 libfoo.so 列为 libbar.so 的依赖项(使用 LOCAL_SHARED_LIBRARIES := foo),那么加载 libbar.so 将总是失败,即使你已经在你的进程中加载了 libfoo.so。
有一点不同。如果我已经在我的进程中加载了 libfoo.so,那么 libbar.so 将会成功。
所以,最后的答案是:
- 如果您需要 android 库项目中的任何共享库,请使用 LOCAL_LDFLAGS := -Lxx -lxx。
- 您必须为所需的每个共享库调用 System.loadLibrary。这也是在一个库中使用另一个共享库的方法。
- /libs/ 的库路径放在/data/data//lib/。