前文地址:http://blog.csdn.net/andyhuabing/article/details/7551230
问题解决方案三:
重点解决:native函数及jmethodID与jfieldID的大多的问题
对于这点的话,我想到的方案就是利用String对象对参数进行封装,只需要在java端及jni端进行打包
和解析即可,这样子的话函数数目大大减小就只有两个函数了,下面就来看具体解决之案吧。
a、利用xml进行传输
一个典型的xml组织方式:
//-------------------xml---------------
<struct name="BBB">
<member name="abc" type="int"> 334 </member>
<member name="kkk" type="int[]">
<array>444</array>
<array>55</array>
<array>333</array>
<array>25</array>
</member>
<member name="yu" type="struct">
<member name="jii" type="string">hi!</member>
<member name="g44" type="string">word</member>
</member>
<member name="gh" type="struct[]">
<array>
<member name="ab" type="int">777</member>
<member name="cd" type="string">ok</member>
</array>
<array>
<member name="ab" type="int">777</member>
<member name="cd" type="string">ok</member>
</array>
</member>
</struct>
这种格式在C++层利用sprintf组包,利用tinyxml进行解包即可,大概的核心代码如下:
拼包:
char buf[MAX_BUFFER_LEN] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
char *p = buf;
char *q = p;
p += strlen(buf) ;
p += sprintf(p, "<element>\n");
p += sprintf(p, "\t<byMessageType>%d</byMessageType>\n",byMessageType);
p += sprintf(p, "\t<SCDCAPVODBuyInfo>\n");
p += sprintf(p, "\t\t<m_dwProgramID>%d</m_dwProgramID>\n",pPVODBuyInfo->m_dwProgramID);
p += sprintf(p, "\t\t<m_wTvsID>%d</m_wTvsID>\n",pPVODBuyInfo->m_wTvsID);
p += sprintf(p, "\t\t<m_wExpiredDate>%d</m_wExpiredDate>\n",pPVODBuyInfo->m_wExpiredDate);
p += sprintf(p, "\t\t<m_dwOriginalWatchTimes>%d</m_dwOriginalWatchTimes>\n",pPVODBuyInfo->m_dwOriginalWatchTimes);
p += sprintf(p, "\t\t<m_dwOriginalWatchDuration>%d</m_dwOriginalWatchDuration>\n",pPVODBuyInfo->m_dwOriginalWatchDuration);
p += sprintf(p, "\t\t<m_dwOriginalWatchTraffic>%d</m_dwOriginalWatchTraffic>\n",pPVODBuyInfo->m_dwOriginalWatchTraffic);
p += sprintf(p, "\t\t<m_wPrice>%d</m_wPrice>\n",pPVODBuyInfo->m_wPrice);
p += sprintf(p, "\t\t<m_wSlotID>%d</m_wSlotID>\n",pPVODBuyInfo->m_wSlotID);
p += sprintf(p, "\t</SCDCAPVODBuyInfo>\n");
p += sprintf(p, "</element>\n");
static int testXMLParse(const char* buf, const char* filename) {
TiXmlDocument doc;
TiXmlElement* rootelement = 0;
TiXmlElement* itemelement = 0;
TiXmlAttribute* itemAttr;
const char *name = NULL;
const char *value = NULL;
if (buf != NULL) {
doc.Parse(buf);
} else if (filename != NULL) {
doc.LoadFile(filename);
}
if (doc.Error()) {
LOGE("Error in %s: %s\n", doc.Value(), doc.ErrorDesc());
return -1;
}
rootelement = doc.FirstChildElement();
#if 1 //平面式解析通用格式
itemelement = rootelement->FirstChildElement();
while (itemelement != NULL) {
name = itemelement->GetText();
value = itemelement->Value();
LOGV("element name = %s,value=%s \n", name, value);
itemelement = itemelement->NextSiblingElement();
}
#else //嵌套式解析通用格式
while(rootelement != NULL) {
itemelement = rootelement->FirstChildElement();
while (itemelement != NULL) {
name = itemelement->GetText();
value = itemelement->Value();
//TODO
LOGV("element name = %s,value=%s \n",name,value);
if(strcmp("SCDCAIPPVPrice",value) == 0) {
TiXmlElement* itemElement = itemelement->FirstChildElement();
while(itemElement!=NULL) {
itemAttr = itemElement->FirstAttribute();
while (itemAttr != NULL) {
name = itemAttr->Name();
value = itemAttr->Value();
printf("price name = %s,value=%s \n",name,value);
itemAttr = itemAttr->Next();
}
itemElement = itemElement->NextSiblingElement();
}
}
itemAttr = itemelement->FirstAttribute();
while (itemAttr != NULL) {
name = itemAttr->Name();
value = itemAttr->Value();
//TODO
LOGV("attribute name = %s,value=%s \n",name,value);
itemAttr = itemAttr->Next();
}
itemelement = itemelement->NextSiblingElement();
}
rootelement = doc.NextSiblingElement();
}
#endif
return 0;
}
在JAVA层xml解包,常见的XML解析器分别为DOM解析器、SAX解析器和PULL解析器
根据函数调用的特性采用PULL解析器即可,这部分网上大把的代码,在此就不复述了。
b、利用json方式,这种方式更简单
我们与xml格式来个对比,你可以发现它相当的简单,成员"member":value 或 "member":"string"
结构则用"{" + xxx + "}" 表示,数组则加 "[" + yyy + "]"
///-----------------json-------------
"{
"abc":334,
"kkk":[444,55,333,25],
"yu":{
"jii":"hi!",
"g44":"word"
}
"gh":[
{"ab":777,"cd":"ok"},
{"ab":777,"cd":"ok"}
]
}"
///------------- java示例代码---------------
import org.json.JSONTokener;
void aa(){
String json = "{"
+ " \"abc\": \"334\", "
+ " \"kkk\": [ 444,55,333,25 ], "
+ " \"tom\": { \"a\": \"xxx\", \"b\": 100 ,\"c\": [33,44]} "
+ "}";
JSONObject object = (JSONObject) new JSONTokener(json).nextValue();
String query = object.getString("query");
JSONArray locations = object.getJSONArray("locations");
int iv = object.getJSONObject("tom").getInt("b");
String sv= object.getJSONObject("tom").getString("a");
int iv1 = object.getJSONObject("tom").getJSONArray.("c").getInt(1);
}
struct mmm_t {
int a;
int b[4];
struct {
int c1, c2;
} c;
struct {
int d1;
char*d2;
} d[2];
float e;
};
/* 对成员一级级的进行取值,比如取c1值,先取得c结构,然后再取c1和c2 */
int get_struct_mmm1(json_t*p, struct mmm_t*m) {
int i;
json_t*pa = NULL, *po = NULL;
p = mjson_child(p);
m->a = mjson_get_number(p);
pa = mjson_get_array((p = mjson_next(p)));
for (i = 0; i < 4; ++i) {
m->b[i] = mjson_get_array_number(pa);
pa = mjson_next(pa);
}
po = mjson_get_object((p = mjson_next(p)));
m->c.c1 = mjson_get_number(po);
m->c.c2 = mjson_get_number((po = mjson_next(po)));
pa = mjson_get_array((p = mjson_next(p)));
for (i = 0; i < 2; ++i) {
po = mjson_get_array_object(pa);
m->d[i].d1 = mjson_get_number(po);
m->d[i].d2 = mjson_get_string((po = mjson_next(po)));
pa = mjson_next(pa);
}
m->e = mjson_get_float((p = mjson_next(p)));
return 0;
}
/* 对成员直接进取取值,比如取c1,直接使用m.c.c1,取数组m.b[2] */
int get_struct_mmm(json_t*p, struct mmm_t*m) {
int i;
char buf[128];
m->a = mjson_locate_number(p, "a");
for (i = 0; i < 4; ++i) {
sprintf(buf, "b[%d]", i);
m->b[i] = mjson_locate_number(p, buf);
}
m->c.c1 = mjson_locate_number(p, "c.c1");
m->c.c2 = mjson_locate_number(p, "c.c2");
for (i = 0; i < 2; ++i) {
sprintf(buf, "d[%d].d1", i);
m->d[i].d1 = mjson_locate_number(p, buf);
sprintf(buf, "d[%d].d2", i);
m->d[i].d2 = mjson_locate_string(p, buf);
}
m->e = mjson_locate_float(p, "e");
return 0;
}
因此最终的解决方案就是:
只需要定义一个native函数:
private static native String native_call_camodule_methods(String name,String value);
使用json格式传递返回值及函数参数,输入值value传入,输出值通过返回值返回
C++调用JAVA函数,也只使用一个函数
public String CAModuleCallStaticObjectMethod(String Function,String value);
具体的json封包及解析放到单独两个文件中,其余的代码全部可以通用,适合多CA移植功能的apk编写。