需求和背景

由于项目需要将apk应用预置到定制安卓系统,且apk中带有so库。正常情况下通过install直接安装是使用PackageManager,它会将so文件拷贝到系统读取的系统so目录(system/lib或system/lib64)下,提供给App使用;但系统应用需要提前将so文件拷贝到系统目录或者app/lib目录下(/system/priv-app/xxx/lib/arm或…/arm64)。否则运行时将报错“无法找到该so库”。

解决方法

解决该问题有两种方案:

方案一,解压apk中so文件,拷贝到apk所在目录的lib目录下。

编译apk的Android.mk文件如下:


# 解压apk并将所有so文件拷贝到apk对应的lib目录下。
PRIVATE_EMBEDDED_JNI_LIBS := 'lib/*.so'
JNI_LIBS :=
$(foreach FILE,$(shell if unzip -l $(LOCAL_PATH)/$(LOCAL_SRC_FILES) $(PRIVATE_EMBEDDED_JNI_LIBS) > /dev/null ; then \
        rm -rf $(LOCAL_PATH)/uncompressedlibs && \
        mkdir $(LOCAL_PATH)/uncompressedlibs; \
        unzip $(LOCAL_PATH)/$(LOCAL_SRC_FILES) $(PRIVATE_EMBEDDED_JNI_LIBS) -d $(LOCAL_PATH)/uncompressedlibs > /dev/null && \
        find $(LOCAL_PATH)/uncompressedlibs -name *.so; \
    fi),$(eval JNI_LIBS += $(FILE)))
$(info echo $(JNI_LIBS))
LOCAL_PREBUILT_JNI_LIBS := $(subst $(LOCAL_PATH),,$(JNI_LIBS))

include $(BUILD_PREBUILT)

方案二,采用@符号指定apk运行时加载apk中的so。

赋值LOCAL_PREBUILT_JNI_LIBS 变量时加上@符号,运行时会加载apk中对应的so库,这样就不需要解压apk中的so并拷贝到lib目录。如果不加@符号,则会寻找apk安装目录下lib目录中对应so。


# 方案二、采用@符号指定apk运行时加载apk中的so
ifeq ($(TARGET_ARCH), arm)
LOCAL_PREBUILT_JNI_LIBS := \
@lib/armeabi-v7a/libxxx1.so \
@lib/armeabi-v7a/libxxx2.so
else ifeq ($(TARGET_ARCH),arm64)
LOCAL_PREBUILT_JNI_LIBS := \
@lib/armeabi-v7a/libxxx1.so \
@lib/armeabi-v7a/libxxx2.so
endif

注: 无论方案一还是方案二、System.loadLibrary方法都会先找到apk所在目录的lib或者apk中所带的so文件。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