如何在 Android Studio 中添加 .so、.mk 等原生文件?
Posted
技术标签:
【中文标题】如何在 Android Studio 中添加 .so、.mk 等原生文件?【英文标题】:How to add .so, .mk and other native files in Android Studio? 【发布时间】:2017-10-30 10:40:37 【问题描述】:我必须在我的 android Studio 项目中添加原生文件 .so、.mk、.sh、.cpp。在 Eclipse 中,将 .so 文件添加到 libs 文件夹中,并将其他文件添加到 jni 和 obj 文件夹中,一切正常。 但是在 Android 工作室中,我在 jniLibs 文件夹中添加了 .so 文件,并在 .gradle 文件中进行了如下更改
ndk
abiFilters 'armeabi', 'armeabi-v7a', 'x86'
sourceSets.main
jniLibs.srcDir 'src/main/libs' //set libs as .so's location instead of jniLibs
jni.srcDirs = [] //disable automatic ndk-build call with auto-generated Android.mk
下面是我的项目结构和我需要添加的文件。有包含本机代码的 jni 和 obj 文件夹,我必须使用它。
我已经看到了可用的链接,但它们已经过时并且没有任何效果。任何帮助表示赞赏。
进行以下更改后登录:
sourceSets.main
jniLibs.srcDir 'src/main/libs' //set libs as .so's location instead of jniLibs
jni.srcDirs = [] //disable automatic ndk-build call with auto-generated Android.mk
externalNativeBuild
ndkBuild
path 'src/main/jni/Android.mk'
日志:
Error while executing 'E:\Android_SDK\ndk-bundle\ndk-build.cmd' with arguments NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=E:\folder\sampleapp\app\src\main\jni\Android.mk NDK_APPLICATION_MK=E:\folder\sampleapp\app\src\main\jni\Application.mk APP_ABI=armeabi-v7a NDK_ALL_ABIS=armeabi-v7a NDK_DEBUG=1 APP_PLATFORM=android-16 NDK_OUT=E:/folder/app/build/intermediates/ndkBuild/debug/obj NDK_LIBS_OUT=E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -n
md "E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib\armeabi-v7a" >NUL 2>NUL || rem
copy /b/y "E:\Android_SDK\ndk-bundle\build\\..\prebuilt\android-arm\gdbserver\gdbserver" "E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib\armeabi-v7a\gdbserver" > NUL
E:/Android_SDK/ndk-bundle/build//../prebuilt/windows-x86_64/bin/echo.exe [armeabi-v7a] "Gdbserver ": "[arm-linux-androideabi] E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib/armeabi-v7a/gdbserver"
E:/Android_SDK/ndk-bundle/build//../prebuilt/windows-x86_64/bin/echo.exe [armeabi-v7a] "Gdbsetup ": "E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib/armeabi-v7a/gdb.setup"
E:/Android_SDK/ndk-bundle/build//../prebuilt/windows-x86_64/bin/echo.exe "directory E:/Android_SDK/ndk-bundle/build//../platforms/android-16/arch-arm/usr/include E:/folder/app/src/main/jni E:/Android_SDK/ndk-bundle/build//../sources/cxx-stl/system" >> E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib/armeabi-v7a/gdb.setup
E:/Android_SDK/ndk-bundle/build//../prebuilt/windows-x86_64/bin/echo.exe "set solib-search-path E:/folder/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a" > E:\folder\sampleapp\app\build\intermediates\ndkBuild\debug\lib/armeabi-v7a/gdb.setup
process_begin: CreateProcess(NULL, "", ...) failed.
make: *** No rule to make target `E:/folder/app/src/main/jni/SerialPort.c', needed by `E:/folder/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/objs-debug/serial_port/SerialPort.o'. Stop.
Build command failed.
Error:executing external native build for ndkBuild E:\folder\sampleapp\app\src\main\jni\Android.mk
Build command failed.
Error while executing 'E:\Android_SDK\ndk-bundle\ndk-build.cmd' with arguments NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=E:\folder\sampleapp\app\src\main\jni\Android.mk NDK_APPLICATION_MK=E:\folder\sampleapp\app\src\main\jni\Application.mk APP_ABI=armeabi-v7a NDK_ALL_ABIS=armeabi-v7a NDK_DEBUG=0 APP_PLATFORM=android-16 NDK_OUT=E:/folder/app/build/intermediates/ndkBuild/release/obj NDK_LIBS_OUT=E:\folder\sampleapp\app\build\intermediates\ndkBuild\release\lib APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -n
make: *** No rule to make target `E:/folder/app/src/main/jni/SerialPort.c', needed by `E:/folder/app/build/intermediates/ndkBuild/release/obj/local/armeabi-v7a/objs/serial_port/SerialPort.o'. Stop.
process_begin: CreateProcess(NULL, "", ...) failed.
Error:executing external native build for ndkBuild E:\folder\sampleapp\app\src\main\jni\Android.mk
【问题讨论】:
developer.android.com/studio/projects/add-native-code.html 顺便说一句,不要贴代码截图;将代码作为文本发布。 @Michael 感谢您的建议,但我不认为上面的代码结构有任何揭示。这只是为了显示项目文件夹结构。 :) 您的屏幕截图未显示jni.srcDirs = []
。如果您有预建库,则根本不需要 externalNativeBuild ...
块。再次从您的屏幕截图中,您似乎没有E:\folder\sampleapp\app\src\main\jni\Android.mk
文件。要使用该图片上的文件结构,您应该使用ndkBuild path 'jni/Android.mk'
@AlexCohn 我稍后在捕获该屏幕截图后添加了 jnisrcDirs=[] 。我给出的外部构建路径是 src/main/jni/Android.mk。在 logcat 中,我刚刚更改了真实项目和文件夹的名称。
【参考方案1】:
首先,确保您的源位置,套件示例。你有一些问题。所有原生文件都应该在src/main/
../src/main
.........../jni # your cpp, header and mk files
.........../jniLibs # your folders with all libs
.........../java # other code
然后,确保在任何 Native 使用之前,在 Activity、Application 等中加载静态字段中的库。
private static final String LIB_NAME = "libserial_port";
private static final String LIB_NAME_1 = "libzqcom";
static
System.loadLibrary(LIB_NAME);
System.loadLibrary(LIB_NAME_1);
UPD 1:
确保您已安装 Android NDK Source for Native Android 项目。
【讨论】:
添加此 System.loadLibrary() 代码后应用程序立即崩溃 @NareshSharma 只有一种方法可以加载本机库,通过System.loadLibrary()
,我想你做错了什么,并收到了 Linkify 异常,因为 Source 找不到具有该名称的库。
NDK 已下载,路径在 local.properties 文件中给出
@NareshSharma 然后我看不到问题,我用我的 C/C++ 源代码构建每个项目都有任何问题。只用官方文档,没什么特别的developer.android.com/studio/projects/add-native-code.html
我们需要对 .mk 文件在 gradle 中做些什么改变?【参考方案2】:
除了 GensaGames 的回答之外,如果您有一个用于构建本机库的 .mk 文件,为了将其添加到构建过程中,您必须在模块级构建中指定该文件的路径。 gradle 文件,在 android 块中:
externalNativeBuild
ndkBuild
path 'path/to/Android.mk'
请注意,GensaGames 建议的目录结构对于 Android Studio 并非绝对必要 - 您可以将 .mk 和 .cpp 文件放在任何您喜欢的位置,只要您在 build.gradle 或 Android.mk 中指定它们的目录即可.
【讨论】:
我使用了路径:path 'src/main/jni/Android.mk' 错误:为 ndkBuild E:\folder\app\src\main\jni\Android 执行外部原生构建。 MK 完整的Logcat在上面可以看到。【参考方案3】:对于原生开发,你应该有 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)
--- 第一行返回 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端使用它们时,你应该做一些操作。
1.检查项目文件夹中local.properties文件中的ndk路径。它显示了用于构建 makefile 的 ndk-bundle 路径。
ndk.dir=/Users/../Library/Android/sdk/ndk-bundle
2.检查 gradle 文件中的构建脚本。此脚本显示共享库的位置:
sourceSets.main
jni.srcDirs = []
jniLibs.srcDir 'src/main/libs'
3.并显示你的makefile路径到gradle。
externalNativeBuild
ndkBuild
path 'src/main/jni/Android.mk'
我想我的回答会帮助你理解一些细节。另外,你也可以看看这些答案。
-
调用原生方法:Enter!
用于链接共享库:Enter!
从我的其他答案复制的答案:Enter!
【讨论】:
【参考方案4】:我想我已经使用一个简单的 JNI 项目在 Android Studio 中重现了该错误。对我来说,触发这个特定错误(“make: *** No target...”)的原因是 Android.mk 中的一个源文件的路径不正确。 (如果路径正确,则构建应该成功;如果您完全保留源文件,您将收到链接器错误。)例如,如果我指定了一个不正确的源路径,则会发生此错误:
make: *** No rule to make target `/Users/afarm/AndroidStudioProjects/Mktest/app/src/main/cp/stringdep.cpp', needed by `/Users/afarm/AndroidStudioProjects/Mktest/app/build/intermediates/ndkBuild/debug/obj/local/armeabi/objs-debug/native-lib/src/main/cp/stringdep.o'. Stop.
这看起来像你上面描述的错误。 Android.mk 没有找到您的 SerialPort.c,所以我猜 SerialPort.c 存储的 Android.mk 的路径不正确。请记住,Android.mk 中存储的路径是相对于 Android.mk 文件本身的,而不是相对于根目录的。
【讨论】:
下面是我的 Android.mk 文件 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) TARGET_PLATFORM := android-3 LOCAL_MODULE := serial_port LOCAL_SRC_FILES := SerialPort.c LOCAL_LDLIBS := - llog 包括 $(BUILD_SHARED_LIBRARY) 上面的Android.mk文件没问题还是需要添加什么? 在屏幕截图中,SerialPort 源文件的扩展名为 .cpp 而不是 .c? 更改为 .cpp 但结果仍然相同 另外,根据错误消息,它在 app/src/main/jni/ 中查找,而在屏幕截图中,文件位于 app/jni/ 中。以上是关于如何在 Android Studio 中添加 .so、.mk 等原生文件?的主要内容,如果未能解决你的问题,请参考以下文章
如何在Android Studio中添加RecyclerView-v7支持包
如何在 android studio 中添加 *.jack?
如何在 android studio 中添加 Mopub 广告