当前位置:网站首页 > Java教程 > 正文

android java jni 教程



   一定要下载demo,动手动脑,结合本篇博客来跑demo,否则看了也还是不会;写代码还是要勤动手才能掌握,否则里边的坑也只是想当然
demo

NDK的基础知识,强烈推荐小楠总的NDK系列博客,先拜读一遍,照着学习还是很厉害的

      JNI:是java和c/c++交互的桥梁;有必要去弄明白整个开发流程;jni的效率比java要快,所以一些好性能的都会通过走底层来调用java
    用途:用的比较多的是视频、美颜、相机、地图等涉及底层以及效率问题
    NDK:是一针对jni中的工具包,包括底层c库、编译工具等
              1. 编译
   xxx.c ——> windows .obj ; Linux .o –》 语法检查
 2. 链接:将函数之间的关系链接起来,生成一个静态或动态库文件(可执行文件)
                  .o —–> log.so .dll .exe
  静态库:静态链接是指把要调用的函数或者过程链接到可执行文件中,成为可执行文件的一部分,已经整合进去了
  动态库:装入过程中将所有动态链接库载入内存。应用程序在运行时,将所有可能要运行到的模块都全部装入内存(共享内存),
  动态链接过程只是把需要调用的函数的路径做个标志(类似于头文件声明),直到运行用到函数时才会从内存载入
  
  jvm 是虚拟机内存,C/C++ 是 native内存,并且这个 so库 是放在 apk 的 lib 下面的
  当我们调用 java中native声明的javaDiff()方法 的时候会到 Java虚拟机 的内存当中来处理找这个方法,
  而加了 native 关键字的时候他就会去到 C++/c 的堆栈空间找这个 C++/c 的实现。
 jni开发中如果不是作为外部库或.c文件的函数不对外,则可以不生成.h头文件,头文件的声明只是想把当前.c/.cpp文件下的功能提供给外部文件使用,如:demo只有一个.c文件,函数定义  都是可以直接调用的,不需要声明;但是要是作为第三方库且库中的函数对外开放,则必须要有对应.c的头文件.h,否则无法调用相应的函数;
即:不管动态还是静态注册,只要不是对外(.c文件之间以及库和库之间)提供的函数功能,则不需要生成头文件;
demo将分开来说,只要按照以下说的步骤,就能清楚知道静态注册、动态注册以及so库对外的函数会在当前JNI函数中被调用的情况。
期间会涉及到修改cmakeList.txt脚本,所以每次修改后,都要同步gradle和重新build--->makeProject(先删除build)

这里也会分两种方式说明:
一、不验证so库,直接gradle,build之后,运行:主要是验证jni的方法是否正确,算是调试吧
二、验证so库
      验证so库的整个过程:
 想要只测试so库,需要将验证的so库放到jniLibs指定的目录,然后将build.gradle中相应的所有的cmake都注释掉如下
 externalNativeBuild {
          cmake {
          }
     }
      然后删除build以及.externalNative目录,再者gradle同步,其次build-->makeproject,最后运行,能正确调用相应的jni  的函数

 在c、c++中叫函数 java中叫方法,实际上两个是一样的玩意,这里为了区分jni和native所以有两个叫法

     1、静态注册

          1) . 静态注册的流程
 
 

      2、动态注册

             大概就是当java中通System.loadLibrary(name);时会调用JNI_OnLoad()函数,所以在这函数中将java中native方法         声明和jni函数实现进行注册,也就是绑定(声明-实现)
            生成动态so库的链接: 动态注册
            代码如下:
            
 
  
      注意gMethod数组和registerNatives(env)函数,重点是在注释;看懂流程才是重点;
      这里流程是System.loadLibrary()-->JNI_onLoad()-->registerNatives()--->RegisterNatives(...)
      一定要看注释,这个流程中registerNatives(env)中,注意这个参数值,是java中的具体类的路径名,只是将"."换成“/”
//这个是具体的类名,不能写错,写错就无法注册成功,也就无法调用jni函数了 clazz = (*engv) -> FindClass(engv, "com/jni/www/jnidemo/dif/JNIDynamicUtil");
    生成并验证so库
    
 
 
