最近做的Android項目需要調用C代碼,進行串口通信及與硬件設備通信,因此要用到JNI,其中本地代碼需要向Java層返回三個參數,分別為
參數一:int型;
參數二: 通信指令,本地代碼中為unsigned char[]型,返回unsigned char[]、int[]都可以,能直接將數據轉換為16進制字符串最好(Android界面上要顯示的就是數組每一位的16進制值);
參數三:同參數二。
具體的實現方式有兩種。
第一種是C代碼獲取Java屬性參數,本地修改參數值。
第二種是將三個參數定義為對象,作為函數返回值返回給Java層。
第二種方法的實現,這里定義了一個對象數組,滿足參數二、三的要求,即返回int型數組,而對於參數一來說有些浪費。
Java 代碼:
package com.fansen.hellojni; import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.widget.TextView; public class MainActivity extends Activity { @SuppressLint("DefaultLocale") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); tv.setText( "Hello World!" ); DiskInfo[] infos = stringFromJNI(); for (int i = 0; i < infos.length; i++) {
Log.i("TAG", "infos[" + i + "].data: " + infos[i].data);
Log.i("TAG", "infos[" + i + "].value: " + infos[i].value);
Log.i("TAG", "infos[" + i + "].number: " + infos[i].number);
} setContentView(tv); } public native DiskInfo[] stringFromJNI(); static { System.loadLibrary("hello-jni"); } } class DiskInfo{ public int data; public int value; public int number; }
C代碼:
#include <string.h> #include <jni.h> typedef struct{ int data; int value; int number; } DiskInfo; jobjectArray Java_com_fansen_hellojni_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz ) { jclass clsDiskInfo = (*env)->FindClass(env, "com/fansen/hellojni/DiskInfo"); jobjectArray infos = (*env)->NewObjectArray(env, 10, clsDiskInfo, NULL); jfieldID dataID = (*env)->GetFieldID(env, clsDiskInfo, "data", "I"); jfieldID valueID = (*env)->GetFieldID(env, clsDiskInfo, "value", "I"); jfieldID numberID = (*env)->GetFieldID(env, clsDiskInfo, "number", "I"); jmethodID consID = (*env)->GetMethodID(env, clsDiskInfo, "<init>", "()V"); unsigned char send[10] = {0xFF,0x1F,0x07,0x08,0x00,0x00,0x01,0x02}; int sendcopy[10] = {0}; int j; for(j = 0; j <= 8; j++){ sendcopy[j] = send[j]; //模擬C代碼值變化 } int i; jobject obj; for(i = 0; i < 10; i++){ obj = (*env)->NewObject(env, clsDiskInfo, consID); (*env)->SetIntField(env, obj, dataID, (jint)i); (*env)->SetIntField(env, obj, valueID, (jint)sendcopy[i]); (*env)->SetIntField(env, obj, numberID, (jint)sendcopy[i]);
(*env)->SetObjectArrayElement(env, infos, i, obj);
}
return infos;
}
