转载请注明出处:(http://blog.csdn.net/qq_35071078/article/details/70502481)
ndk-build 文件是 Android NDK r4 中引入的一个 shell 脚本。其用途是调用正确的 NDK 构建脚本。可以用这个命令来生成.so文件。
当你想使用该命令将.cpp/.c文件生成.so文件,必须有具备以下几个条件
需有有Android.mk文件,并且与对应的.cpp/.c文件在同一个目录下
需要有Application.mk文件,并且与对应的.cpp/.c文件在用一个目录下
Android.mk 文件位于项目 jni/ 目录的子目录中,用于向构建系统描述源文件和共享库。 它实际上是构建系统解析一次或多次的微小 GNU makefile 片段。 Android.mk 文件用于定义 Application.mk、构建系统和环境变量所未定义的项目范围设置。 它还可替换特定模块的项目范围设置。
Android.mk 的语法用于将源文件分组为模块。 模块是静态库、共享库或独立可执行文件。 可在每个 Android.mk 文件中定义一个或多个模块,也可在多个模块中使用同一个源文件。 构建系统只会将共享库放入应用软件包。 此外,静态库可生成共享库。
除了封装库之外,构建系统还可为您处理各种其他详细信息。例如,您无需在 Android.mk 文件中列出标头文件或生成的文件之间的显式依赖关系。 NDK 构建系统会自动为您计算这些关系。 因此,您应该能够享受到未来 NDK 版本中新工具链/平台支持的优点,而无需接触 Android.mk 文件。
此文件的语法与随整个 Android 开放源代码项目分发的 Android.mk 文件中使用的语法非常接近。 虽然使用它们的构建系统实现不同,但类似之处在于,其设计决定旨在使应用开发者更容易重复使用外部库的源代码。
简单来说,这个文件可以定义生成的.so文件的名字,可以像.cpp/.c文件引入一些动态库。
具体可以去看谷歌官方的参考
Application.mk 文件实际上是定义要编译的多个变量的微小 GNU Makefile 片段。 它通常位于 PROJECT/jni/下,其中 PROJECT 指向应用的项目目录。 另一种方式是将其放在顶级 $NDK/apps/ 目录的子目录下。
例如,Application.mk可以用来指定需要生成哪些cpu类型的.so文件,或者定义引用.so的最低android api。
详细请看谷歌官方参考
创建一个类Jni,用来声明native方法:
用javah命令生成.h文件:首先 cd app/build/intermediates/classes/debug 进入到debug目录,然后 javah com.chenxin.testndk.MyJni 生成.h文件,在app/src/main目录下创建一个jni文件夹,将刚才生成的.h文件剪切到jni文件夹里面,在jni文件夹里面创建一个.c/.cpp的文件
如果创建的是.c:
#include
#include
#define LOG_TAG "infoo"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
JNIEXPORT jstring JNICALL Java_com_chenxin_testndk_MyJni_get
(JNIEnv *env, jclass jz){
LOGI("hello,这里是native层");
return (*env)->NewStringUTF(env,"hello jni , you are so easy!");
}
如果是.cpp:
#include
#include
#define LOG_TAG "infoo"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
JNIEXPORT jstring JNICALL Java_com_chenxin_testndk_MyJni_get
(JNIEnv *env, jclass jz){
LOGI("hello,这里是native层");
return env->NewStringUTF("hello jni , you are so easy!");
}
在jni目录下创建Android.mk文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyJni
LOCAL_SRC_FILES := test.c
LOCAL_LDLIBS +=-L$(SYSROOT)/usr/lib -lm -llog
include $(BUILD_SHARED_LIBRARY)
LOCAL_MODULE:是将要生成的.so的名字
LOCAL_SRC_FILES:是需要将哪个.c/.cpp文件生成.so文件,例如我这里是test.c
LOCAL_LDLIBS:这里是给.c/.cpp文件添加了一个log库,可以打印log
在jni目录下创建Application.mk文件
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := all
APP_PLATFORM := android-8
APP_ABI:是将要生成哪些cpu类型的so,all代表全部
APP_PLATFORM:生成的so的最低android版本
.c/.cpp,android.mk,application.mk创建完成之后:
打开android studio的终端,进入到jni文件夹,cd app/src/main/jni ,然后 输入 ndk-build 回车ok,so就生成了:
此时就可以看到libs文件夹里面的so文件了:
接下来就是使用so了,首先先与.so关联起来,有两种方法
(1)第一种方法,app/src/main目录下面创建一个jniLibs文件夹,将刚才生成的libs下的所有文件夹拷贝或者剪切到这里面,然后在 build.gradle中加入:
android {
......
sourceSets {
main() {
jni.srcDirs = [] //屏蔽掉默认的jni编译生成过程
}
}
}
(2)第二种方法,直接在gradle中加入
android {
......
sourceSets {
main() {
jniLibs.srcDirs = ['src/main/libs']
jni.srcDirs = [] //屏蔽掉默认的jni编译生成过程
}
}
}
然后就是在代码中调用了:
MyJni.java:
public class MyJni {
static {
System.loadLibrary("MyJni");
}
public native static String get();
}
MainActivity.java:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("info","调用jni层的结果 : "+MyJni.get());
}
}
编译运行:
ok,成功!