一、JNI简介
JNI = Java Native Interface,Java本地接口。
二、交织编译
在什么平台运行的软件就必要在什么平台举行编译,为什么Android可以在Windows下kaifa-并在手机的unix体系上运行呢?这是由于Java是运行在假造机上的。为什么说Java是一次编译到处实验?
交织编译:在一个平台下编译出另一个平台下可以运行的本地代码
- cpu平台 x86 arm
- 操纵体系平台 windows linux mac os unix
- 差别的cpu和差别的操纵体系所支持的指令集是不一样的,以是在哪个平台上的软件必要在哪个平台上举行编译。
三、NDK简介
NDK = native develop kit,本地开发工具集。
通过NDK来实现交织编译,NDK是Google提供的。
四、NDK集成开发流程(以cmake工程为例)
1、下载NDK
解压NDK的zip包到非中文目次
2、设置情况变量
根目次中有ndk-build.cmd文件,将根目次设置情况变量path中
3、在local.properties 中设置ndk根路径
ndk.dir=C:\Users\94317\AppData\Local\Android\ndk\android-ndk-r25b
4、在gradle.properties 中设置useDeprecatedNdk 属性
android.useDeprecatedNdk = true,作用是兼容老的ndk
现在,useDeprecatedNdk 已经不支持,改为cmake大概ndk-bundle
5、界说本地接口
public class JNI { /** * 界说本地接口 */ public native String stringFromJNI();}6、编写C++代码
在main目次下创建一个恣意名称的文件夹,好比cpp文件夹,在cpp文件夹中创建一个cpp文件,好比:native-lib.cpp,代码如下:
#include <jni.h>#include <string>using namespace std;extern "C" JNIEXPORT jstring JNICALLJava_com_nobug_jniproject_JNI_stringFromJNI(JNIEnv* env,jobject /* this */) { string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str());}extern "C":在编译时,模式是以C++11标准编译,不支持C语言的编译,以是必要添加 extern "C",可以或许让C和C++相互调用。
jstring:表示返回值是string范例
7、cmake设置
在cpp目次下新建cmake文件,文件名固定,不可修改: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("jniproject")# 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. jniproject # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). native-lib.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. jniproject # Links the target library to the log library # included in the NDK. ${log-lib})cmake_minimum_required:指定cmake的最小版本
project("jniproject"):cmake工程名称
add_library:添加库。jniproject:库名,SHARED:表示动态库
8、模块的build.gradle 下设置cmake
android { compileSdk 32 defaultConfig { // ... externalNativeBuild { cmake { abiFilters 'armeabi-v7a' cppFlags "-std=c++11 -frtti -fexceptions -Os -Wall" } } ndk { // "armeabi-v7a", "arm64-v8a" abiFilters 'armeabi-v7a' } } externalNativeBuild { cmake { path file('src/main/cpp/CMakeLists.txt') version '3.18.1' } }}cmake 指定c++11标准,而且cpu架构必要指定为 armeabi-v7a,如果不指定cpu架构,默认的cpu架构是:arm64-v8a
9、编译
编译之后天生 so 库:
10、加载动态库
public class JNI { static { // 导入动态库 System.loadLibrary("jniproject"); } ...}11、链接动态库
public class MainActivity extends AppCompatActivity { private ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); // Example of a call to a native method TextView tv = binding.sampleText; tv.setText(new JNI().stringFromJNI()); }}五、天生头文件
头文件代码如下:
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_nobug_jniproject_JNI */#ifndef _Included_com_nobug_jniproject_JNI#define _Included_com_nobug_jniproject_JNI#ifdef __cplusplusextern "C" {#endif/* * Class: com_nobug_jniproject_JNI * Method: stringFromJNI * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_nobug_jniproject_JNI_stringFromJNI (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif该文件可以资助步调员快速完成JNI接口的步调编写。
天生该文件只必要一个下令即可天生。
第一步:切换目次
cd .\app\src\main\java\第二步:拷贝Java本地接口文件的引用
复制出来的内容是:com.nobug.jniproject.JNI
第三步:实验下令天生头文件
javah com.nobug.jniproject.JNI六、快速创建JNI函数
除了使用 javah 天生JNI代码,还可以使用快捷键可以直接天生。
首先界说好native函数,按下快捷键 alt+enter,如下图:
选择"Create JNI function for xxxx",可以快速天生JNI代码。
[本章完...] |