android jni 開發流程

來源:互聯網
上載者:User

JNI
(Java Native Interface),即Java本地介面,是為java編寫本地方法和jvm嵌入本地應用程式的標準的應用程式介面。首要的目標是在給定的平台上採用JAVA通過JNI
調
用本地方法,而本地方法是以庫檔案的形式存放的(在WINDOWS平台上是DLL檔案形式,在UNIX機器上是SO檔案形式)。通過調用本地的庫檔案的內
部方法,使JAVA可以實現和本地機器的緊密聯絡,調用系統級的各介面方法。有的jvm來實現相容的二進位編碼本地方法庫。

 

簡敘步驟
      ·編寫帶有native聲明的方法的java類
      ·使用javac命令編譯所編寫的java類
      ·使用javah
java類名產生副檔名為h的標頭檔
      ·使用C/C++實現本地方法,並產生動態串連庫
      ·將庫檔案拷貝到java工程目錄下,運行java程式

 

1 建立java工程
在JAVA程式中,首先需要在類中聲明所調用的庫名稱,如下:
static {
System.loadLibrary(“lidptest”);
}

庫的副檔名字可以不用寫出來,究竟是DLL還是SO,由系統自己判斷。接著對將要調用的方法做本地聲明,關鍵字為native。並且只需要聲明,而不需要具 體實現。如下:
public native static void fn1(int i);
public native static int  fn2(void );
然後編譯該JAVA程式檔案,產生CLASS,再用JAVAH
命令,JNI
就會產生C/C++的標頭檔。
例如建立java檔案TestDel.java,內容為:

public class TestDel
{
    static
    {
        System.loadLibrary("lidp"); //庫名cjw
    }

    public native static void creFolder();
    public native static void delFolder1();
    public native static void delFolder2();
    public static void main(String[] args)
    {
        TestDel test = new TestDel();
  
        System.out.println("start create  Folder...");
        test.creFolder();
        System.out.println("create Folder finished.");
  
        long stime = System.currentTimeMillis();    
        //test.delFolder1();
          test.delFolder2();    
      long etime =System.currentTimeMillis();
    
        System.out.println(etime-stime);
    }
}
用javac TestDel.java編譯它,產生TestDel.class。
再用javah
TestDel,則會在目前的目錄下產生TestDel.h檔案,這個檔案需要被C/C++程式調用來產生所需的庫檔案。

2 產生動態連結程式庫
對於已產生的.h標頭檔,C/C++所需要做的,就是把它的各個方法具體的實現。然後編譯串連成庫檔案。
接上例子。我們先看一下TestDel.h檔案的內容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni
.h>
/* Header for class TestDel */
#ifndef _Included_TestDel
#define _Included_TestDel
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     TestDel
* Method:    creFolder
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_TestDel_creFolder
  (JNIEnv *, jclass);
/*
* Class:     TestDel
* Method:    delFolder1
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_TestDel_delFolder1
  (JNIEnv *, jclass);
/*
* Class:     TestDel
* Method:    delFolder2
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_TestDel_delFolder2
  (JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif

在具體實現的時候,我們只關心幾個函數原型 :
JNIEXPORT void JNICALL Java_TestDel_creFolder
  (JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_TestDel_delFolder1
  (JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_TestDel_delFolder2
  (JNIEnv *, jclass);
這裡JNIEXPORT和JNICALL都是JNI
的關鍵字,表示此函數是要被JNI
調用 的。如果java中申明的函數原型包含參數,例如int,那麼產生的標頭檔中變成jint,它是以JNI

中介使JAVA的int類型與本地的int溝通
的一種類型,我們可以視而不見,就當做int使用。其它參數類似。函數的名稱是JAVA_再加上java程式的package路徑再加函數名組成的。參數
中,我們也只需要關心在JAVA程式中存在的參數,至於JNIEnv*和jclass我們一般沒有必要去碰它。

好,下面我們使用dll具體實現這幾個函數(一個函數是建立目錄,另兩個是兩種刪除目錄的方法)。

意,本例是通過VS2005建立dll的,需要安裝"WebDeploymentSetup.msi", New一個工程選擇VC++建立win32
project,選中dll建立Empty
project。將java中產生的標頭檔拷貝至此工程添加,再建立新檔案test.cpp(必須以cpp尾碼,若以c尾碼則builder會出
錯)test.cpp代碼如下(注意這句#include "TestDel.h"):

#include <stdio.h>
#include <direct.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include "TestDel.h"

JNIEXPORT void JNICALL Java_TestDel_creFolder(JNIEnv *, jclass)
{
int i,j;
char buf1[20];
char buf2[20]="./Folder/";
char buf3[20];
mkdir("Folder");
for(i=0;i<100;i++)
{
    itoa(i,buf1,10);
mkdir(strcat(buf2,buf1));
strcpy(buf3,strcat(buf2,"//"));
for(j=0;j<100;j++)
{
  itoa(j,buf1,10);
  mkdir(strcat(buf2,buf1));
  strcpy(buf2,buf3);
}
strcpy(buf2,"./Folder/");
}
}

JNIEXPORT void JNICALL Java_TestDel_delFolder1
  (JNIEnv *, jclass)
{
int i,j;
char buf1[20];
char buf2[20]=".//Folder//";
char buf3[20];
for(i=0;i<100;i++)
{
  itoa(i,buf1,10);
  strcat(buf1,"//");
  strcpy(buf3,strcat(buf2,buf1));
  for(j=0;j<1000;j++)
  {
   itoa(j,buf1,10);
   rmdir(strcat(buf2,buf1));
   strcpy(buf2,buf3);
  }
  rmdir(buf3);
  strcpy(buf2,".//Folder//");
}

}
JNIEXPORT void JNICALL Java_TestDel_delFolder2
  (JNIEnv *, jclass)
{
  char   cmd[50];    
  strcpy(cmd,"rmdir /s/q ");
  strcat(cmd,"Folder");  
  system(cmd);    

}


意:一定要把SDK中的include文
件夾中(和它下面的win32檔案夾下的標頭檔)的幾個標頭檔拷貝到VC的include檔案夾中。或者在VS的tools/options
-〉Projects and Solutions/VC++ Project
Settings,修改directories中include的設定,把標頭檔../sdk1.5.0/inlcude 和
../sdk1.5.0/include/win32給包含進來。

編譯串連成庫檔案dll(在debug檔案夾中),注意名稱要與JAVA中需要調用庫名的一致,這裡可以修改為lidp.dll。

3 運行程式

把lidp.dll拷貝到TestDel.class的目錄下,java TestDel運行它,就可以觀察到結果了。這裡實現的功能是統計刪除檔案夾的時間。

 

java中有一種直接把c C++代碼轉換成java類的工具 swig 很方便。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.