介紹Java如何將數據傳遞給C和C回調Java的方法。 java傳遞數據給C,在C代碼中進行處理數據,處理完數據後返回給java。C的回調是Java傳遞數據給C,C需要用到Java中的某個方法,就需要調用java的方法。
Android中使用JNI七個步驟:
1.創建一個android工程
2.JAVA代碼中寫聲明native 方法 public native String helloFromJNI();
3.用javah工具生成頭文件
4. 創建jni目錄,引入頭文件,根據頭文件實現c代碼
5.編寫Android.mk文件
6.Ndk編譯生成動態庫
7.Java代碼load 動態庫.調用native代碼
Java調用C進行數據傳遞
這裡分別傳遞整形、字符串、數組在C中進行處理。
聲明native 方法:
- public class DataProvider {
- // 兩個java中的int 傳遞c 語言 , c語言處理這個相加的邏輯,把相加的結果返回給java
- public native int add(int x ,int y);
-
- //把一個java中的字符串傳遞給c語言, c 語言處理下字符串, 處理完畢返回給java
- public native String sayHelloInC(String s);
-
- //把一個java中int類型的數組傳遞給c語言, c語言裡面把數組的每一個元素的值 都增加5,
- //然後在把處理完畢的數組,返回給java
- public native int[] intMethod(int[] iNum);
- }
以上方法要在C中實現的頭文件,頭文件可以理解為要在C中實現的方法
其中 JENEnv* 代表的是java環境 , 通過這個環境可以調用java的方法,jobject 表示哪個對象調用了 這個c語言的方法, thiz就表示的是當前的對象
- /* DO NOT EDIT THIS FILE - it is machine generated */
- #include <jni.h>
- /* Header for class cn_itcast_ndk3_DataProvider */
-
- #ifndef _Included_cn_itcast_ndk3_DataProvider
- #define _Included_cn_itcast_ndk3_DataProvider
- #ifdef __cplusplus
- extern "C" {
- #endif
- /*
- * Class: cn_itcast_ndk3_DataProvider
- * Method: add
- * Signature: (II)I
- */
- JNIEXPORT jint JNICALL Java_cn_itcast_ndk3_DataProvider_add
- (JNIEnv *, jobject, jint, jint);
-
- /*
- * Class: cn_itcast_ndk3_DataProvider
- * Method: sayHelloInC
- * Signature: (Ljava/lang/String;)Ljava/lang/String;
- */
- JNIEXPORT jstring JNICALL Java_cn_itcast_ndk3_DataProvider_sayHelloInC
- (JNIEnv *, jobject, jstring);
-
- /*
- * Class: cn_itcast_ndk3_DataProvider
- * Method: intMethod
- * Signature: ([I)[I
- */
- JNIEXPORT jintArray JNICALL Java_cn_itcast_ndk3_DataProvider_intMethod
- (JNIEnv *, jobject, jintArray);
-
- #ifdef __cplusplus
- }
- #endif
- #endif
C代碼出了要引用頭文件外,還要引入日志信息,以方便在C 中進行調試
- //引入頭文件
- #include "cn_itcast_ndk3_DataProvider.h"
- #include <string.h>
- //導入日志頭文件
- #include <android/log.h>
- //修改日志tag中的值
- #define LOG_TAG "logfromc"
- //日志顯示的等級
- #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
- #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
-
- // java中的jstring, 轉化為c的一個字符數組
- char* Jstring2CStr(JNIEnv* env, jstring jstr)
- {
- char* rtn = NULL;
- jclass clsstring = (*env)->FindClass(env,"java/lang/String");
- jstring strencode = (*env)->NewStringUTF(env,"GB2312");
- jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B");
- jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312");
- jsize alen = (*env)->GetArrayLength(env,barr);
- jbyte* ba = (*env)->GetByteArrayElements(env,barr,JNI_FALSE);
- if(alen > 0)
- {
- rtn = (char*)malloc(alen+1); //new char[alen+1]; "\0"
- memcpy(rtn,ba,alen);
- rtn[alen]=0;
- }
- (*env)->ReleaseByteArrayElements(env,barr,ba,0); //釋放內存
-
- return rtn;
- }
-
- //處理整形相加
- JNIEXPORT jint JNICALL Java_cn_itcast_ndk3_DataProvider_add
- (JNIEnv * env, jobject obj, jint x, jint y){
- //打印 java 傳遞過來的 jstring ;
- LOGI("log from c code ");
- LOGI("x= %ld",x);
- LOGD("y= %ld",y);
- return x+y;
- }
-
- //處理字符串追加
- JNIEXPORT jstring JNICALL Java_cn_itcast_ndk3_DataProvider_sayHelloInC
- (JNIEnv * env, jobject obj, jstring str){
-
- char* p = Jstring2CStr(env,str);
- LOGI("%s",p);
- char* newstr = "append string";
-
- //strcat(dest, sorce) 把sorce字符串添加到dest字符串的後面
- LOGI("END");
- return (*env)->NewStringUTF(env, strcat(p,newstr));
- }
-
- //處理數組中的每一個元素
- JNIEXPORT jintArray JNICALL Java_cn_itcast_ndk3_DataProvider_intMethod
- (JNIEnv * env, jobject obj, jintArray arr){
- // 1.獲取到 arr的大小
-
- int len = (*env)->GetArrayLength(env, arr);
- LOGI("len=%d", len);
-
- if(len==0){
- return arr;
- }
- //取出數組中第一個元素的內存地址
- jint* p = (*env)-> GetIntArrayElements(env,arr,0);
- int i=0;
- for(;i<len;i++){
- LOGI("len=%ld", *(p+i));//取出的每個元素
- *(p+i) += 5; //取出的每個元素加五
- }
- return arr;
- }
編寫Android.mk文件
- LOCAL_PATH := $(call my-dir)
-
- include $(CLEAR_VARS)
-
- LOCAL_MODULE := Hello
- LOCAL_SRC_FILES := Hello.c
- #增加 log 函數對應的log 庫 liblog.so libthread_db.a
- LOCAL_LDLIBS += -llog
-
- include $(BUILD_SHARED_LIBRARY)