android JNI 簡單demo(2)之JNI demo 編寫

android JNI 簡單demo(2)之JNI demo 編寫

一、搭建Cygwin 環境:http://blog.csdn.net/androidolblog/article/details/25559013

二、JNI 基本要素:

1、編寫 含native 方法的java文件。

2、把該文件用javah 生成 Cygwin 編譯庫時要用到的頭文件,既*.h 文件。

3、編寫*.c 文件,在*.c文件中,實現 *.h 中的方法。

4、編寫mk文件。

5、配置NDK環境。

6、用Cygwin 編譯庫文件。

7、拷貝庫文件到eclipse工程中的JNI demo。

8、調用 JNI中的native 方法。

三、JNI demo 編寫詳細:

1、編寫native 方法的java類

MyJniMethod .java 
package com.lin.myjin;

public class MyJniMethod {
 
  static{
   System.loadLibrary("myJin");
  }
     public native void add(int add);
     public native void print(int i);
     public native int getadd(int add);
}


2、把該文件用javah 生成 Cygwin 編譯庫時要用到的頭文件,既*.h 文件:

 生成步驟如下:以下文字是網上找的。覺得寫的挺全的。就直接貼了。

 假設你是用Eclipse開發,例如工程在 D盤的myjin目錄中,你有一個類Test.java具有包路徑,例如 package cn.edu.xmu.zgy;

即在D:\MyTest\src\cn\edu\xmu\zgy\目錄下會存放着你的Test.java文件。

那麼要生成.h文件,則在控制檯下切換到D:\MyTest\bin\classes目錄下,然後輸入 javah -jni cn.edu.xmu.zgy.Test 之後,就可以在D:\MyTest\bin\classes\目錄下可以找到 cn_edu_xmu_zgy_Test.h頭文件。

原理:eclipse下的android工程被編譯後,會把java生成字節碼class文件。所用直接跳轉到編譯了的工程的classes目錄,然後用java - jni *.class 的文件名。生成h文件。


注意

(1)生成的*.h一定要帶包名的h文件。在*.class 文件所在目錄下, 進行javah -jni * 生成的文件是不帶包名的。

(2)這裏的 javah -jni cn.edu.xmu.zgy.Test而不是 javah -jni  cn.edu.xmu.zgy.Test.class


下面是我生成頭文件的截圖:工程名是 myJin



生成的com_lin_myjin_MyJniMethod.h 文件如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_lin_myjin_MyJniMethod */
#ifndef _Included_com_lin_myjin_MyJniMethod
#define _Included_com_lin_myjin_MyJniMethod
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class: com_lin_myjin_MyJniMethod
 * Method: add
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_lin_myjin_MyJniMethod_add
  (JNIEnv *, jobject, jint);
/*
 * Class: com_lin_myjin_MyJniMethod
 * Method: print
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_lin_myjin_MyJniMethod_print
  (JNIEnv *, jobject, jint);
/*
 * Class: com_lin_myjin_MyJniMethod
 * Method: getadd
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_com_lin_myjin_MyJniMethod_getadd
  (JNIEnv *, jobject, jint);
#ifdef __cplusplus
}
#endif
#endif

3、編寫*.c 文件,在*.c文件中,實現 *.h 中的方法:

這裏以:

JNIEXPORT jint JNICALL Java_com_lin_myjin_MyJniMethod_getadd
  (JNIEnv * env, jobject obj, jint count)
  {
       return count+8;
 
  }
爲例

com_lin_myjin_MyJniMethod.c
文件內容:

#include "com_lin_myjin_MyJniMethod.h"
//#define LOG_TAG "Android-T"
//#undef LOG
//#include <android/log.h>
//#define LOGD(a) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,a)
//#define LOGD2(a,b) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,a,b)
// #define DBUG
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
JNIEXPORT void JNICALL Java_com_lin_myjin_MyJniMethod_add
  (JNIEnv * env, jobject obj, jint count)
  {
 
  }
/*
 * Class: com_lin_myjin_MyJniMethod
 * Method: print
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_lin_myjin_MyJniMethod_print
  (JNIEnv * env, jobject obj, jint count)
  {
 
  }
/*
 * Class: com_lin_myjin_MyJniMethod
 * Method: getadd
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_com_lin_myjin_MyJniMethod_getadd
  (JNIEnv * env, jobject obj, jint count)
  {
       return count+8;
 
  }

4、編寫mk文件:
關於MK文件。可自行了解。在此不贅述。

Android.mk文件:
內容:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := myJin
LOCAL_SRC_FILES := com_lin_myjin_MyJniMethod.c
include $(BUILD_SHARED_LIBRARY)

5、配置NDK環境:
在這裏,NDK不用配置環境變量。原理是用絕對路徑操作命令。
在Cygwin下,跳轉到你 C文件 h文件 mk 文件的目錄。或者把這三個文件拷貝到一個叫jni的目錄下面。目錄名字可以隨便取。
然後跳轉到含有這三個文件的目錄,輸入:/cygdrive/d/android-ndk-r5b/ndk-build  回車。/cygdrive/d/這個部分根據你 存放android-ndk-r5b/ndk-build的目錄變化而變化。只要能直接精確到android-ndk-r5b/ndk-build 就行。
原理:$符號取添加在環境變量中的 命令或者目錄。

舉例:自定義一個myCommand 命令,實現命令是 cd .  .   即跳轉到上層目錄。
添加myCommand 成功後,可以直接用 $myCommand 來實現 cd  .. 
所以:網上的NDK-Build 命令 其實是/cygdrive/d/android-ndk-r5b/ndk-build  的方便操作模式。前提是你添加了NDK-Build環境變量。
myCommand 命令截圖:

6、用Cygwin 編譯庫文件步驟:

(1)新建一個jni目錄:


(2)目錄下面放三個文件: 跳轉到相應目錄 輸入:/cygdrive/d/android-ndk-r5b/ndk-build  回車

 


生成的庫文件:



6、拷貝庫文件到eclipse工程中的工程,這裏是myJin:這個名字本來是打算打myJni的。大家當做工程名就好。


注意:

  (1)庫文件名一般是lib**.so  加載時名字是 **.so 比如上面的 庫文件是libmyJin.so 而加載處是 myJin

  (2)加載庫時,文件名不帶庫文件後綴 .so

(3)加載庫代碼塊 要靜態加載。  


7、調用 JNI中的native 方法:


運行結果是:


可見 加過是12  也就是4+8的結果。說明代碼已經正常調用。

工程demo源碼鏈接:http://download.csdn.net/detail/linhuorongandroid/7332143

結語:該代碼demo上十分簡單。目的只是跑個JNI流程。有所不足,多多指教。



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