一、使用环境 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的方法需要按照以下步骤:

  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>      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

更多相关文章

  1. Android(安卓)启动 Activity和一键退出应用的的最佳方法
  2. Android(安卓)Studio 入门
  3. Glide框架V3版本和V4版本区别
  4. 查看Android源码的版本方法
  5. java泛型操作复习,以及讲解在android中使用的场景
  6. 三种自定义漂亮的Android(安卓)SeekBar的方法
  7. Android(java)学习笔记89:泛型概述和基本使用
  8. Android使用ActivityLifecycleCallbacks管理Activity和区分App前
  9. 深入了解Android图形管道-part1

随机推荐

  1. Android(安卓)生成Release版本时,混淆问题
  2. android 巨坑 Received close_notify dur
  3. Android中链接到百度进行搜索
  4. Android适应方案汇总(三)
  5. Android(安卓)自定义控件圆形图案
  6. android系统进程重要等级
  7. Android:Handler中的Idle Handler
  8. android轻量框架六__Title文字淡入和淡出
  9. Android(安卓)Bitmap变迁与原理解析(4.x-8
  10. Winow&WindowManager