Android C++向java傳遞不定長且不同型別的引數
阿新 • • 發佈:2019-01-03
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); } } }