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;
}
關於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流程。有所不足,多多指教。