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