HAL中通過jni調用java方法的問題

來源:互聯網
上載者:User

轉載請註明本文出處:http://www.cnblogs.com/xl19862005

作者:Xandy

 

由於工作的需要,最近一直在研究HAL、JNI、java方法之間互調的問題,並做了如下一些記錄和大家一起分享!

 

工作背景:所調試的是一款叫goc-md-102的車載藍芽模組,由於這款藍芽模組無法直接用HCI的方式控制,而它已經有了現成的一套AT命令集進行控制,所以我在HAL中直接通過串口讀寫的方式進行通訊,然後通過JNI和java層建立聯絡。

考慮到效率的問題,我在HAL中用回呼函數的方式通過JNI與java層交換資料,看了一下GPS資料上報的方法正和我用的這個方法一樣!

1、首先是在HAL中串口的開啟、初始化和讀寫,這些都比較簡單,主要看看初始化這個函數中的代碼,如下:

 

/***************************************************************
** fun: init gocmd102_init(/dev/ttymxc1);
** in:
** out: fd sucess, -1 false;
** gocmd102_init
***************************************************************/
static int gocmd102_init(BluetoothCallback *callBack)
{
int fd,var;
btportinfo pPort_info;
int err;

pReceiveCmdPackage = malloc(sizeof(bluetooth));

memset(pReceiveCmdPackage,0,sizeof(bluetooth));
memset(recCmdBuf,0,RECCMDBUFLEN);
//clear message buf
memset(&pPort_info,0,sizeof(btportinfo));

fd=open_bluetoothPort();

if(fd < 0)
{
LOGE("gocmd102_init open port error!");
return -1;
}

pReceiveCmdPackage->fd= fd;
FD = fd;

pPort_info.baud_rate=GOCMD102_BAUD;
pPort_info.data_bits=GOCMD102_DATABIT;
pPort_info.flow_ctrl=GOCMD102_CTRL;
pPort_info.stop_bit=GOCMD102_STOPBIT;
pPort_info.parity=GOCMD102_PARITY;
pPort_info.port_fd=fd;

//pthread_mutex_lock(&pPort_info.portlock);
var = set_btportLocked(&pPort_info);
//pthread_mutex_unlock(&pPort_info.portlock);

if(var < 0)
{
LOGE("set_portLocked error!");
return -1;
}

//在這裡將獲得輸入的函數結構體指標,在後繼資料上報的時候將通過這個函數結構體指標來實現
if(callBack != NULL)
pReceiveCmdPackage->callback = *callBack;
else
{
LOGE("BluetoothCallback struct is empty!");
return -1;
}

//uart receive message thread and analyze it
sem_init(&pReceiveCmdPackage->uart_end, 0, 0);
pReceiveCmdPackage->uart_inited = true;

//err = pthread_create(&pReceiveCmdPackage->thread_id, NULL, &BTuartDownloadData, (void *)pReceiveCmdPackage);

  //在這這裡,通過callback的方式建立了一個線程,用於串口資料的讀取和上報,這個線程是在VM中建立的一個java線程,一定要用這個,而不能用pthread_create,否則會出問題!
pReceiveCmdPackage->thread_id = callBack->bluetooth_thread("gocmd102_bluetooth", BTuartDownloadData, pReceiveCmdPackage);

if (!pReceiveCmdPackage->thread_id)
{
LOGE("could not create bluetooth thread: %s", strerror(errno));
return -1;
}

return fd;
}

 

當藍芽開啟時,上層app通過JNI調用到這個init函數完成串的初始,同時將JNI中調用java方法的函數結構體地址傳入了進來,這個函數結構體如下:

typedef struct
{
size_t size;
void (*callIn_bt)(telephoneIn *callIn);
void (*state_bt)(int state);
void (*getVol_bt)(BtVol *vol);
void (*connect_bt)(matchDev *btDevice);
void (*match_bt)(matchDev *btDevice);
void (*downPHBook_bt)(phoneNumber *phoneNum);
void (*callOut_bt)(phoneNumber *dailNum);
pthread_t (* bluetooth_thread)(const char* name, void (*start)(void *), void* arg);
}BluetoothCallback,*pBluetoothCallback;

