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的方法需要按照以下步骤:

  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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章