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路径:

img

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)步,依然会有问题。)

img

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

img

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");
分类: JNI

0 条评论

发表回复

您的电子邮箱地址不会被公开。