1. 程式人生 > >Android C++向java傳遞不定長且不同型別的引數

Android C++向java傳遞不定長且不同型別的引數

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);
            }
        }

    }