android adt jni开发步骤
一、使用环境 1、windows32位操作系统2、ADT为adt-bundle-windows-x86-20131030 3、NDK为android-ndk-r9d
二、配置生成头文件.h
⒈首先,如图所示,点击External Tools Configurations...
⒉然后,如图所示,点击
⒊接下来,看图操作
最后点击Apply,然后 我们在一个android工程中新建一个class文件
三、配置build ndk,和上面类似,参考图中配置即可
创建C文件
创建Android.mk文件
创建Application.mk文件
最后 加载so的库文件 就可以把C语言的函数当Java函数使用了
编译结果:
Jni中数据类型对应关系
了解了jni的简单用法,我们再来进行深入的学习:首先使jni中Java基本类型和C基本类型的对应关系
访问Java中的域
使用C语言访问Java中的域和方法都要知道其Id,使用起来相对也比较复杂,在这里举一个简单的例子,假设我们的类People中有一个int类型的域age,即:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">package com.example.jnitest;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> People { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> age; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">getAge</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> age; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setAge</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> age) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.age = age; }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>
修改JniTest中的方法,这一次我们通过调用native方法使得age域变为原来的二倍:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.example.jnitest;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">JniTest</span> {</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">native</span> People <span class="hljs-title" style="box-sizing: border-box;">changeAge</span>(People people);}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>
重新生成头文件后再cpp文件中编写我们的方法,每次访问Java中的域我们需要得到FieldId才可以,其步骤为:
1. 获取隐式参数的类
2. 获取域Id
3. 访问域的值
<code class="hljs scala has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">#include<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"jni_hello.h"</span>JNIEXPORT j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">JNICALL</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Java_com_example_jnitest_JniTest_changeAge</span></span> (JNIEnv *env, j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">cl</span>, <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">jobject</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ob</span>){</span> j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">cl_people</span> = <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">GetObjectClass</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(ob)</span>;</span> jfieldID c_ageId = env->GetFieldID(cl_people, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"age"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"I"</span>); jint c_age = env->GetIntField(ob,c_ageId); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//打印修改之后的语句</span> printf(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%d"</span>, c_age); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//修改age域</span> env->SetIntField(ob, c_ageId, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>*c_age); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> ob;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>
env->GetFieldID方法中的第二个参数表示该域的名称,第三个参数表示该age域的类型为int,这个jni的编码签名有关,稍后会提到。接下来在main方法中调用:
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">package com.example.jnitest;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> Main { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span>{ System.loadLibrary(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"JniApplication"</span>); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(String[] args) { People people = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> People(); people.setAge(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>); people = JniTest.changeAge(people); System.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">out</span>.println(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"changed::"</span>+people.getAge()); }}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>
输出结果:
可以看到,结果变为原来的2倍。对于访问静态域时只需更换env->GetIntField为env->GetStaticIntField即可。
访问Java中的方法
刚刚我们使用了访问域的方法去修改了域的值,下面我们在cpp文件中调用People类下的setAge方法修改age的值;调用Java的方法需要按照以下步骤:
- 获取隐式参数的类
- 获取方法Id
- 进行调用
<code class="hljs scala has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">#include<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"jni_hello.h"</span>JNIEXPORT j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">object</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">JNICALL</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Java_com_example_jnitest_JniTest_changeAge</span></span> (JNIEnv *env, j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">cl</span>, <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">jobject</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ob</span>){</span> j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">cl_people</span> = <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">env</span>-><span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">GetObjectClass</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(ob)</span>;</span> jfieldID c_ageId = env->GetFieldID(cl_people, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"age"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"I"</span>); jint c_age = env->GetIntField(ob,c_ageId); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//第三个参数同样和编码签名有关</span> jmethodID c_setAgeId = env->GetMethodID(cl_people, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"setAge"</span>,<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"(I)V"</span>); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//void表示了返回类型,若返回为int,则调用CallIntMethod</span> env->CallVoidMethod(ob,c_setAgeId,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>*c_age); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> ob;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>
在main函数中调用,代码同上,结果如下:
对于static方法的调用,我们只需要将调用时的方法更换就好,例如setAge方法为static的话,只需将 env->CallVoidMethod(ob,c_setAgeId,2*c_age);更换为 env->CallStaticVoidMethod(ob,c_setAgeId,2*c_age);即可。
Jni编码签名
在前面我们提到了env->GetFieldID方法中的第三个参数用编码签名来表示了该域的数据类型,现在来介绍一下jni中数据类的对应关系。
- 基本数据类型:
B——byte, C——char, D——double, F——float,
I——-int , J——long, S——short, V——–void , Z——boolean - 数组类型,在开头加“[”来表示,如int[] 数组为“[I”;二维数组int[][] 即为“[[I”
- 类类型,以“L+完整包名+类名+;”表示其中所有的“.”换为“/”,如com.example.jnitest.People类表示为Lcom/example/jnitest/People;
关于方法的编码签名规则是,“(传入参数类型的编码签名)+返回参数类型的编码签名”,多个传入参数之间直接相接就好;例如我们的setAge方法中传入参数为int,返回为void,则表示为“(I)V”。
好了,上面就是是用eclipse快速开发JNI的方法了,你学会了吗?
参考文章:
http://blog.csdn.net/smbroe/article/details/44133741
更多相关文章
- Android(安卓)启动 Activity和一键退出应用的的最佳方法
- Android(安卓)Studio 入门
- Glide框架V3版本和V4版本区别
- 查看Android源码的版本方法
- java泛型操作复习,以及讲解在android中使用的场景
- 三种自定义漂亮的Android(安卓)SeekBar的方法
- Android(java)学习笔记89:泛型概述和基本使用
- Android使用ActivityLifecycleCallbacks管理Activity和区分App前
- 深入了解Android图形管道-part1