突然发现之前的jni知识在大脑中空空如也,只留有那么点痕迹知道它曾经在大脑中驻足过.我还是简单写下,留下些更深的痕迹 ,方便查找
JNl:即 Java Native Interface Java本地接口
JNI:作用 就是方便的在Java/Android中调用 C/C++代码
使用前提:
1.下载NDK工具 方法
在AS中 File-Setting--Android SDK--sdkTools中安装
2.安装CMAKE
3.配置环境变量:
在Android中使用JNI分为静态注册和动态注册两种(现在先讲一下静态注册)
静态注册:Java层声明的native方法和JNI函数一一对应.
动态注册:Java层声明的native方法和任意JNI函数连接起来.
静态注册方式如下:
1.在类中定义static方法 加入System.loadlibray()引入C代码库名(即加载so库文件)
static {
System.loadLibrary("JniTest");
}
2.定义native方法(static可以加可以不加)
public class JNIUtils {
public static native double Add(double num1,double num2);
public static native double Sub(double num1,double num2);
public static native double Mul(double num1,double num2);
public static native double Div(double num1,double num2);
}
3.编译一下生成class!!(必须步骤)
4.使用javah命令生成C语言函数名
当然也可以自己生成就是比较麻烦容易出错格式如下:
Java_PkgName_ClassName_NativeMethodName,
以Java为前缀,并且用“_”下划线将包名、类名以及native方法名连接起来就是对应的JNI函数了。
Javah方法说明:
Javah -d :指定输出目录 为每个含有jni方法的java类 都生成一个头文件 生成文件存放到-d 后指定目录中
-o :为所以jni方法 生成一个头文件 并存放到 -o后的指定目录中
(-d/-o只能二选一)
-classpath
使用-classpath后JDK将不再使用CLASSPATH中的类搜索路径,如果-classpath和CLASSPATH都没有设置,则JDK使用当前路径(.)作为类搜索路径。
具体方法: 在Terminal中执行以下语句:
javah -d app/src/main/jni -classpath app/src/main/java/ -jni -v com.net.testjni.JNIUtils
执行命令后会自动创建一个jni目录 并且 生成一个.h命名结尾的文件
这样就生成了对应的C/C++代码的函数名
5.在jni文件夹下 编写C/C++文件(函数的名称使用上面步骤中生成函数名称)
6.在jni文件夹下 编写Android.mk和Application.mk文件 这两个文件是编译so时用到的脚本文件
Android.mk中内容如下:
LOCAL_PATH := $(call my-dir) #my-dir 表示当前文件夹,一般不用修改
include $(CLEAR_VARS) #这个配置需要但不需要修改
LOCAL_MODULE := JniTest #JniTest 就是命名so的名称如果不是lib开头编译器自动加上lib 即以lib+名称为so的名称
LOCAL_SRC_FILES := caclpwd.cpp #指定需要编译的C/C++ 文件include $(BUILD_SHARED_LIBRARY) #不需修改
Application.mk中内容如下
APP_PLATFORM := 25.1.8937393#必选,定义使用的ndk库函数版本号。
APP_MODULES := JniTest#指定需要编译模块名字
##APP_ABI := armeabi-v7a #编译so的平台,根据你的需求选择这些'armeabi','x86', 'armeabi-v7a', 'x86_64' 多个版本 中间空格隔开
APP_ABI:=all #生成所有so的平台
7.在app目录下创建CMakeLists.txt
内容如下:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.18.1)
# Declares and names the project.
project("jnidemo")
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library(# Sets the name of the library.
# 设置so文件名称.
JniTest
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/jni/cacl.cpp)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library(# Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries(# Specifies the target library.
# 制定目标库.
JniTest
# Links the target library to the log library
# included in the NDK.
${log-lib})
8.在build.gradle中 进行 ndk版本 和CMake的配置 :如下
// 在android节点下增加一下内容
// 指定CMakeLists.txt路径
externalNativeBuild{
cmake{
// 在该文件种设置所要编写的c源码位置,以及编译后so文件的名字
path 'CMakeLists.txt'
}
}
ndkVersion'25.2.9519653'
//在defaultConfig{} 节点下增加内容
// 增加cmake控制属性
externalNativeBuild{
cmake{
// 指定编译架构
abiFilters'arm64-v8a','armeabi-v7a','x86','x86_64'
}
}
9.编译一下在app/build/intermediates下会自动生成cmake文件夹
到此处 So文件生成成功
10.将so文件复制到 libs目录中 并在build.gradle(app) android 节点下中指定so文件路径
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
运行项目成功得到结果:
静态注册成功 !!