我有一个很大的C文件库,它依赖于OpenSSL,我很擅长使用本机库,尤其是使用android的新手。我已经成功地在iOS上实现了这个库而没有任何问题。
我一直在网上寻找关于如何做到这一点的教程/信息,但到目前为止我还没有找到任何我能理解的内容。这对我来说都很困惑。
基本上我正试图弄清楚如何使用NDK将C文件库编译成本机库,并使用imy android应用程序编译库。
根据我的理解,我需要一个自己的自定义cmake文件,但我不知道从哪里开始,我发现的文档非常难以理解。
所以,我需要一些帮助来理解在以下庄园中编译库的过程:
(我已经设法为android需要的所有arch构建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文件实际上正确构建了库。
答案 0 :(得分:6)
0。为Android构建openssl库;你必须选择ABI( armeabi-v7a 和 x86 通常就足够了)。你可以找到official tutorial长而无聊的人。在这种情况下,您可以在GitHub或其他地方找到预构建的二进制文件。决定是否需要共享库或静态库。
1。使用Android Studio 2.3,您可以通过集成的externalNativeBuild gradle任务构建您的库。但您可以使用ndk-build
命令单独构建它。
2. 如果您选择不使用gradle,请将构建的共享库复制到Android项目的app/src/main/jniLibs
目录。
3. 您需要一个JNI包装器来将Java代码与C代码连接起来。在Java端,在一个或多个类中声明必要的 native 方法。这些方法必须在C / C ++端实现,如Android JNI walkthrough中所述。您的Java代码必须显式加载包含这些本机方法实现的共享库。请注意,即使这些函数是导出,也无法直接调用库中的本机函数或opensssl库中的本机函数。
工作 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_PATH)
前添加前缀。 Android.mk 不应该(也不能)设置目标ABI;它从ndk-build
接收目标ABI。您可以通过将它们列在 Application.mk 文件或命令行中来控制要在构建中包含哪些ABI,例如
ndk-build APP_ABI="x86 armeabi-v7a"
如果您使用gradle插件在Android Studio 2.3或更高版本中构建库,则会忽略APP_ABI
设置。您必须在abiFilters中指定列表。
答案 1 :(得分:4)
您可以使用本机开发进行数千次操作(我的意思是C / C ++)。这些语言非常简单,您可以执行从Java到C / C ++的繁重操作。例如,Camera硬件是Android设备中最重且最差的硬件之一。所以,当你试图处理这个并添加自己的操作时,它真的很糟糕。在本地开发方面,这种操作在CPU上工作,不需要通过Dalvik或其他方式进行翻译。这就是为什么你需要Android设备的所有CPU架构。因为,每个拱门都有自己的计算速度或技术。如果有任何协处理器,您也应该考虑到这一点。这是关于NDK的简短概述。
对于构建或重建本机库,您有两种方法,CMake和NDK构建。这两个建筑系统之间没有太多差异,所以我想用NDK建筑解释我的答案。
对于本机开发,您应该有main / jni文件夹,您应该将库和本机源放在其中并在此文件夹中构建它们。在您创建两个文件之前,Android.mk和Application.mk。 Android.mk用于构建本机库(模块),添加标志等。您可以在Android.mk中构建静态库和共享库。构建C源时,它会创建静态库(.a)。但是这些库不适合在Java端使用。您只能使用它们来创建共享库(.so)。为此,您应该构建C ++源代码,如果需要,可以将静态库添加到此。
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
ifneq (,$(filter $(TARGET_ARCH_ABI), armeabi-v7a x86 arm64-v8a x86_64))
LOCAL_MODULE := myLibrary
LOCAL_SHARED_LIBRARIES := cpufeatures opencv_imgproc opencv_core
LOCAL_C_INCLUDES := $(LOCAL_PATH)/c-files
LOCAL_SRC_FILES := $(LOCAL_PATH)/myJni.cpp
include $(BUILD_SHARED_LIBRARY)
---第1行返回main / jni路径。
---第二行清除所有旧的LOCAL_***
变量。
---每个拱门的第3行构建模块在那里声明。
---第4行显示模块名称,当你构建它时,NDK会自动添加lib和.so扩展名(libmyLibrary.so)。
---第5行添加了其他共享库,您需要在本地源中使用它们。
---第6行将C文件添加到您的模块中。
---第7行显示了您尝试构建的C ++源代码。
---第8行是建筑指挥。
在Application.mk中,您可以在发布模式或调试模式下为项目提供类似的命令。你应该在这个文件中给出arch。例如APP_ABI := armeabi-v7a x86 arm64-v8a x86_64
等等
当您尝试构建库并在java端使用它们时,您应该执行一些操作。
检查项目文件夹中local.properties文件中的ndk路径。它显示了构建makefile的ndk-bundle路径。
ndk.dir = /用户/../库/ Android设备/ SDK / NDK束
在gradle文件中检查构建脚本。此脚本显示共享库的位置:
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir 'src/main/libs'
}
并将您的makefile路径显示为gradle。
externalNativeBuild {
ndkBuild {
path 'src/main/jni/Android.mk'
}
}
我认为我的回答将帮助您理解一些细节。另外,您还可以查看这些答案。
答案 2 :(得分:0)
首先,您需要已经交叉编译(针对Android平台和ABI)OpenSSL lib,或者在AS Project中进行编译。 然后,如果您熟悉cmake和gradle,这是最简单的方法,您可以在https://github.com/googlesamples/android-ndk/tree/master/hello-libs找到您想要的完整示例。 请特别注意cmake脚本CMakeLists.txt和gradle脚本app / build.gradle和gen-libs / build.gradle。我希望这可以帮到你