如何在 APK 中引用库,构建 Android 图像

How to reference libraries inside an APK, building an Android image

我需要构建一个 Android 9 图像,其中包括一些预构建的 APKs(OpenVPNForAndroid,在这种特定情况下)。

从 f-droid 下载的 APK 包含一些动态加载的库。我已经使用下面的 Android.mk 文件将它添加到图像中;该应用程序已安装并正常启动,但当我尝试连接时失败并出现此错误:

Cannot run program "/system/app/OpenVPNForAndroid/lib/arm64/libovpnexec.so": error=2, No such file or directory
java.io.IOException: Cannot run program "/system/app/OpenVPNForAndroid/lib/arm64/libovpnexec.so": error=2, No such file or directory
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:1050)
        at de.blinkt.openvpn.core.OpenVPNThread.startOpenVPNThreadArgs(OpenVPNThread.java:139)
        at de.blinkt.openvpn.core.OpenVPNThread.run(OpenVPNThread.java:68)
        at java.lang.Thread.run(Thread.java:764)
Caused by: java.io.IOException: error=2, No such file or directory
        at java.lang.VNIXProcess.forkAndExec(Native Method)
        at java.lang.VNIXProcess.<init>(VNIXProcess.java:133)
        at java.lang.ProcessImpl.start(ProcessImpl.java:132)
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
        ... 3 more
,Error reading from output of OpenVPN process
Attempt to invoke virtual method 'void java.lang.Process.destroy()' on a null object reference
java.lang.NullPointerException: Attempt to invoke virtual method 'void java.lang.Process.destroy()' on a null object reference
        at de.blinkt.openvpn.core.OpenVPNThread.stopProcess(OpenVPNThread.java:56)
        at de.blinkt.openvpn.core.OpenVPNThread.startOpenVPNThreadArgs(OpenVPNThread.java:194)
        at de.blinkt.openvpn.core.OpenVPNThread.run(OpenVPNThread.java:68)
        at java.lang.Thread.run(Thread.java:764)

显然,APK 中的库将被忽略。

我想避免提取 .so 文件以将它们添加到图像中(因为我担心在未来的更新中我会忘记提取库再次),我认为这应该是可能的,但显然仍然缺少一些东西。

使用Android.mk文件,使用genandroidmk生成,是这样的:

LOCAL_PATH := $(call my-dir)

my_archs := arm x86 arm64
my_src_arch := $(call get-prebuilt-src-arch, $(my_archs))

include $(CLEAR_VARS)
LOCAL_MODULE := OpenVPNForAndroid
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_BUILT_MODULE_STEM := package.apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_SRC_FILES := de.blinkt.openvpn_175.apk

LOCAL_PREBUILT_JNI_LIBS := \
  @lib/arm64-v8a/libjbcrypto.so \
  @lib/arm64-v8a/libopenvpn.so \
  @lib/arm64-v8a/libopvpnutil.so \
  @lib/arm64-v8a/libosslspeedtest.so \
  @lib/arm64-v8a/libovpn3.so \
  @lib/arm64-v8a/libovpnexec.so

LOCAL_MODULE_TARGET_ARCH := $(my_src_arch)

include $(BUILD_PREBUILT)

然后,在我的产品定义中我有:

PRODUCT_PACKAGES += OpenVPNForAndroid

我是不是遗漏了什么,或者如果不提取它们就无法再引用 APK 中的库?

提前致谢。

嵌入式库将不再提取。看: Don't extract jni from prebuilt apks

所以你可以通过LOCAL_POST_INSTALL_CMD提取它。 尝试以下操作:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := OpenVPNForAndroid
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_BUILT_MODULE_STEM := package.apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_SRC_FILES := de.blinkt.openvpn_175.apk

# use lib/armeabi-v7a and lib/arm respectively, for 32bit apps
MY_PREBUILT_LIBS_SRC := lib/arm64-v8a
MY_PREBUILT_LIBS_DST := lib/arm64

ifeq ($(LOCAL_PRIVILEGED_MODULE),true)
MY_TARGET_DST := $(TARGET_OUT_APPS_PRIVILEGED)
else
MY_TARGET_DST := $(TARGET_OUT_APPS)
endif
LOCAL_POST_INSTALL_CMD := unzip -o $(LOCAL_PATH)/$(LOCAL_SRC_FILES) $(MY_PREBUILT_LIBS_SRC)/* -d $(MY_TARGET_DST)/$(LOCAL_MODULE) ; \
    mv $(MY_TARGET_DST)/$(LOCAL_MODULE)/$(MY_PREBUILT_LIBS_SRC) $(MY_TARGET_DST)/$(LOCAL_MODULE)/$(MY_PREBUILT_LIBS_DST) ; \
    chmod 0755 $(MY_TARGET_DST)/$(LOCAL_MODULE)/$(MY_PREBUILT_LIBS_DST)/*

include $(BUILD_PREBUILT)