android-ndk - 使用Android NDK编译依赖于其他 native 库运行的 native 库?

标签 android-ndk openssl android-gradle-plugin

我有一个依赖于 OpenSSL 的大型 C 文件库,并且我对使用 native 库非常陌生,尤其是对使用 android 很陌生。我已经成功地在 iOS 上实现了这个库,没有出现任何问题。

我一直在网上寻找有关如何执行此操作的教程/信息,但到目前为止我还没有找到任何我能理解的内容。这一切让我很困惑。

本质上,我试图弄清楚如何使用 NDK 将 C 文件库编译为 native 库,并将编译后的库与 imy android 应用程序一起使用。

据我了解,我需要一个适用于 android 本身的自定义 cmake 文件,但我不知道从哪里开始,而且我发现的文档非常难以理解。

所以,我需要一些帮助来理解在以下庄园中编译库的过程:

  1. 使用 Gradle 和 CMakeLists.txt 编译该库,将其与 openssl 和 libcrypto 链接,并将最终库与我的 Android Studio 项目链接。
  2. 能够从我的 Java 代码调用这些库中的 native 函数。 (我知道这需要 JNI Java 包装器)

(我已经成功地为 Android 所需的所有架构构建了 libssl 和 libcrypto,但我不确定如何处理 .a/.so 文件。)

对于此事的任何帮助将不胜感激。

谢谢

编辑:

我成功地使用以下内容生成了一些库文件。

文件结构:

.idea
app
build
gradle
jni    <--- I made this folder specifically fo this.
    Android.mk <-- This is the important file.
    include
        openssl
            <openssl header files>
    libs
        arm64-v8a
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
        armeabi
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
        armeabi--v7a
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
        mips
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
        mips64
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
        x86
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
        x86_64
            libcrypto.a
            libcrypto.so
            libssl.a
            libssl.so
    src <--- These are example files that i used to build this with.
        myc_files.c
        myother_c_files.c
        myc_heades.h
        myother_c_headers.h

然后,我在 Android.mk 中使用以下内容,通过运行 ndk-build 来生成一些库。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# Select from arm64-v8a armeabi armeabi-v7a mips mips64 x86 x86_64
ARCH := armeabi

APP_UNIFIED_HEADERS := true

#APP_ABI := $(ARCH)
# TARGET_ARCH := $(ARCH)
TARGET_PLATFORM := android-14

SRC_DIR := $(LOCAL_PATH)/src
HDR_DIR := $(LOCAL_PATH)/include
LIB_DIR := $(LOCAL_PATH)/libs

LOCAL_C_INCLUDES := $(HDR_DIR)
LOCAL_MODULE := myclib
LOCAL_SRC_FILES := $(SRC_DIR)/myc_files.c $(SRC_DIR)/myother_c_files.c
LOCAL_LDLIBS += -L$(LIB_DIR)/$(ARCH) -lssl -lcrypto

include $(BUILD_STATIC_LIBRARY)

这些库被放入 PROJECT/obj/local 中,我不知道从这里到哪里,或者 Android.mk 文件是否确实正确构建了库。

最佳答案

更新:使用 AGP 4.0(尚未发布),您可以从 maven 使用 OpenSSL。

dependencies {
    implementation "com.android.ndk.thirdparty:openssl:1.1.1d-alpha-1"
}

Android.mk 中,您只需添加(在末尾)

$(call import-module, prefab/curl)

以下是完整详细信息:https://android-developers.googleblog.com/2020/02/native-dependencies-in-android-studio-40.html

<小时/>

原答案:

  • 0. 为 Android 构建 openssl 库;您必须选择 ABI(armeabi-v7ax86 通常就足够了)。您可以找到official tutorial又长又无聊。在这种情况下,您可以在 GitHub 或其他地方找到预构建的二进制文件。决定您需要共享库还是静态库。

  • 1. 使用 Android Studio 2.3,您可以通过集成的 externalNativeBuild 构建您的库。梯度任务。但您可以使用 ndk-build 单独构建它命令。

  • 2.如果您选择不使用 gradle,请将构建的共享库复制到 Android 项目的 app/src/main/jniLibs 目录中。

  • 3. 您需要一个 JNI 包装器来将 Java 代码与 C 代码连接起来。在 Java 方面,在一个或多个类中声明必要的 native 方法。这些方法必须在 C/C++ 端实现,如 Android JNI walkthrough 中所述。 。您的 Java 代码必须显式加载包含这些 native 方法实现的共享库。请注意,您无法直接调用库或 opensssl 库中的 native 函数,即使这些函数已导出

正在运行的Android.mk:

include $(CLEAR_VARS)

LOCAL_MODULE := vrazovpn
LOCAL_SRC_FILES := src/myc_files.c src/myother_c_files.c
LOCAL_STATIC_LIBRARIES := openssl libcrypto
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := openssl
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libssl.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libcrypto
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libcrypto.a
include $(PREBUILT_STATIC_LIBRARY)

一些评论来澄清上述内容:

  • LOCAL_SRC_FILES 路径相对于LOCAL_PATH
  • LOCAL_C_INCLUDE 路径是相对于工作目录的,这就是为什么我们经常在它们前面加上 $(LOCAL_PATH) 前缀。
  • 可以使用 LOCAL_C_INCLUDES 来引用属于我们使用的某些库的 header ,但使用 的功能将这些 header 与库一起导出会更安全、更简洁LOCAL_EXPORT_C_INCLUDES;还有其他设置可以类似地导出。
  • Android.mk 不应该(也不能)设置目标 ABI;它从 ndk-build 接收目标 ABI。您可以通过在 Application.mk 文件中或在命令行上列出它们来控制构建中包含哪些 ABI,例如

    ndk-build APP_ABI="x86 armeabi-v7a"

如果您在 Android Studio 2.3 或更高版本中使用 gradle 插件构建库,APP_ABI 设置将被忽略。您必须在 abiFilters 中指定列表.

关于android-ndk - 使用Android NDK编译依赖于其他 native 库运行的 native 库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44297396/

相关文章:

android - Android中的应用程序安装

python - 如何提供 SWIG 的包含路径?

java - 在 bouncy caSTLe 中生成 ECDSA 私钥返回公钥

android-gradle-plugin - Android gradle 插件(升级到 2.2.0 后)失败,出现 dexguard 任务错误 "No signature of method: ....getAllLibraries()"

android - 在 gradle 中重构 Maven block

opencv - android native 代码中的 cv::VideoCapture

Android GCC 编译器更改

android - 将 FFTW 链接到 Android NDK 应用程序

security - 从 pkcs7 (.p7b) 文件中提取私钥和证书

android - 不受支持的 Android Gradle 版本