這個函數結構體裡的回呼函數在JNI中實現,我們來看看電話打入的時候上報電話號碼的這個回呼函數:

static void telephoneIn_callback(telephoneIn *callIn)
{
JNIEnv* env = AndroidRuntime::getJNIEnv();
jstring number = env->NewStringUTF(callIn->number);

dbg(DBG_DEBUG," JNI telephoneIn_callback");
//調用java方法上報資料
env->CallVoidMethod(mBTCallbackObj,method_reportCallIn,callIn->Len,number);

if(number)
env->DeleteLocalRef(number);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
}

這裡mBTCallbackObj(jobject)是在java調用jni初始化的時候賦值的,應該是獲得對應的java類,而method_reportCallIn(jmethodID)是獲得的java中對應的java方法ID,如下:

static void android_location_BlueToothLocationProvider_class_init_native(JNIEnv* env, jclass clazz) 
{
method_reportCallIn = env->GetMethodID(clazz, "telephoneCallIn", "(ILjava/lang/String;)V");
method_reportState = env->GetMethodID(clazz, "bluetoothState", "(I)V");
method_reportVol = env->GetMethodID(clazz, "reportVol", "(II)V");
method_reportConnect = env->GetMethodID(clazz,"reportConnect","(Ljava/lang/String;[I)V");
method_reportMatch = env->GetMethodID(clazz,"reportMatch","(ILjava/lang/String;[I)V");
method_reportPhoneBook = env->GetMethodID(clazz,"reportPhoneBook","(IILjava/lang/String;Ljava/lang/String;)V");
method_reportDailNum = env->GetMethodID(clazz,"reportDailNumber","(Ljava/lang/String;)V");
}

再來看看jni中建立java線程的回呼函數:

static pthread_t bluetooth_thread_callback(const char* name, void (*start)(void *), void* arg)
{
return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
}

在相應的java類中電話打入的時候,號碼上報的方法如下:

    /**
* called from native code to update call in telephone number
*/
private void telephoneCallIn(int numberLen, String number)
{
if(DEBUG)
Log.v(TAG, "telephoneCallIn number: " + number);

if(numberLen <= 0)
Log.e(TAG,"telpphone call in,but the phone number is null");

if(number != null)
{
// send an intent to notify there is a telephone call in.
Intent intent = new Intent(TELEPHONE_CALLIN_ACTION);
intent.putExtra(EXTRA_BT_PHONENUMBER, number);
mContext.sendBroadcast(intent);
}

}

最後再來看看HAL中是如何通過這個回呼函數上報資料的,當解析得到電話打入時,將會進入到如下黃色標註的這部分代碼上報打入的電話號碼:

static void processCharacterI(pBluetooth bt,const uuint8 *data)
{
const uuint8 *pdata = data;

dbg(DBG_DEBUG,"processCharacterI : %s",pdata);

switch(*pdata)
{
case 'D':
{
telephoneIn callIn;

memset(&callIn,0,sizeof(telephoneIn));

callIn.Len = (*(++pdata)-0x30)*10;
callIn.Len += *(++pdata)-0x30;
callIn.number = ++pdata;
BLUETOOTH_CALLIN_CB(bt->callback,callIn);
}
break;

case 'S':
BLUETOOTH_STATE_CB(bt->callback,uartInitOK);
break;

case 'C':
{
phoneNumber CallOut;
uuint32 tmp=0;

memset(&CallOut,0,sizeof(phoneNumber));

tmp = (*(++pdata)-0x30)*10;
tmp += *(++pdata)-0x30;
CallOut.nameLen = tmp;

CallOut.number = ++pdata;

BLUETOOTH_CALLOUT_CB(bt->callback,CallOut);
}
break;

default:
LOGW(" Unknow command : I%s",pdata);
break;
}
}

其中BLUETOOTH_CALLIN_CB這個是如下定義的:

#define BLUETOOTH_CALLIN_CB(_cb,_in)    \
if((_cb).callIn_bt){ \
(_cb).callIn_bt(&(_in)); \
}

這樣完整的資料上報鏈路就已經打通了,當有相應的資料從串口發送出來時就會通過這套回呼函數將資料上報至java方法中,最後在java方法中通過廣播發給對應的監聽者!

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.