JNI编程配置

AS支持JNI编写方法有两种,一种是用ndk-bundle,另一种是Cmake,推荐使用Cmake方式进行编写JNI,因为AS本身支持,在编写JNI的时候会有提供语法提示和各种调试,而ndk-bundle则没有,像写文档一样,没有任何的提示,会麻烦很多(可能是AS版本问题)。
    还有一个注意点就编写JNI的时候,AS版本最好更新成高版本,否则可能会不支持或者支持程度不太友好。

两者的区别
ndk会自动帮我们实现Android.mk,还有一些配置,开发者只需要设置好ndk的路径和设置使用ndk编译的权限就可以了,无论添加多少个cpp文件都会自动帮你管理并生成好对应so库。
而Cmake方法是AS本身自己提供支持的C++编译的手段,这个感觉更加简单,AS已经提供专门的cpp文件夹供给开发者进行cpp文件创建,需要做的就是当我们创建多个cpp的时候,需要在CmakeList.txt中添加源文件的路径。


一.JNI配置
    1.ndk方式配置
            
        首先创建好native方法,在JNI里面进行方法实现
     JNI编程配置JNI编程配置
        
        ②在调用的地方加载so库
    JNI编程配置

          ②在app中的build.gradle中的defaultConfig中进行配置ndk,其中moudleName与第二步中的名字一致,abiFilters则是生成类库的各种CPU平台类型,armeabi,armeabiv7,x86这几种。 但是有一个奇怪的BUG,就是一旦加入另外两种一起生成so库的时候就会报错。
           所以只保留armeabi类型

                JNI编程配置
        
            ③在gradle.properties中添加android.useDeprecatedNdk=true,相当于开启ndk编译的权限。


                    JNI编程配置

             ④local.properties中设置好NDK的路径(一般而言AS会自动设置好)

                JNI编程配置
    
    
                2.Cmake方式配置

              这种方法基本是不用做什么东西的,除了一个通用的编译步骤,其余的只创建工程,AS已经直接帮你搞定
              
                只需要在创建工程的时候把这个支持C++的功能打钩即可,当然就是要创建好native方法。
        
JNI编程配置

            3.JNI,两者通用的步骤(必须的)

                将包含有的native方法的class进行编译,生成对应的.h文件

                首先点击AS Terminal,即是类似cmd的编译窗口,然后进入到java目录,javah acc.gonsin.com.ndkdemo.JniReceiver
                确定生成对应的.h文件。
               
                    JNI编程配置
                    
                
                
                
                然后新建cpp,把.h文件里面的内容复制到cpp中,并修改参数之类的,然后就可以编写C++
                
                最后Rebuild一下生成so库



                NDK生成的so库位置

  JNI编程配置
                    


               Cmake生成的so库位置

              JNI编程配置

                

            4.JNI调用(java调用c++方法)
            
                前面的步骤都完成以后,调用就简单了
                直接new类对象直接调用即可


            

  二.JNI代码编写规则
        除了C++本身的语法以外,jni本身编写也是有规则语法的

          JNI的引用关系表(java<——>JNI)
JNI编程配置
  

              1.c++调用java方法
               原理则是通过java的反射还获取到java工程中对应的方法
                
               ①首先先通过Findclass获取类
            JNI编程配置


                       然后根据方法名来获取menthodID,最后一个参数是方法的类型签名,括号里的就是参数,括号外的表示方法返回类型
                    比如方法 boolean method(String str , int i)   签名就是(Ljava/lang/String;I)Z
                
                 JNI编程配置
                    

            ③最后调用方法
                
                调用静态方法(Void类型)  env-> CallStaticVoidMethod(类,方法ID,参数1,参数2......)
                调用非静态方法(Void类型) env-> CallVoidMethod(类,方法ID,参数1,参数2......)


注意点   
    C++调用JAVA方法如果忽然闪退,但没有任何报错信息,那么就很可能是调用的时候传参数有错误。             

                    

                JNI本身还有一些方法,比如常用的jstring类型转char*类型或者char*转jstring
                      jstring str = env->NewStringUTF(msgbuf);    char*转jstring
                const char* message = (char*)env->GetStringUTFChars(msg,0);  jstring类型转char*