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

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