I need to build an Android 9 image which includes some prebuilt APKs (OpenVPNForAndroid, in this specific case).
The APK, downloaded from f-droid, includes some libraries that are loaded dynamically. I've added it to the image with the Android.mk file below; the app is installed and starts normally, but fails when I try to connect with this error:
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)
Apparently, the libraries that are inside of the APK are ignored.
I'd like to avoid to extract the .so files to add them to the image (since I fear that on future updates I'll forget to also extract the libraries again) and I think it should be possible, but apparently something is still missing.
The used Android.mk file, generated using genandroidmk, is this:
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)
and then, in my product definition I have:
PRODUCT_PACKAGES += OpenVPNForAndroid
Am I missing something or it's simply no longer possible to refer to libraries inside an APK, without extracting them?
Thanks in advance.
The embedded libs will not be extracted any more. See: Don't extract jni from prebuilt apks
So you can extract it by LOCAL_POST_INSTALL_CMD. Try the following:
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)