有关NDK配置的教程大多数的配置都是在app中直接实现,但实际项目中如此混杂开发会引发项目的管理混乱等问题,可以考虑在Module中,利用JNI去统一封装实现。
一、配置
配置主要为安装NDK库、CMacke插件等,本文不作说明。
二、实现步骤
2.1 创建Java类
package com.ganahe.routealglib;
/**
* @brief: JNI Test
*
* @auther: GanAHE
* @date: 2022/3/20
*/
public class JNITest {
static {
System.loadLibrary("pilotGSO");
}
/*
public static void main(String args[]){
JNITest jniTest = new JNITest();
System.out.println(jniTest.jniGet());
jniTest.jniSet("hello world");
}*/
public native String jniGet();
public native void jniSet(String str);
}
pilotGSO
为即将生成的so库名。
native类型的方法即为JNI中实现的方法。
随后通过javac生成JNI所必须的头文件:
(1)在Module根目录中打开终端Terminal、PowerShell或命令行CMD,根据上一步创建的java类路径键入命令javac path/JNITest.java
:
示例: javac main/java/***/JNITest.java
此步骤将生成JNITest.class文件;
(2)进入到java文件所在位置,输入javac -encoding utf8 -h . JNITest.java
;
(3)此时会得到包名_包名+JNITest.h
的头文件,示例如下:
com_ganahe_routealglib_JNITest.h
2.2 C/C++示例编写
新建test.cpp文件,内容如下:
//
// Created by dingg on 2022/3/20.
//
#include "include/com_ganahe_routealglib_JNITest.h"
#include<cstdio>
extern "C" {
JNIEXPORT jstring JNICALL Java_com_ganahe_routealglib_JNITest_jniGet(JNIEnv *env, jobject thiz) {
printf("invoke get in c++\n");
return (*env).NewStringUTF( "Hello from JNI!");
}
JNIEXPORT void JNICALL
Java_com_ganahe_routealglib_JNITest_jniSet(JNIEnv *env, jobject thiz, jstring string) {
printf("invoke set in c++\n");
char *str = (char *) (*env).GetStringUTFChars(string, NULL);
printf("%s\n", str);
(*env).ReleaseStringUTFChars( string, str);
}
}
根据自己的头文件所在位置与cpp文件的位置自行引入头文件。
说明:
JNIEnv*:表示一个指向JNI环境的指针,可以通过它来访问JNI提供的接口方法
jobect:表示Java对象中的this
2.3 CMake文件编写
在Module根目录下新建CMakeLists.txt文件,根据cpp在Module的路径配置如下:
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
PilotGSO
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/***/test.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.
PilotGSO
# Links the target library to the log library
# included in the NDK.
${log-lib} )
src/main/***/test.cpp
需要替换为自己项目的文件路径,PilotGSO即为要生成的so文件名。
2.4 构建与引用
本次构建gradle版本为4.0,
在当前Module的build.gradle中加入:
android {
--xxx代表省略的默认生成代码--
ndk{
abiFilters "arm64-v8a","armeabi-v7a"/*,"armeabi"*//*,"x86"*/
}
externalNativeBuild{
cmake{
cppFlags ""
abiFilters 'armeabi-v7a',"arm64-v8a"
}
}
}
externalNativeBuild{
cmake{
path "../routeALGLib/CMakeLists.txt"//编译后so文件的名字
}
}
}
在app的build.gradle引入该module:
implementation project(":routeAlGLib")
完成后点击Android studio上的Make Project,开始构建生成,随后在app中调用测试:
findViewById(R.id.appCompatImageView3).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
JNITest jniTest = new JNITest();
Toast.makeText(getApplicationContext(),"Click Me to Link JIN." + jniTest.jniGet(),Toast.LENGTH_SHORT).show();
}
});
Comments NOTHING