I am trying to send a std::map<> from C++ to my Java application through JNI. I have gotten basics to work through JNI such as strings and ints, but I cannot get the map to go through. I have done research and found it needs to be converted to a jobject HashMap. There is no complete answer I found anywhere so I had to piece certain parts of different answers and can't get it to work.
On the C++ side:
void AppAnalytics::sendCustomAction(std::string name, std::map<std::string, std::string> strings, std::map<std::string, int> ints) {
cocos2d::JniMethodInfo methodInfo;
if (! getJNIStaticMethodInfo(methodInfo, "sendCustomAction", "(Ljava/lang/String;java/util/HashMap;java/util/HashMap;)V")) {
return;
}
jclass clazz = methodInfo.env->FindClass("java/util/HashMap");
jmethodID init = methodInfo.env->GetMethodID(clazz, "<init>", "()V");
jobject stringMap = methodInfo.env->NewObject(clazz, init);
jmethodID putMethod = methodInfo.env->GetMethodID(
clazz,
"put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"
);
map<std::string, std::string>::iterator itStr;
for ( itStr = strings.begin(); itStr != strings.end(); itStr++ ) {
const char * firstStr = itStr->first.c_str();
const char * secondStr = itStr->second.c_str();
jstring key = methodInfo.env->NewStringUTF( firstStr );
jstring value = methodInfo.env->NewStringUTF( secondStr );
methodInfo.env->CallObjectMethod(
stringMap,
putMethod,
key,
value
);
}
jobject intMap = methodInfo.env->NewObject(clazz, init);
map<std::string, int>::iterator itInt;
for ( itInt = ints.begin(); itInt != ints.end(); itInt++ ) {
const char * firstStr = itInt->first.c_str();
jstring key = methodInfo.env->NewStringUTF( firstStr );
int value = itInt->second;
methodInfo.env->CallVoidMethod(
intMap,
putMethod,
key,
value
);
}
jstring stringArg = methodInfo.env->NewStringUTF(name.c_str());
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, stringArg, stringMap, intMap);
methodInfo.env->DeleteLocalRef(stringArg);
methodInfo.env->DeleteLocalRef(stringMap);
methodInfo.env->DeleteLocalRef(intMap);
methodInfo.env->DeleteLocalRef(methodInfo.classID);
}
This is on the receiving side on the Java application:
public class AnalyticsHelper {
public static void sendCustomAction(String name, HashMap<String, String> strings, HashMap<String, Integer> ints) {
CustomEvent event = new CustomEvent(name);
for (String key : strings.keySet()) {
event.putCustomAttribute(key, strings.get(key));
}
for (String key : ints.keySet()) {
event.putCustomAttribute(key, ints.get(key));
}
Answers.getInstance().logCustom(event);
}
}
I keep getting this error on the Java side when I trigger the action from within the app:
E/JniHelper: Failed to find static method id of sendCustomAction
Any help would be greatly appreciated. I have tried different combinations of what I have and can never seem to get it though.
Thanks!