JNI开发要做的环境搭建和开发流程:
1.为什么要使用jni?
C和C++,拥有Java所没有的一些特性,比如处理数据的效率,操作硬件的效率,C的效率是最快的;
2.怎么去调用C或C++的函数?
遵循Java和C的中间件,JNI规范,让Java和C进行互通交互;
3.开发当中需要什么工具和环境?
1. C或C++的编写,需要给eclipse安装cdt插件;
adt: android develop tools
cdt: c/c++ develop tools
2. C或C++的编译,需要安装开发工具集,NDK;
ndk: natvie develop kits 本地开发工具集 ( 交叉编译的工具链)
建议装在d盘根目录;
3. 使用NDK中的Linux脚本,需要安装一个Linux模拟环境,
1.装一个虚拟机,建议装置d盘根目录;
2. Cygwin 一个windows下 linux环境的模拟器
1.给虚拟机指定ndk-build的路径 /cygdrive/d/android-ndk-r7b/ndk-build
#在PATH中添加ndk-build的路径:/cygdrive/d/android-ndk-r7b
PATH="/usr/local/bin:/usr/bin:/cygdrive/d/android-ndk-r7b:${PATH}"
配置成功的体现:
Administrator@PC2012102114RDI ~
$ ndk-build
Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
/cygdrive/d/android-ndk-r7b/build/core/build-local.mk:130: *** Android NDK: Aborting 。 停止。
4.在环境搭建好之后,怎么开发?走什么流程?
1.声明native方法
2.在classes目录下使用javah生产.h文件
3.创建jni目录,把.h文件拷贝过来;
4.在jni目录创建.c或.cpp文件;
5.在jni目录创建.mk文件,用于指定.so名称,以及原文件名称;
6.在项目目录下,允许ndk-build工具,自动生成.so文件,并且把.so文件放到该放的位置 libs/armeabi/libXXX.so
7.在java代码中的静态代码块中把.so加载进来;
C和C++的编写,数据类型,需要参照JNI规范:
参照 D:\android-ndk-r7b\platforms\android-8\arch-arm\usr\include 目录下的 jni.h 文件,该文件详细描述了Java和C/C++的中间类型;
规范了数据类型的声明,以及创建对象的方法,还有常用的方法;
.h文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cn_itcast_cpp_DemoActivity */
#include"cn_itcast_cpp_DemoActivity.h"
#define _Included_cn_itcast_cpp_DemoActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: cn_itcast_cpp_DemoActivity
* Method: hellofromcpp
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_cn_itcast_cpp_DemoActivity_hellofromcpp
(JNIEnv *, jobject);
/*
* Class: cn_itcast_cpp_DemoActivity
* Method: helloInCpp
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_cn_itcast_cpp_DemoActivity_helloInCpp
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
.cpp文件:
#include<stdio.h>
#include"cn_itcast_cpp_DemoActivity.h"
#include <android/log.h>
#include<stdlib.h>
#include <malloc.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
char* Jstring2CStr(JNIEnv* env, jstring jstr)
{
char* rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = (env)->NewStringUTF("GB2312");
jmethodID mid = (env)->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr= (jbyteArray)(env)->CallObjectMethod(jstr,mid,strencode); // String .getByte("GB2312");
jsize alen = (env)->GetArrayLength(barr);
jbyte* ba = (env)->GetByteArrayElements(barr,JNI_FALSE);
if(alen > 0)
{
rtn = (char*)malloc(alen+1); //"\0"
memcpy(rtn,ba,alen);
rtn[alen]=0;
}
(env)->ReleaseByteArrayElements(barr,ba,0); //
return rtn;
}
JNIEXPORT jstring JNICALL Java_cn_itcast_cpp_DemoActivity_hellofromcpp
(JNIEnv * env, jobject obj){
// return (*env)->NewStringUTF(env,"hello from c");
return env->NewStringUTF("hello form cpp");
}
JNIEXPORT void JNICALL Java_cn_itcast_cpp_DemoActivity_helloInCpp
(JNIEnv * env, jobject obj , jstring jstr){
char* cstr = Jstring2CStr(env,jstr);
LOGI("cstr=%s",cstr);
}
.mk文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#LOCAL_CPP_EXTENSION := cc
LOCAL_MODULE := Hello
LOCAL_SRC_FILES := Hello.cpp
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)