1

I am trying to pass a database value to Java via JNI :

__android_log_print(ANDROID_LOG_ERROR, "MyApp", "c_string >>> %s", cStringValue);

prints : c_string >>>

env->SetObjectField(jPosRec, myJniPosRec->_myJavaStringValue, env->NewStringUTF(strdup(cStringValue)));  

However, this fails without errors.

How can you go about passing special characters (such as emojis) to Java in JNI?

Thank you all in advance.

Community
  • 1
  • 1
Program-Me-Rev
  • 6,184
  • 18
  • 58
  • 142

2 Answers2

5

Cribbing from my answer here, you can use the JNI equivalent of

Charset.forName("UTF-8").decode(bb).toString()

as follows, where each paragraph roughly implements one step, and the last sets your object field to the result:

jobject bb = env->NewDirectByteBuffer((void *) cStringValue, strlen(cStringValue));

jclass cls_Charset = env->FindClass("java/nio/charset/Charset");
jmethodID mid_Charset_forName = env->GetStaticMethodID(cls_Charset, "forName", "(Ljava/lang/String;)Ljava/nio/charset/Charset;");
jobject charset = env->CallStaticObjectMethod(cls_Charset, mid_Charset_forName, env->NewStringUTF("UTF-8"));

jmethodID mid_Charset_decode = env->GetMethodID(cls_Charset, "decode", "(Ljava/nio/ByteBuffer;)Ljava/nio/CharBuffer;");
jobject cb = env->CallObjectMethod(charset, mid_Charset_decode, bb);

jclass cls_CharBuffer = env->FindClass("java/nio/CharBuffer");
jmethodID mid_CharBuffer_toString = env->GetMethodID(cls_CharBuffer, "toString", "()Ljava/lang/String;");
jstring str = env->CallObjectMethod(cb, mid_CharBuffer_toString);

env->SetObjectField(jPosRec, myJniPosRec->_myJavaStringValue, str);  
Botje
  • 26,269
  • 3
  • 31
  • 41
1

First off, you are leaking the memory allocated by strdup(). You need to pass the char* pointer from strdup() to free() when you are done using it. However, there is no need to call strdup() in this situation at all, you can pass cStringValue directly to JNI's NewStringUTF() function.

That said, JNI's NewStringUTF() function requires the input C string to be in "modified" UTF-8 format, which standard C++ knows nothing about. While it is possible to create a C string in that format, you will have to do so manually. Since Java strings use a UTF-16 interface, and standard C++ has facilities to work with UTF-16 strings, I strongly suggest you use JNI's NewString() function instead.

If your database code allows you to retrieve strings in UTF-16 format, then you are all set. If not, you will have to convert the strings to UTF-16 before passing them to NewString() (just as you would have to convert them to "modified" UTF-8 if you continue using NewStringUTF()).

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770