1、c/c++和java之间的通信经常通过jni来实时传递参数,但是由于参数不固定或者参数类型很多需要一个合适的方法来传递。
2、这里有个实例,记录以备用,头文件
/*
* jni_tbox_observer.h
*
*/
#ifndef JNI_TBOX_OBSERVER_H_
#define JNI_TBOX_OBSERVER_H_
#include <map>
#include "jni.h"
#ifdef HAVE_ANDROID_OS
#include "JNIHelp.h"
#endif
#include "tbox_interfaces.h"
#include "common_head.h"
#include "tbox_status.h"
namespace dls
{
using std::string;
class jni_tbox_observer : public tbox_observer
{
public:
// void on_mic_forward_changed(const u8& forward);
// void on_telema_business_status(const u8& business_id, const u8& status);
// void on_tbox_key_event(const u8& key_code, const u8& action);
void on_tbox_communication_state(const u8& state);
void on_call_status(const u8& call_status);
void on_tbox_reply_gps(const char *gps_info);
void on_test_uart_result(const u8& result);
jni_tbox_observer(JavaVM *jvm, JNIEnv* env, jobject obj);
virtual ~jni_tbox_observer();
private:
JavaVM* _jvm;
JNIEnv* _construct_env;
jobject _corresponding_jobj;
jclass _corresponding_jclz;
std::map<int, JNIEnv*> _callback_thread_JNIEnvs;
pthread_mutex_t _JNIEnvs_lock;
tbox_status* _tbox_status;
JNIEnv* obtain_callback_thread_env();
void call_java_method(const char* method_name, const char* arg_format, ...);
};
} /* namespace dls */
#endif /* JNI_TBOX_OBSERVER_H_ */
3、实例
/*
* jni_tbox_observer.cpp
*
*/
#include <sys/syscall.h>
#include "jni_tbox_observer.h"
#undef LOG_TAG
#define LOG_TAG "TB_JNI_Observer"
namespace dls {
using std::map;
struct _gpsInfo {
u8 _gpsStatus;
int _gpsLongtitude;
int _gpsLatitude;
u16 _gpsSpeed;
u16 _gpsBearing;
u16 _gpsAltitude;
u32 _gpsTime;
u16 _gpsGeoDirection;
u8 _gpsHdop;
u8 _gpsVdop;
u8 _gpsCurTolSat;
u8 _gpsPosSat;
};
/** Represents SV information. */
struct GpsSvInfo {
/** Pseudo-random number for the SV. */
u8 prn;
/** Elevation of SV in degrees. */
u8 elevation;
/** Azimuth of SV in degrees. */
u16 azimuth;
/** Signal to noise ratio. */
u8 snr;
} ;
jni_tbox_observer::jni_tbox_observer(JavaVM *jvm, JNIEnv* env, jobject obj) :
_jvm(jvm), _construct_env(env), _corresponding_jobj(
env->NewGlobalRef(obj)), _corresponding_jclz(NULL) {
pthread_mutexattr_t mutex_attr;
pthread_mutexattr_init(&mutex_attr);
pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE_NP);
pthread_mutex_init(&_JNIEnvs_lock, &mutex_attr);
jclass clz = env->GetObjectClass(_corresponding_jobj);
_corresponding_jclz = reinterpret_cast<jclass>(env->NewGlobalRef(clz));
_tbox_status = new tbox_status();
}
jni_tbox_observer::~jni_tbox_observer() {
_construct_env->DeleteGlobalRef(_corresponding_jobj);
_construct_env->DeleteGlobalRef(_corresponding_jclz);
for (map<int, JNIEnv*>::iterator it = _callback_thread_JNIEnvs.begin();
it != _callback_thread_JNIEnvs.end(); it++) {
//XXX How To detach current thread JNI environment???? OMG, I don't know, fortunately we needn't to do so.
}
_callback_thread_JNIEnvs.clear();
}
/*
void jni_tbox_observer::on_mic_forward_changed(const u8& forward) {
call_java_method("onMicForwardFromNative", "(I)V", forward);
}
void jni_tbox_observer::on_telema_business_status(const u8& business_id,
const u8& status) {
call_java_method("onTelematicBusinessStatusFromNative", "(II)V",
business_id, status);
}
void jni_tbox_observer::on_tbox_key_event(const u8& key_code,
const u8& action) {
call_java_method("onTBoxKeyEventFromNative", "(II)V", key_code, action);
}
*/
void jni_tbox_observer::on_tbox_communication_state(const u8& state) {
call_java_method("onTBoxCommunicationState", "(I)V", state);
}
void jni_tbox_observer::on_call_status(const u8& call_status) {
call_java_method("onCallStatusResponse", "(I)V", call_status);
}
void jni_tbox_observer::on_test_uart_result(const u8& result) {
call_java_method("onTestUartResponse", "(I)V", result);
}
u32 EndianConvertLToB(u32 InputNum) {
u8 *p = (u8*)&InputNum;
return(((u32)*p<<24)+((u32)*(p+1)<<16)+
((u32)*(p+2)<<8)+(u32)*(p+3));
}
u16 EndianConvertLToBS(u16 InputNum) {
u8 *p = (u8*)&InputNum;
return(((u16)*p<<8)+((u16)*(p+1)));
}
GpsSvInfo getSVInfo(const char *gInfo) {
struct GpsSvInfo mGi;
mGi.prn = *gInfo;
mGi.elevation = *(gInfo+1);
mGi.azimuth = *(u16 *)(gInfo+2);
mGi.azimuth = EndianConvertLToBS(mGi.azimuth);
mGi.snr = *(gInfo+4);
return mGi;
}
void jni_tbox_observer::on_tbox_reply_gps(const char * gps_info) {
struct _gpsInfo gI;
struct GpsSvInfo GSI1;
struct GpsSvInfo GSI2;
struct GpsSvInfo GSI3;
struct GpsSvInfo GSI4;
struct GpsSvInfo GSI5;
struct GpsSvInfo GSI6;
struct GpsSvInfo GSI7;
struct GpsSvInfo GSI8;
struct GpsSvInfo GSI9;
struct GpsSvInfo GSI10;
struct GpsSvInfo GSI11;
struct GpsSvInfo GSI12;
gI._gpsStatus = *gps_info;
gI._gpsLongtitude = *(int *)(gps_info+1);
gI._gpsLongtitude =(int) EndianConvertLToB(gI._gpsLongtitude);
gI._gpsLatitude = *(int *)(gps_info+5);
gI._gpsLatitude =(int) EndianConvertLToB(gI._gpsLatitude);
gI._gpsSpeed = *(u16 *)(gps_info+9);
gI._gpsSpeed = EndianConvertLToBS(gI._gpsSpeed);
gI._gpsBearing = *(u16 *)(gps_info+11);
gI._gpsBearing = EndianConvertLToBS(gI._gpsBearing);
gI._gpsAltitude = *(u16 *)(gps_info+13);
gI._gpsAltitude = EndianConvertLToBS(gI._gpsAltitude);
gI._gpsTime = *(u32 *)(gps_info+15);
gI._gpsTime =(u32) EndianConvertLToB(gI._gpsTime);
gI._gpsGeoDirection = *(u16 *)(gps_info+19);
gI._gpsGeoDirection = EndianConvertLToBS(gI._gpsGeoDirection);
gI._gpsHdop = *(gps_info+21);
gI._gpsVdop = *(gps_info+22);
gI._gpsCurTolSat = *(gps_info+23);
gI._gpsPosSat = *(gps_info+24);
/*LOGD("################# gI->_gpsStatus[%d]\n",gI._gpsStatus);
LOGD("################# gI->_gpsLongtitude[%ul],[0x%x]\n",gI._gpsLongtitude,gI._gpsLongtitude);
LOGD("################# gI->_gpsLatitude[%ul],[0x%x]\n",gI._gpsLatitude,gI._gpsLatitude);
LOGD("################# gI->_gpsSpeed[%d]\n",gI._gpsSpeed);
LOGD("################# gI->_gpsBearing[%d]\n",gI._gpsBearing);
LOGD("################# gI->_gpsAltitude[%d]\n",gI._gpsAltitude);
LOGD("################# gI->_gpsTime[%ul],[0x%x]\n",gI._gpsTime,gI._gpsTime);
LOGD("################# gI->_gpsGeoDirection[%d]\n",gI._gpsGeoDirection);
LOGD("################# gI->_gpsHdop[%d]\n",gI._gpsHdop);
LOGD("################# gI->_gpsVdop[%d]\n",gI._gpsVdop);
LOGD("################# gI->_gpsCurTolSat[%d]\n",gI._gpsCurTolSat);
LOGD("################# gI->_gpsPosSat[%d]\n",gI._gpsPosSat);*/
GSI1 = getSVInfo((gps_info+25));
GSI2 = getSVInfo((gps_info+30));
GSI3 = getSVInfo((gps_info+35));
GSI4 = getSVInfo((gps_info+40));
GSI5 = getSVInfo((gps_info+45));
GSI6 = getSVInfo((gps_info+50));
GSI7 = getSVInfo((gps_info+55));
GSI8 = getSVInfo((gps_info+60));
GSI9 = getSVInfo((gps_info+65));
GSI10 = getSVInfo((gps_info+70));
GSI11 = getSVInfo((gps_info+75));
GSI12 = getSVInfo((gps_info+80));
_tbox_status->gps_status = gI._gpsStatus;
_tbox_status->gps_longitude = gI._gpsLongtitude;
_tbox_status->gps_latitude = gI._gpsLatitude;
_tbox_status->gps_speed = gI._gpsSpeed;
_tbox_status->gps_Bearing = gI._gpsBearing;
_tbox_status->gps_altitude = gI._gpsAltitude;
_tbox_status->gps_time = gI._gpsTime;
_tbox_status->gps_geo_direction = gI._gpsGeoDirection;
_tbox_status->gps_hdop = gI._gpsHdop;
_tbox_status->gps_vdop = gI._gpsVdop;
_tbox_status->gps_cur_tol_sat = gI._gpsCurTolSat;
_tbox_status->gps_pos_sat = gI._gpsPosSat;
call_java_method("onTBoxReplyGPSInfo", "(IIISSSISIIIIIISIIISIIISIIISIIISIIISIIISIIISIIISIIISIIISIIISI)V", gI._gpsStatus,gI._gpsLongtitude,gI._gpsLatitude,gI._gpsSpeed,gI._gpsBearing,
gI._gpsAltitude,gI._gpsTime,gI._gpsGeoDirection,gI._gpsHdop,gI._gpsVdop,gI._gpsCurTolSat,gI._gpsPosSat,
GSI1.prn,GSI1.elevation,GSI1.azimuth,GSI1.snr,
GSI2.prn,GSI2.elevation,GSI2.azimuth,GSI2.snr,
GSI3.prn,GSI3.elevation,GSI3.azimuth,GSI3.snr,
GSI4.prn,GSI4.elevation,GSI4.azimuth,GSI4.snr,
GSI5.prn,GSI5.elevation,GSI5.azimuth,GSI5.snr,
GSI6.prn,GSI6.elevation,GSI6.azimuth,GSI6.snr,
GSI7.prn,GSI7.elevation,GSI7.azimuth,GSI7.snr,
GSI8.prn,GSI8.elevation,GSI8.azimuth,GSI8.snr,
GSI9.prn,GSI9.elevation,GSI9.azimuth,GSI9.snr,
GSI10.prn,GSI10.elevation,GSI10.azimuth,GSI10.snr,
GSI11.prn,GSI11.elevation,GSI11.azimuth,GSI11.snr,
GSI12.prn,GSI12.elevation,GSI12.azimuth,GSI12.snr);
}
void jni_tbox_observer::call_java_method(const char* method_name,
const char* arg_format, ...) {
JNIEnv* env = obtain_callback_thread_env();
va_list args;
jmethodID method = env->GetMethodID(_corresponding_jclz, method_name,
arg_format);
if (method) {
va_start(args, arg_format);
env->CallVoidMethodV(_corresponding_jobj, method, args);
va_end(args);
} else {
LOGW(
"Can't call Java method name[%s], arg_format[%s]", method_name, arg_format);
}
}
JNIEnv* jni_tbox_observer::obtain_callback_thread_env() {
JNIEnv* env = NULL;
#ifdef HAVE_ANDROID_OS
int tid = gettid();
#else
int tid = syscall(SYS_gettid);
#endif
map<int, JNIEnv*>::iterator it = _callback_thread_JNIEnvs.find(tid);
if (it == _callback_thread_JNIEnvs.end() || it->second == NULL) {
LOGW("Not Found JNIEnv For Thread[%d] In The <Tid, JNIEnv> Map", tid);
#ifdef HAVE_ANDROID_OS
_jvm->AttachCurrentThread(&env, NULL);
#else
_jvm->AttachCurrentThread((void**) &env, NULL);
#endif //HAVE_ANDROID_OS
_callback_thread_JNIEnvs[tid] = env;
} else {
env = it->second;
}
return env;
}
} /* namespace dls */
4、java实例
/** Parameters
*
* gpsStatus 定位状态
* gpsLongitude 经度
* gpsLatitude 纬度
* gpsSpeed 速度
* gpsBearing 方向
* gpsAltitude 高度
* gpsTimeStamp 时间
* gpsGeoDirection 地磁方向
* gpsHdop HDOP
* gpsVdop VDOP
* gpsCurTolSat 当前卫星总数
* gpsPosSat 用于定位的卫星数
*
*/
private int gpsStatus;
private double gpsLongitude = TBoxManager.DEFAULT_VALUE_LONG_LAT;
private double gpsLatitude = TBoxManager.DEFAULT_VALUE_LONG_LAT;
private float gpsSpeed;
private float gpsBearing = TBoxManager.DEFAULT_VALUE_BEARING;
private float gpsAltitude;
private long gpsTimeStamp;
private float gpsGeoDirection;
private float gpsHdop;
private float gpsVdop;
private int gpsCurTolSat;
private int gpsPosSat;
private float m_sv1_azimuth;
private float m_sv2_azimuth;
private float m_sv3_azimuth;
private float m_sv4_azimuth;
private float m_sv5_azimuth;
private float m_sv6_azimuth;
private float m_sv7_azimuth;
private float m_sv8_azimuth;
private float m_sv9_azimuth;
private float m_sv10_azimuth;
private float m_sv11_azimuth;
private float m_sv12_azimuth;
private void onTBoxReplyGPSInfo(int gI_status, int gI_longitude, int gI_latitude, short gI_speed, short gI_Bearing,short gI_Altitude, int gI_TimeStamp,
short gI_geo_direction, int gI_Hdop, int gI_Vdop, int gI_cur_tol_sat, int gI_pos_sat,
int sv1_prn,int sv1_elevation,short sv1_azimuth,int sv1_snr,
int sv2_prn,int sv2_elevation,short sv2_azimuth,int sv2_snr,
int sv3_prn,int sv3_elevation,short sv3_azimuth,int sv3_snr,
int sv4_prn,int sv4_elevation,short sv4_azimuth,int sv4_snr,
int sv5_prn,int sv5_elevation,short sv5_azimuth,int sv5_snr,
int sv6_prn,int sv6_elevation,short sv6_azimuth,int sv6_snr,
int sv7_prn,int sv7_elevation,short sv7_azimuth,int sv7_snr,
int sv8_prn,int sv8_elevation,short sv8_azimuth,int sv8_snr,
int sv9_prn,int sv9_elevation,short sv9_azimuth,int sv9_snr,
int sv10_prn,int sv10_elevation,short sv10_azimuth,int sv10_snr,
int sv11_prn,int sv11_elevation,short sv11_azimuth,int sv11_snr,
int sv12_prn,int sv12_elevation,short sv12_azimuth,int sv12_snr) {
int mOldState = mConmmuincationState;
if(mOldState == COMMUNICATION_DISCONNECTED || mOldState == COMMUNICATION_UNKNOWN) {
mConmmuincationState = COMMUNICATION_ESTABLISHED;
}
gpsStatus = gI_status;
gpsLongitude = (double) (gI_longitude / 100000.0);
gpsLatitude = (double) (gI_latitude / 100000.0);
gpsSpeed = (float) (gI_speed / 100.0);
gpsBearing = (float) (gI_Bearing / 100.0);
gpsAltitude = (float) gI_Altitude;
gpsTimeStamp = (long) gI_TimeStamp;
gpsGeoDirection = (float) (gI_geo_direction / 100.0);
gpsHdop = (float) (gI_Hdop / 10.0);
gpsVdop = (float) (gI_Vdop / 10.0);
gpsCurTolSat = gI_cur_tol_sat;
gpsPosSat = gI_pos_sat;
m_sv1_azimuth = (float) (sv1_azimuth / 1.0);
m_sv2_azimuth = (float) (sv2_azimuth / 1.0);
m_sv3_azimuth = (float) (sv3_azimuth / 1.0);
m_sv4_azimuth = (float) (sv4_azimuth / 1.0);
m_sv5_azimuth = (float) (sv5_azimuth / 1.0);
m_sv6_azimuth = (float) (sv6_azimuth / 1.0);
m_sv7_azimuth = (float) (sv7_azimuth / 1.0);
m_sv8_azimuth = (float) (sv8_azimuth / 1.0);
m_sv9_azimuth = (float) (sv9_azimuth / 1.0);
m_sv10_azimuth = (float) (sv10_azimuth / 1.0);
m_sv11_azimuth = (float) (sv11_azimuth / 1.0);
m_sv12_azimuth = (float) (sv12_azimuth / 1.0);
/*
LOGD("######################### onTBoxReportGPSInfo == " + "\n" +
" gpsStatus == " + gpsStatus + "\n" +
" gpsLongitude == " + gpsLongitude + "\n" +
" gpsLatitude == " + gpsLatitude + "\n" +
" gpsSpeed == " + gpsSpeed + "\n" +
" gpsBearing == " + gpsBearing + "\n" +
" gpsAltitude == " + gpsAltitude + "\n" +
" gpsTimeStamp == " + gpsTimeStamp + "\n" +
" gpsGeoDirection == " + gpsGeoDirection + "\n" +
" gpsHdop == " + gpsHdop + "\n" +
" gpsVdop == " + gpsVdop + "\n" +
" gpsCurTolSat == " + gpsCurTolSat + "\n" +
" gpsPosSat == " + gpsPosSat + "\n"
+ " prn 1: " + sv1_prn + " elevation 1: " +sv1_elevation + " azimuth 1: " +sv1_azimuth + " snr 1: " +sv1_snr + "\n"
+ " prn 2: " + sv2_prn + " elevation 2: " +sv2_elevation + " azimuth 2: " +sv2_azimuth + " snr 2: " +sv2_snr + "\n"
+ " prn 3: " + sv3_prn + " elevation 3: " +sv3_elevation + " azimuth 3: " +sv3_azimuth + " snr 3: " +sv3_snr + "\n"
+ " prn 4: " + sv4_prn + " elevation 4: " +sv4_elevation + " azimuth 4: " +sv4_azimuth + " snr 4: " +sv4_snr + "\n"
+ " prn 5: " + sv5_prn + " elevation 5: " +sv5_elevation + " azimuth 5: " +sv5_azimuth + " snr 5: " +sv5_snr + "\n"
+ " prn 6: " + sv6_prn + " elevation 6: " +sv6_elevation + " azimuth 6: " +sv6_azimuth + " snr 6: " +sv6_snr + "\n"
+ " prn 7: " + sv7_prn + " elevation 7: " +sv7_elevation + " azimuth 7: " +sv7_azimuth + " snr 7: " +sv7_snr + "\n"
+ " prn 8: " + sv8_prn + " elevation 8: " +sv8_elevation + " azimuth 8: " +sv8_azimuth + " snr 8: " +sv8_snr + "\n"
+ " prn 9: " + sv9_prn + " elevation 9: " +sv9_elevation + " azimuth 9: " +sv9_azimuth + " snr 9: " +sv9_snr + "\n"
+ " prn 10: " + sv10_prn + " elevation 10: " +sv10_elevation + " azimuth 10: " +sv10_azimuth + " snr 10: " +sv10_snr + "\n"
+ " prn 11: " + sv11_prn + " elevation 11: " +sv11_elevation + " azimuth 11: " +sv11_azimuth + " snr 11: " +sv11_snr + "\n"
+ " prn 12: " + sv12_prn + " elevation 12: " +sv12_elevation + " azimuth 12: " +sv12_azimuth + " snr 12: " +sv12_snr);
*/
if(mReportGpsFlag){
setGPSInfoDataSource(gpsStatus, gpsLongitude, gpsLatitude, gpsSpeed, gpsBearing, gpsAltitude,
gpsTimeStamp, gpsGeoDirection, gpsHdop, gpsVdop, gpsCurTolSat, gpsPosSat,
sv1_prn, sv1_elevation, m_sv1_azimuth, sv1_snr,
sv2_prn, sv2_elevation, m_sv2_azimuth, sv2_snr,
sv3_prn, sv3_elevation, m_sv3_azimuth, sv3_snr,
sv4_prn, sv4_elevation, m_sv4_azimuth, sv4_snr,
sv5_prn, sv5_elevation, m_sv5_azimuth, sv5_snr,
sv6_prn, sv6_elevation, m_sv6_azimuth, sv6_snr,
sv7_prn, sv7_elevation, m_sv7_azimuth, sv7_snr,
sv8_prn, sv8_elevation, m_sv8_azimuth, sv8_snr,
sv9_prn, sv9_elevation, m_sv9_azimuth, sv9_snr,
sv10_prn, sv10_elevation, m_sv10_azimuth, sv10_snr,
sv11_prn, sv11_elevation, m_sv11_azimuth, sv11_snr,
sv12_prn, sv12_elevation, m_sv12_azimuth, sv12_snr);
//Broadcast the GPS time when the GPS status is ok.
if(gpsStatus == 1 && mReportTimeFlag) {
LOGD("Broadcast the GPS time stamps");
mReportTimeFlag = false;
//Intent i = new Intent(TBoxManager.ACTION_TBOX_GPS_TIME);
Date date;
long tempTime = gpsTimeStamp * 1000;
date = new Date(tempTime);
LOGD("sendBroadcast the Current time is: " + date);
//i.putExtra(TBoxManager.EXTRA_TBOX_GPS_TIME, tempTime);
//LOGD("sendBroadcast intent: " + i.toURI());
//mContext.sendBroadcast(i);
Bundle bundle = new Bundle();
bundle.putLong(TBoxManager.EXTRA_TBOX_GPS_TIME, tempTime);
broadcastTBoxEvent(TBoxManager.ACTION_TBOX_GPS_TIME, bundle);
}
}
}