emoji表情引发的JNI崩溃
今天突然接到客服那邊的反饋說,有玩家反饋進游戲后不久就崩潰了,我先是懷疑網(wǎng)絡(luò)問題,因為一連接聊天成功后就掛了。之后用logcat抓日志,發(fā)現(xiàn)掛在jni那里了
JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0xf0
string: ''
in call to NewStringUTF
from void org.cocos2dx.lib.Cocos2dxRenderer.nativeRender()
?
調(diào)用JNI的NewStringUTF方法就掛了,然后讓后臺把聊天日志全部拉出來,另存為html放到mac機上查看。發(fā)現(xiàn)一個特殊的表情,如下圖所示:
?
我先讓后臺的同事,把所有聊天信息清理干凈,這時候設(shè)備重新登錄進去沒有問題了。所以確定問題就是這個NewStringUTF方法引起的(但部分設(shè)備上有問題,部分設(shè)備沒問題??戳艘幌潞孟袷茿ndroid5.0及以后的系統(tǒng)就有此問題),問了其它同事,發(fā)現(xiàn)他們之前遇到過并且處理了。
有二種方案:一種是升級NDK,另外一種是C++傳給Java時使用byte[],Java里再把byte[]轉(zhuǎn)成String,避免NewStringUTF導(dǎo)致的崩潰。
?
我用的是cocos2d-x 2.x版本,找到CCImage.cpp文件,修改getBitmapFromJava方法
?
bool getBitmapFromJava(const?char *text, int nWidth, int nHeight, CCImage::ETextAlign eAlignMask, const?char * pFontName, float fontSize){
??? JniMethodInfo methodInfo;
??? if (! JniHelper::getStaticMethodInfo(methodInfo, "org/cocos2dx/lib/Cocos2dxBitmap", "createTextBitmap",
??????? "([BLjava/lang/String;IIII)V"))
??? {
??????? CCLOG("%s %d: error to get methodInfo", __FILE__, __LINE__);
??????? return false;
??? }
??? /**create bitmap
???? * this method call Cococs2dx.createBitmap()(java code) to create the bitmap, the java code
???? * will call Java_org_cocos2dx_lib_Cocos2dxBitmap_nativeInitBitmapDC() to init the width, height
???? * and data.
???? * use this appoach to decrease the jni call number
??? */
??? int strLen = strlen(text);
??? jbyteArray byteArray = methodInfo.env->NewByteArray(strLen);
??? methodInfo.env->SetByteArrayRegion(byteArray, 0, strLen, reinterpret_cast<const jbyte*>(text));
//??????? jstring jstrText = methodInfo.env->NewStringUTF(text);
??? jstring jstrFont = methodInfo.env->NewStringUTF(pFontName);
??? methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, byteArray,
??????? jstrFont, (int)fontSize, eAlignMask, nWidth, nHeight);
//??????? methodInfo.env->DeleteLocalRef(jstrText);
??? methodInfo.env->DeleteLocalRef(byteArray);
??? methodInfo.env->DeleteLocalRef(jstrFont);
??? methodInfo.env->DeleteLocalRef(methodInfo.classID);
??? return true;
}
注釋部分為原來的代碼,將string替換為byte[]再傳給Java即可,其它地方如果也遇到JNI崩潰的問題,也按上面進行修改即可。
符一個字符串與jbyteArray的互轉(zhuǎn)函數(shù)
jbyteArray as_byte_array(unsigned?char* buf, int len) {??? jbyteArray array = env->NewByteArray(len);
??? env->SetByteArrayRegion(array, 0, len, reinterpret_cast<jbyte*>(buf));
??? return array;
}
?
unsigned?char* as_unsigned_char_array(jbyteArray array) {
??? int len = env->GetArrayLength(array);
??? unsigned?char* buf = new?unsigned?char[len];
??? env->GetByteArrayRegion(array, 0, len, reinterpret_cast<jbyte*>(buf));
??? return buf;
}
mysql 5.5之前僅支持3個字節(jié),如果游戲中有留言等功能要存進數(shù)據(jù)庫的記錄,那么你就需要過濾這些字符了,不然就會插入數(shù)據(jù)報錯。
?
更多閱讀鏈接:
JNI UTF-8 encoding bug with some characters
Android ICS 4.0 NDK NewStringUTF is crashing down the App
A correct way to convert byte[] in java to unsigned char* in C++, and vice versa?
emoji處理方式大起底
cocos2d-x android游戲使用自己的字體
Android 上的 制表符(tab) —— 一個神奇的字符 (cocos2dx crash)
Android 上的 制表符(tab) —— 一個神奇的字符 (二)
?
Java Native Interface
C and C++ JNI - University of Cambridge
Java Native Interface
探索在Android中使用Emoji Font的方法
總結(jié)
以上是生活随笔為你收集整理的emoji表情引发的JNI崩溃的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到抱别人家的婴儿是什么意思
- 下一篇: Objective-c 程序结构