如何在Android Studio中添加.so,.mk和其他原生文件?

时间:2017-05-30 05:23:22

标签: android android-studio gradle android-ndk java-native-interface

我已在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文件夹包含本机代码,我也可以使用它。 Native files under jni, obj and jniLibs folders

我已经看过可用的链接但是它们已经过时且没有任何效果。任何帮助表示赞赏。

执行以下更改后记录:

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

4 个答案:

答案 0 :(得分:6)

首先,请确保您的源位置,套件示例。你有一些问题。所有原生文件都应在src/main/

../src/main
.........../jni # your cpp, header and mk files
.........../jniLibs # your folders with all libs
.........../java # other code

然后,确保在任何Native使用之前,在Activity,Application等中,在静态字段中加载lib。

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项目安装了Android NDK Source。

From Android SDK Settings

答案 1 :(得分:3)

添加到GensaGames'回答,如果您有一个.mk文件用于构建本机库,为了将其添加到构建过程,您必须在模块级build.gradle文件中指定该文件的路径,在android {}中块:

externalNativeBuild {
    ndkBuild {
        path 'path/to/Android.mk'
    }
}

作为一个注释,GensaGames建议的目录结构对Android Studio来说并不是必需的 - 只要您在build.gradle或Android中指定目录,就可以将.mk和.cpp文件放在任何您喜欢的位置。 .mk。

答案 2 :(得分:2)

我想我已经使用简单的JNI项目在Android Studio中重现了这个错误。触发此特定错误的事情(“make:*** No target ...”)对我来说是Android.mk中其中一个源文件的路径不正确。 (如果路径正确,则构建应该成功;如果完全保留源文件,则会出现链接器错误。)例如,如果我指定了其中一个源的错误路径,则会发生以下错误:< / p>

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,所以我猜想存储Android.mk的SerialPort.c的路径是不正确的。请记住,Android.mk中存储的路径是相对于Android.mk文件本身而不是根目录。

答案 3 :(得分:2)

对于本机开发,您应该有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端使用它们时,您应该执行一些操作。

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'
   }
}

我认为我的回答将帮助您理解一些细节。另外,您还可以查看这些答案。

  1. 用于调用本机方法:Enter
  2. 用于链接共享库:Enter
  3. 从我的其他答案中复制了答案:Enter