通过NDK在Android上加载不同版本的系统共享库?

时间:2013-02-02 13:46:30

标签: android android-ndk shared-libraries skia

我正在尝试使用一些本机库来开发一个Android应用程序。但是,android 4.0android 4.1.2上的系统共享库是不同的。为了确保兼容性,我从平台4.0获取libskia.so文件,并将其导入到我的项目中。我希望像使用第三方共享库一样加载此共享库。不幸的是,在android 4.1.2上运行时,我的应用程序似乎仍然调用系统skia库。我不知道这个,以下是我的Android.mk文件

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := sample
LOCAL_SRC_FILES := sample-jni.cpp

LOCAL_CFLAGS    := -I /home/WORKING_DIRECTORY/external/skia/include \
-I /home/WORKING_DIRECTORY/external/skia/include/core \
-I /home/WORKING_DIRECTORY/frameworks/base/core/jni/android/graphics  \
-I /home/WORKING_DIRECTORY/frameworks/base/include \
-I /home/WORKING_DIRECTORY/frameworks/base/native/include/android \
-I /home/WORKING_DIRECTORY/system/core/include \
-I /home/WORKING_DIRECTORY/external/skia/include/xml \
-I /home/WORKING_DIRECTORY/external/skia/include/images \
-I /home/WORKING_DIRECTORY/external/skia/include/views \

 LOCAL_SHARED_LIBRARIES :=skia jnigraphics
 include $(BUILD_SHARED_LIBRARY)
 include $(LOCAL_PATH)/prebuilt/Android.mk

和预建的makefile

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := skia
LOCAL_SRC_FILES := libskia.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := jnigraphics
LOCAL_SRC_FILES := libjnigraphics.so
include $(PREBUILT_SHARED_LIBRARY)

有什么想法吗?或者,还有其他方法可以确保兼容性吗?

2 个答案:

答案 0 :(得分:0)

我希望您理解,不建议在stable API之外对系统库具有任何依赖性。但Android的开放性(允许在技术上和许可方面)引入这样的依赖。从本质上讲,它意味着在非特许水域航行,并准备不仅在平台的下一版本中进行API更改,而且还准备在相同平台级别的供应商提供的(即非AOSP)设置中进行API更改。

从理论上讲,您可以将系统库变体的副本放入应用的 libs / armeabi-v7a 文件夹中,然后使用System.load(fullPath)而不是加载它的LoadLibrary()

但实际上我相信在你有机会执行你的代码之前会在你的进程中加载​​ system / lib / libskia.so ,并且你无法加载同一个lib的两个版本同样的过程。此外,较旧版本的 libskia 很可能无法在系统上加载,因为它依赖于其他系统库。

确保转发(和供应商)兼容性的最安全方法是将dynamic linking用于未记录的系统功能,并在路上执行仔细的错误检查。

但在许多情况下,系统未记录的API实际上非常稳定,Google Android团队中的优秀人员不会经常进行重大更改。因此,如果您链​​接到4.0版本的 skia ,您的代码很可能只适用于4.1.2及... ...

更新:在您的特定情况下,当一个额外的字段fTextLocale被添加到旧类时,您应该首先祝福没有在中间插入此字段的开发人员类声明。因为现在你有一个合理的策略:使用4.1.2头文件(带有额外的字段),链接4.0库(没有将访问器方法引入新字段),你的代码将有希望正常工作。

答案 1 :(得分:0)

您可以使用参数RTLD_DEEPBIND在本机代码中使用dlopen来使用不同版本的libskia。这将覆盖全局符号表。