动态注册是需要JNIDynamicUtil类的具体路径才能进行动态注册的,所以如果要封装成第三发so库供给第三方使用,需要写一个工具类统一管理native的注册,然后将这个工具类做成jar包,将jar包和so供给第三方使用;(这只是个人看法,没有具体实施,希望有知道怎么做的,能不吝赐教)

注:不管是静态注册还是动态注册:都必须遵循 java的类名包名方法名和jni的函数一一对应
如:
       静态注册:不管so库是不是在不同的项目中使用,都必须保证java中使用声明native的方法的类必须和JNI函数命名规则            保持一致:即java_包名_类名_方法名

       动态注册:由于动态注册也是要通过java类中的绝对路径来找到类中的class,才能进行映射;如代码中

   3.so库链接

若是要引用第三方so库的话需要将第三方的头文件和当前的so库建立关系

快速获取头文件的方式:

http://blog.csdn.net/wang_zhi_hao/article/details/


归根结底都是通过命令 javah -d jni -jni -classpath class的路径生成


如:


javah -d jni -jni -classpath  

C:UsersAdministratorDesktopJNIDemoappbuildintermediatesclassesdebug   com.jni.www.jnidemo.JNIUtil

会在当前目录下创建jni目录(没有的话),并将自动生成.h头文件在jni目录下,


注意此时的头文件是整个是:包名_类名.h 一定要改成和.c文件一样的文件名;此外还要.h头文件的函数声明也要和.c对应上,尤其是动态注册的函数一定一定要一一对应上,否则很容易报找不到方法


如果想要jni中调用第三方的so库,那么需要通过书写cmakeLists.txt脚本关联jni与第三方的so库,编写好之后build就可以是掉第三方so库的方法了;

如:在cmakeList.txt中加入,其中jni是存放头文件的目录

set(distribution_DIR ${CMAKE_SOURCE_DIR}/jni)
#加入头文件:第三方的so库的头文件加入编译到native-lib.so中,native-lib.so中才能使用它里边的函数
#参数是头文件所在的目录
target_include_directories(native-lib PRIVATE ${distribution_DIR})

具体用法可以参考:


文档地址:

https://developer.android.com/ndk/guides/cmake.html


build.gradle脚本中配置externalNativeBuild{}中的信息可以查看: 

app.externalNativeBuildcmakedebugarm64-v8acmake_build_command.txt,这里有build之后的具体信息

比如:


查询文档可以知道 arguments 中 -DANDROID_PLATFORM 代表编译的 android 平台,


文档建议直接设置 minSdkVersion 就行了,所以这个参数可忽略。


另一个参数 -DANDROID_TOOLCHAIN=clang,


CMake 一共有2种编译工具链 - clang 和 gcc,gcc 已经废弃,clang 是默认的。


    流程:
     
   可能频繁出现的异常 
   
 
 

cmakeLists.txt:
生成静态库和动态库:区分于静态注册和动态注册:库是将函数打包成动态库,注册是函数注册,两者概念没关系
  
 
 
 
总结:
     
 
 
demo

以下以下强烈推荐一篇博客:cmake的手册文档、ndk的手册文档在这篇博客都有讲解,会更新cmake的讲解
http://mp.weixin..com/s/QTxEQg4s5ummtFNe8vRIvA

 CMake 的官方文档使用。

https://cmake.org/documentation/

同时在这推荐一个中文翻译的简易的 CMake手册

https://www.zybuluo.com/khan-lau/note/

  • 上一篇: java 教程 string
  • 下一篇: 阜阳java教程咨询
  • 版权声明


    相关文章:

  • java 教程 string2025-03-21 12:42:04
  • 英文java教程2025-03-21 12:42:04
  • java系统架构师教程2025-03-21 12:42:04
  • 长沙java笔记教程2025-03-21 12:42:04
  • java编程教程大全2025-03-21 12:42:04
  • 阜阳java教程咨询2025-03-21 12:42:04
  • java架构精品教程2025-03-21 12:42:04
  • java教程w3c2025-03-21 12:42:04
  • java158教程2025-03-21 12:42:04
  • java嵌套教程2025-03-21 12:42:04