AndroidStudio2.2 cMake方式创建jni工程

千金一刻莫空度,老大无成空自伤。这篇文章主要讲述AndroidStudio2.2 cMake方式创建jni工程相关的知识,希望能为你提供帮助。
关于CMake:从androidStudio2.2版本开始,可以用cmake方式创建jni工程。

打开androidStudio之后按照以下步骤:
1)File-New-New Project , 注意勾选支持c++。然后一路next一直到finish。

AndroidStudio2.2 cMake方式创建jni工程

文章图片

 

2)我这里出现一个编译问题;(如果没遇到这个问题,跳过此步骤)
AndroidStudio2.2 cMake方式创建jni工程

文章图片

 
这个是因为新创建的工程,没有默认的NDK配置;配一下即可。操作如下:
右键工程名,选open Module Setting 打开这个:
AndroidStudio2.2 cMake方式创建jni工程

文章图片

然后注意红色标记。配置好你的NDK路径,我用的是14b这个版本。
点OK,然后androidStudio会自动编译。
3)观察一下自动生成的这些代码;
AndroidStudio2.2 cMake方式创建jni工程

文章图片

这里有一个自动生成的MainActivity.java 红色标记的地方,就是调用的JNI。
下面的System.loadLibrary就是加载名为native-lib.so的引擎文件(cmake方式下,在工程中看不到这个文件,但是编译出来的apk是有的)
上面的native方法,就是在java代码中声明,jni层有这么一个方法的实现。
左边画圈圈的 ,点一下
AndroidStudio2.2 cMake方式创建jni工程

文章图片
(或者鼠标放在方法名上面,按住ctrl,点鼠标左键),就能直接索引到cpp文件中,这个方法的具体实现。如下图。
AndroidStudio2.2 cMake方式创建jni工程

文章图片

 

第一次看到这个文件可能有点陌生,下面贴出重要代码的注解;
#include < jni.h> #include < string> extern "C" //这一句,表示,按照C的方式去编译,如果不加这句,可能导致找不到这个方法 JNIEXPORT jstring JNICALL //这一句,表示,返回值是一个java的string,至于JNIEXPORT ,JNICALL都是JNI的语法 Java_test_hank_com_jni1011_MainActivity_stringFromJNI( // 这句,表示这个是实现JAVA类中的一个方法,java类的全名是test.hank.com. //jni1011.MainActivity,方法名为stringFromJNI JNIEnv *env,//指针对象 jobject /* this */) { std::string hello = "Hello from C++"; //创建string 对象,std::的写法,std是c++标准库,两个冒号之后,加上string,是说这个类是c++标准库内的string类。用这个类来创建一个string对象 return env-> NewStringUTF(hello.c_str()); //返回值 ,由于env是指针对象,所以要用-> 来调用方法,NewStringUTF() 构建一个UTF编码的字符串 }

运行工程,就能看到界面中间显示一行字符串“Hello from C++”;这行字符串明显来自jni层。
android给我们创建示例工程的时候,只告诉我们怎么用java调用jni。但是jni回调java的过程,需要我们手动修改代码。
4)手动修改代码,来实现jni层调用c++层的代码;
1-新建一个java类:JavaCaller.java ,并创建一个方法,表示这个就是让jni层去调用的方法。
AndroidStudio2.2 cMake方式创建jni工程

文章图片

 

2-jni调用java某个对象的方法,也要遵循面向对象的方式,必须有该对象的引用才行。所以我们要先传递一个对象到jni层。
看代码。
在java层,新建一个native方法,setJavaObject,参数为JavaCaller类的一个对象。
AndroidStudio2.2 cMake方式创建jni工程

文章图片

 

鼠标放在方法名上,按住alt+enter,就会提示,创建一个jni方法,作为这个native的实现。
选择创建该方法,(这里有个坑,自动生成的这个方法,没有extern "C" 导致编译通不过,大概原因就是加了extern "C",就表示用c的方式去编译,jni对接的应该还是c,所以要加上extern "C")
然后写代码调用这个setJavaObject方法。
接下来继续进入jni层,这里,我们的目的是jni层调用java类的某个方法。
所以,要在jni中写代码来使用传递进来的这个java对象。
代码如下,有每个步骤的详细注解:
AndroidStudio2.2 cMake方式创建jni工程

文章图片

这样的话,调用过程就执行完毕了。
执行代码,就会发现,日志中有这一行。
10-11 04:23:51.112 4254-4254/test.hank.com.jni1011 D/hankzhou: param:这里能不能放中文? - param2:真的可以放中文耶
这个就是我们在JavaCaller.java test方法中打印的日志。说明,jni回调java的方法成功。
至此,AndroidStudio - cMake方式开发jni的示例就完成了。
但是,有两点需要说明一下。
1)java的类型 转化为jni的类型存在有规律的转化(观察一下java层的native方法,以及jni层的c方法,两者的参数列表。有关联,但是写法大不相同)

AndroidStudio2.2 cMake方式创建jni工程

文章图片

 

很抽象?那么看图吧。
这是java的:
AndroidStudio2.2 cMake方式创建jni工程

文章图片

 
这是jni的:
AndroidStudio2.2 cMake方式创建jni工程

文章图片

 
jni前面的两个是干啥的暂时不知,但是很明显能看到3个参数都是string,到了jni这里,就变成了jstring,这就是所谓写法上的转化。
2) jni回调java对象的某个方法,也是有类型转换的;
AndroidStudio2.2 cMake方式创建jni工程

文章图片

还是看图:
java的方法:
AndroidStudio2.2 cMake方式创建jni工程

文章图片

jni中用反射创建该方法:
AndroidStudio2.2 cMake方式创建jni工程

文章图片

 

这里的实参,test 是方法名,保持一致。
形参以及返回值,必须完全对应,这里就有一个类型转换了。
先看最后这个V,对应test方法的返回值void。
前面的两个 Ljava/lang/String; 对应两个string。(多个参数,分号分隔)
这里是void和string,那么如果是其他类型呢?参见了上面的表格。
 
以上就是cMake方式开发jni的入门级指导。更复杂的,以后再写。
【AndroidStudio2.2 cMake方式创建jni工程】


    推荐阅读