实战演练
在我们实战JNI与NDK时,有两种方式在编译.so文件
(1)一种是编译生成 .h头文件 编写C/C++文件、Android.mk文件 使用ndk命令来编译生成 .so文件
(2)一种是使用AS下CMake编程自动生成 .so文件(这种比较方便)
我们重点讲一下第一种 来共同的学习一下从JNI到NDK的过程
一、NDK编译 .so
(1)第一步我们新建一个项目 新建一个JniUtils类在JniUtils里面写native函数,写完函数重新build一下或者运行一下都ok
(2)将我们的工程目录从Android目录下切换到project目录下
在app的build/intermediates目录下有个classes有编译生成的class文件
(app-->build-->intermediates-->clsasses-->debug-->我们的包名-->JniUtils.class)
使用Terminal 命令工具 进入debug目录下 使用命令javah -jni com.hyperx.jnitestdemo.JniUtils
我们看到在debug目录下会生成com_hyperx_jnitestdemo_JniUtils.h头文件 这个名字比较长 可以改个短一点的
(3)在app的main目录下我们新建一个jni文件夹,将刚才的 .h头文件复制过来 接着要在jni目录下新建一个c或者c++文件 都可以
ps.这里要注意一下:c/c++文件中要include我们刚才生成的 .h 头文件
(4)接下来就是Android.mk文件 这里注意一下 命名一定要规范
LOCAL_MODULE: 指向的是你将要打包好的.so库的名字
LOCAL_SRC_FILES:指向的是你写好的C文件(我这里应该是jni.c文件)这个C文件你可以理解为是一个目录
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS :=-llog
LOCAL_MODULE := test
LOCAL_SRC_FILES := jni.c
include $(BUILD_SHARED_LIBRARY)
(5)还有一个就是Application.mk文件 这里可以指定你要打包so文件所对应的的平台,因为我这里只使用armeabi-v7a 所以只输出了一种
输出全部 改成 all 即可
APP_ABI := all
(6)接下来就是ndk编译打包.so文件了
我们还是使用窗口命令进入main目录下的jni文件下使用 ndk-build命令即可
ps: 1. 需要进入jni目录下使用ndk命令
2.我这里只输出了armeabi-v7a架构的so文件 大家在Application.mk文件中改成all 重新编译即可生成各个架构的.so文件
3.这里有个警告————> ndk编译支持Android的最小版本是16 大家记得改一下
(7)大家重新切换到project视图下的main目录,我们可以看到多出来两个文件夹 (libs,obj),点开看一下 libs目录下已经有我们打包好的.so库了,我们把libs下对应架构目录的so拷贝出来就可以使用了,到此我们的ndk工作已经完成。(这两个文件夹都是编译产生的,拷贝完后 都可以删除 对项目没有影响 )
(8)关于jni的与java的调用以及return
我们在main目录下新建一个jniLibs目录 将我们刚才打包好的armeabi-v7a版本的so库拷贝过去
ps:在build.gradle中我们要指定一下需要使用的cpu架构
这里我要load一下so库 这里的 "test" 就是我们在Android.mk中指定的so的名字
做一下小测验 给TextView重新复制
这里我们可能会报错
这个问题主要是因为Android studio以前使用ndkCompile后来废弃掉了,Android-Terminal-Emulator没有最近没有更新的缘故。
解决:在build.gradle中的buildTypes加如下几行代码 重新sync一下
sourceSets {
main {
jni.srcDirs = []
}
}
运行结果如下:
二、Android studio 之CMake编程
在我们使用cmake编译 .so 库时我们需要简单配置一下cmake环境
打开AS的SDK manager ——sdk tools 选中对应版本的cmake(注意这里没有cmake选项的同学,要选择AS的64位重新启动)
在cmake 下载完 同步以后我们就可以新建项目了
之前我们在使用AS创建项目的时候一直没用过下面两个勾选项,也没做过深入了解 现在知道了 是用于Android开发NDK项目使用的
在向导的Customize C++ Support部分,您可以使用下列选项自定义项目:
C++ Standard:使用下拉列表选择您希望使用哪种 C++ 标准。选择Toolchain Default会使用默认的 CMake 设置。
Exceptions Support:如果您希望启用对 C++ 异常处理的支持,请选中此复选框。如果启用此复选框,Android Studio 会将 -fexceptions 标志添加到模块级 build.gradle文件的 cppFlags中,Gradle 会将其传递到 CMake。
Runtime Type Information Support:如果您希望支持 RTTI,请选中此复选框。如果启用此复选框,Android Studio 会将 -frtti 标志添加到模块级 build.gradle文件的 cppFlags中,Gradle 会将其传递到 CMake。
项目创建完成后我们运行一下 ,看到手机上面的文字就被修改了
我们还是切换到project视图下 可以看到cmake自动帮我们生成了.so文件
因为我这里是模拟器 所以他只生成了x86架构的so文件
CMake运转流程
1、Gradle 调用外部构建脚本CMakeLists.txt
2、CMake 按照构建脚本的命令将 C++ 源文件native-lib.cpp编译到共享的对象库中,并命名为libnative-lib.so,Gradle 随后会将其打包到APK中
3、运行时,应用的MainActivity会使用System.loadLibrary()加载原生库。应用就是可以使用库的原生函数stringFromJNI()。
至此我们jni实战Hello word 两种方式都已实现 接下来我们学习一下JNI函数与Java函数之间的相互传值 (基本数据类型,数组,结构体...)
感觉有用的同学,动动小手指给个赞,码字不易。