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)