How to use a library project with both c and java apis on Android

爱⌒轻易说出口 提交于 2020-01-01 07:03:20

问题


I have asked this question in google android-ndk group but not get any answer.

I am trying to build a common module in a independent project by click the "Is Library" is eclipse. This project provides both c apis and java apis. While some of these apis are related. ( it means it's not a good idea to separate them into 2 projects) Let's name it common and libcommon.so.

When I am using this library in another project ( suppose testcommon), I add the common project as a library in eclipse at project explorer--> properties --> Android --> Library --> Add. But this only make me possible to use java apis in the library.

Also I add libcommon.so as a PREBUILT_SHARED_LIBRARY in android.mk in testcommon project so that I could access c apis. ( as below )

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) 

In this way, ndk-build is success but when I am running it, I get below errors:

[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 

I think that because both reference to library and prebuild shared library add libcommon.so to testcommon project. In fact, I have tested to only reference the library or add a prebuild shared library, they both copied libcommon.so to testcommon.

The question is, what should I do if I need a library with both c and java apis.( not only code )

Thanks


After I read Can shared library call another shared library?, I found a way to solve this but still not very sure.

Use below line in Android.mk instead of PREBUILT_SHARED_LIBRARY also make native part works and libraries will not be copied in this way. So that duplicate copy could be fixed.

LOCAL_LDFLAGS := -L$(LOCAL_PATH)/../../Common/libs/$(TARGET_ARCH_ABI)/ -lcommon

The reason why this could not work in my before test is that even is this way, both libraries should be load in java, but not only libtestCommon.

System.loadLibrary("common"); // I lost this in my before test
System.loadLibrary("testCommon");

I think it's clear for me now.

Both LOCAL_SHARED_LIBRARIES and -L plus -l should work fine in NDK.

The problem is that when I call

System.loadLibrary("testCommon")

it will try to find so files at /data/data/$(app path)/lib (System.java::loadLibrary --> Runtime.java::loadLibrary --> DexPathList.java::findLibrary ) but when libtestCommon try to find its dependency libCommon.so, it will only find it at /vendor/lib and /system/lib since

LD_LIBRARY_PATH=/vendor/lib:/system/lib.

If I call System.loadLibrary("common") first, dlopen will load it into cache (Linker.c::alloc_info). This make libtestCommon.so loads libCommon.so success I guess. So everything works.

I also noticed these words at the end of SYSTEM-ISSUES.html in ndk-r7:

  • A bug prevents one application shared library from depending on another one. For example, if you build both libfoo.so and libbar.so for your application, and list libfoo.so as a dependency for libbar.so in bar/Android.mk (with LOCAL_SHARED_LIBRARIES := foo), then loading libbar.so will always fail, even if you have already loaded libfoo.so in your process.

There is a little different. If I have already loaded libfoo.so in my process, libbar.so will success.

So, answer at last is:

  • Use LOCAL_LDFLAGS := -Lxx -lxx if you need any shared libraries in android library project.
  • You must call System.loadLibrary for every shared libraries needed. That's also the way to use another shared library in one library.
  • The path of libraries at /libs/ is placed at /data/data//lib/.

回答1:


As an option you can use

LOCAL_ALLOW_UNDEFINED_SYMBOLS := true

in one of Android.mk and exclude the duplicate lib.




回答2:


I have been wrestling with a similar problem. I want to build an Android library project with both Java and C. I want dependent projects' Java to be able to reference the library's Java and dependent projects' C code in JNI to be able to reference the C in the library's jni. I required two kludges. One is almost identical to your solution:

LOCAL_LDFLAGS := -L$(LOCAL_PATH)/../../Common/libs/$(TARGET_ARCH_ABI)/ -lcommon

I created a dependency on the library project's actual location in the file system. Your dependency assumes the Common library project is a sibling directory of your dependent TestCommon project.

I also created a build.xml Ant file that copies the C header files from the library project to a jni/include directory in the dependent jni folder.

With these two kludges, I am able to get everything working. I would really like to eliminate both kludges, but could not find a way.



来源:https://stackoverflow.com/questions/9510162/how-to-use-a-library-project-with-both-c-and-java-apis-on-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!