这里写自定义目录标题
- Android JNI编程并生成so库
- Android Studio配置
- 下载配置NDK
- 配置NDK路径
- 编写native方法和c文件
- 编写配置文件生成so库
- 使用so库
Android JNI编程并生成so库
你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
Android Studio配置
下载配置NDK
下载NDK: 点击如下按钮,或者在 File->settings->Android SDK->SDK Tools中检查NDK是否下载,如果没有就需要下载并配置一下,除了需要NDK之外,还需要下载LLDB、CMake这两个编译工具。
配置NDK路径
local.properties文件或者 file -> project Structure ->Sdk Location 配置好androidNDK;
编写native方法和c文件
编写Native接口方法: 编写一个java类,并在Java文件中声明native方法。
public class NdkTools {
public static native String getStrFromNative();
}
点击build中的make project编译一下项目,获取对应的class文件:app->build->intermediates目录下,
在AS的Terminal面板下,进入到路径/app/build/intermediates/javac/debug/classes下,执行javac -h -jni com.example.test2.NDKTools (com.example.test2是自己的包名)生成.h文件,生成完毕之后如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_test2_NdkTools */
#ifndef _Included_com_example_test2_NdkTools
#define _Included_com_example_test2_NdkTools
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_test2_NdkTools
* Method: getStrFromNative
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_test2_NdkTools_getStrFromNative
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
在工程main目录下创建目录命名为jni,将刚才生成的.h文件剪切过来,在jni目录下新建一个c文件,命名为ndktest.c,如下图:
写ndkdemotest.c文件如下:
#include "com_example_test2_NdkTools.h"
JNIEXPORT jstring JNICALL Java_com_example_test2_NdkTools_getStrFromNative
(JNIEnv *env,jclass NDKTools){
return (*env)->NewStringUTF(env,"Hello World,this is Ndk");
}
新电脑,所以中间遇到个问题说一下:1,jdk环境变量配置好;2,javah 命令在java高版本上已经被javac -h替换,有些同学可能会遇到javah命令找不到的错误;
编写配置文件生成so库
在jni目录下新建Android.mk和Application.mk文件,这两个文件是编译so时用到的脚本文件。配置选项不多,根据我们的需求进行配置,这里的配置尽量选择少一点,根据我下面的注释修改的脚本文件。
android.mk
LOCAL_PATH := $(call my-dir) #my-dir 表示当前文件夹,一般不用修改
include $(CLEAR_VARS) #这个配置需要,但是不用做修改
LOCAL_MODULE := ndktest-jni #ndktest-jni就是命名so的名称,如果不是以lib开头,编译后的so文件名会以lib+文件名作为so名称
LOCAL_SRC_FILES := ndktest.c #指定需要编译的c++/c文件
include $(BUILD_SHARED_LIBRARY) #这个不用修改
Application.mk
APP_MODULES := ndktest-jni #指定需要编译模块名子
APP_ABI := armeabi-v7a #编译so的平台,根据你的需求选择这些'armeabi','x86', 'armeabi-v7a', 'x86_64'
添加ndktest.c文件
#include "com_example_test2_NdkTools.h"
JNIEXPORT jstring JNICALL Java_com_example_test2_NdkTools_getStrFromNative
(JNIEnv *env,jclass NDKTools){
return (*env)->NewStringUTF(env,"Hello World,this is Ndk");
}
编译c++:到terminal中切换到jni目录,执行ndk-build;
D:\workspace\Test2\app\src\main\jni> ndk-build
ndk-buil命令结束之后,会在libs目录中出生成对应平台的so文件,这里我只配置了armeabi-v7a这一种格式。
现在编译so的过程就完成了,接下来就是使用so了。
使用so库
首先需要在gradle里面配置so文件的目录,如果不指定jniLigs.srcDirs, 会报找不到so的错误。
在//在Android{}里面配置如下。
sourceSets.main{
jni.srcDirs = []
jniLibs.srcDirs = ['src/main/jniLibs']
}
接着就是编写我们的使用代码了,代码如下 ,需要注意的是,我们在加载so文件的时候,前缀“lib”不需,直接使用我们命名的文件名就可以了
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.toolbar)
val navController = findNavController(R.id.nav_host_fragment_content_main)
appBarConfiguration = AppBarConfiguration(navController.graph)
setupActionBarWithNavController(navController, appBarConfiguration)
binding.fab.setOnClickListener { view ->
//使用native方法的地方
Snackbar.make(view, NdkTools.getStrFromNative(), Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
// Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
// .setAction("Action", null).show()
}
}
运行之后如图: