目录
1.什么是jni
jni:java native interface,java本地开发接口,是JAVA和C互相调用的桥梁。
2.jni有什么用
1)硬件操作 :java语言不可以直接操作硬件,但是C可以,通过JNI,JAVA也就能操作硬件。 JAVA操作硬件的API,基本上都是由C和C++去写的,然后由JNI实现JAVA去调用。比如android系统框架,底层是libc,然后上层就是framework和应用层,libc层和上层就用到了JNI技术。
2)算法复用:用C写算法然后编译成so库,然后java来调用。比如著名的音视频编解码库FFmpeg就是 用C写的,java如果要使用这个库,就得将FFmpeg编译成so库然后调用。
3.如何学习jni技术
1)学习路线:熟悉C语言、Java语言、Android开发。
这里公布一下我以前写的JNI技术培训的手册的百度网盘连接,手把手教你搭建环境,开发第一个jni demo:
链接:https://pan.baidu.com/s/1DsbioKZ0x554fo8oiWeoAw
提取码:atzi
上面的手册涵盖NDK环境搭建、JNI Demo编写、so库打包等详细流程
#补充
Mac下 AndroidStudio 配置javah 命令:https://blog.csdn.net/lw0328/article/details/78754682
android studio 4.1 javah tools配置不一样:https://blog.csdn.net/qq_25421571/article/details/115094901 $ModuleFileDir$应变成$SourcepathEntry$
2) 学习的核心
熟练掌握C语言、Java语言、JNI语法
4.关于一些坑总结
1)编译问题
1.跨平台编译的问题
一定要在哪个平台(操作系统32位还是64位)上使用,就在哪个平台(操作系统)上编译。比如CentOS上编译的so库不能在Ubantu上使用,可能会报错。
is 32-bit instead of 64-bit动态库错误分析
https://blog.csdn.net/hnkwei1213/article/details/53843460
如何判断android手机是32位还是64位?
https://blog.csdn.net/qq_37858386/article/details/78905342
2.使用非常旧版本的ndk编译的问题
公司有个要求使用,使用ndkr9d去编译so库,然后给android4.4 5.1系统上的应用使用。
我的Windows AndroidStudio是最新的3.5.X版本,然后下载好windows版本的
ndkr9d,通过绑定一下ndk路径:
ndk-bundle是集成了各个ndk版本的集合体,这里改成ndkr9d。不出意外会报下面的错误:
Parameter specified as non-null is null: method com.android.build.gradle.internal.cxx.configure.JsonGenerationVariantConfiguration., parameter ndkVersion
按照https://forum.cocos.org/t/android-studio/70658的说法,我开始误入歧途:改完后按照as提示又将cmake由3.6升级到3.10,然后打包armbi-v7a报新的错误:
No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
然后按照https://blog.csdn.net/hewenlee/article/details/83780990提示下载 mips64el-linux-android 放到ndk的toolchains下又会报新的错误,源源不断.....
最后,不断的尝试才找到解决办法:
1)ndkr9d依然正常绑定到ndk的路径
2)项目的gradle.properties配置android.useDeprecateNdk=true
3)把app下的build.gradle的externalNativeBuild注释掉,他会继续指定cmake的版本为3.10.2,而实际上ndkr9d对应的cmake不能这么高。(很多博客上都只有第2)步,依然会有问题。)
2)so引用问题
将 so 库的工具类拷贝到当前项目,注意工具类的包名不能变,必须和 so 库源码中的包 名保持一致。 这个,上面的手册我已经说明十分清楚。
如果包名不一致,就会报类似下面的错:
No implementation found for java.io.FileDescriptor method_xx(java.lang.String, int, int) (tried Java_com_juli_doneserialport_serial_SerialPort_open and Java_com_juli_doneserialport_serial_SerialPort_method_xx__Ljava_lang_String_2II)
4.JNI里如何打印日志
https://www.cnblogs.com/kebibuluan/p/7065213.html
1.修改jni工程的gradle
2.引入头文件并定义相应的宏
最好可以将下面的代码再封装成一个.h文件,然后引用就行。
// 引入log头文件
#include
// log标签
#define TAG "JNI层日志11111111"
// 定义info信息
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)
// 定义debug信息
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
// 定义error信息
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)
3.按照C语言打印的方法打印即可
LOGE("lenResult:%s", "XXXXXXXXXXXXXXXXXXXXXXXX");
0 条评论