Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
呼叫C++;JNI NewStringUTF在使用多种不同的表情符号和语言(除了ascii,但仍然有效修改utf-8)时崩溃android应用程序_Android_C++_Utf 8_Java Native Interface_Cocos2d X - Fatal编程技术网

呼叫C++;JNI NewStringUTF在使用多种不同的表情符号和语言(除了ascii,但仍然有效修改utf-8)时崩溃android应用程序

呼叫C++;JNI NewStringUTF在使用多种不同的表情符号和语言(除了ascii,但仍然有效修改utf-8)时崩溃android应用程序,android,c++,utf-8,java-native-interface,cocos2d-x,Android,C++,Utf 8,Java Native Interface,Cocos2d X,我试图解决安卓5.x上的Cocos2d-x键盘输入崩溃问题,当时我在安卓4.x上用键盘上的许多表情符号(虽然有些有效,但大多数无效)创建了CCImage,其中一些设备只显示损坏的文本/额外字符。崩溃的根源是JNI的NewStringUTF()调用。它根本不支持Android5/Lollipop中所有的2、3和4字节utf-8字符 这个崩溃发生在cocos2d-x v2.2.6(并在3.x上得到确认)上,使用NDK 10e和Toolchain 4.8(不确定是否有任何不同,我们在迁移到Androi

我试图解决安卓5.x上的Cocos2d-x键盘输入崩溃问题,当时我在安卓4.x上用键盘上的许多表情符号(虽然有些有效,但大多数无效)创建了CCImage,其中一些设备只显示损坏的文本/额外字符。崩溃的根源是JNI的NewStringUTF()调用。它根本不支持Android5/Lollipop中所有的2、3和4字节utf-8字符

这个崩溃发生在cocos2d-x v2.2.6(并在3.x上得到确认)上,使用NDK 10e和Toolchain 4.8(不确定是否有任何不同,我们在迁移到Android Studio之前使用的是9d,我肯定我们遇到了这个问题,但棒棒糖的使用量要少得多。)


如果您从未按下任何未修改的utf-8符号(即坚持使用ascii),您可能永远不会看到问题

Log Cat:
    12-11 01:02:17.460 10451-10959/com.appsomniacs.da2.debug A/art: sart/runtime/check_jni.cc:65]     string: 'We found a solution by sending the contents of the std::string in jbyte array and let the java side be java and return the jstring we could use on the C++ jni side. For us these strings are coming from the users keyboard and I have 170k crashes in one week that says they use emoji in character names and chat like crazy... and naming their avatars in itself caused crashes too. So any lobby a Android 5.x user joined would cause them to crash as soon as their client tried to render the other players names with the characters in question. In Android 4.x this was not an issue in that it just printed some garbage characters.

In your c++ side you can do something like this to achieve this function:

jstring JniHelper::getjString(const char *input) {
    JniMethodInfo minfo; // JniHelper

    bool hasMethod = JniHelper::getStaticMethodInfo (minfo, APPTAG_JNI_PACKAGE_NAME, "convertCStringToJniSafeString", "([B)Ljava/lang/String;");
    if (!hasMethod)
    {
        return minfo.env->NewStringUTF(""); // TODO Tune your response to fit your needs...
    }
    else
    {
        string nativeString = std::string(input); // has a bit of a code smell, there is probably a better way.
        // cite: http://stackoverflow.com/questions/27303316/c-stdstring-to-jstring-with-a-fixed-length
        jbyteArray array = minfo.env->NewByteArray(nativeString.length());
        minfo.env->SetByteArrayRegion(array,0,nativeString.length(),(jbyte*)nativeString.c_str());

        // cite: http://discuss.cocos2d-x.org/t/jni-return-string/9982/3
        jstring str = (jstring)minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID, array);
        minfo.env->DeleteLocalRef(array);
        return str;
    }
}
Log Cat:

12111-0902: 17.460 1045 1-10959/COM.AppSoMyNAC.DA2.DESTAG/ART:SART/RunTime/Cuthj.jNi.cc:65)字符串:'

通过在JByl数组中发送STD::string的内容,并让java端为java,返回C++字符串,我们可以在C++ JNI端使用JString。对我们来说,这些字符串来自用户键盘,我在一周内有170k次崩溃,说他们在字符名中使用表情符号,疯狂地聊天。。。而给他们的头像命名本身也导致了崩溃。因此,Android 5.x用户加入的任何游说团都会在他们的客户试图用有问题的角色呈现其他玩家的名字时导致他们崩溃。在Android4.x中,这不是一个问题,因为它只是打印了一些垃圾字符

在你的C++方面,你可以做一些类似的事情来实现这个功能:

public static String convertCStringToJniSafeString(byte[] input) {
    try {
        String nativeString = new String(input, "UTF-8"); // please debate what the safest charset should be?
        return nativeString;
    } catch (UnsupportedEncodingException e) {
        // TODO Simplistic Error handling, tune to your needs.
        Log.e(APPTAG, "Couldn't convert the jbyteArray to jstring");
        return ""; //JSTRING_CONVERT_FAIL
    }
}
在java端,将其转换为java字符串,并以相同的方法返回:

在我们的例子中,我们希望一个jstring(作为修改的UTF8输入)提供给呈现端并存储以供稍后检索,返回空字符串只是我们在转换失败时为提示所做的选择


我希望这能帮助某人找到一种方法。。。甚至可能是正确的方法…

jstring
没有修改UTF-8;这是对标准JVM(Java)字符串的JNI引用,它是UTF-16代码单元的计数序列,其中一个或两个编码Unicode代码点。关于更好的方法的建议非常受欢迎。这只是一个解决方案,似乎能让我度过最糟糕的时刻。我启动了一个单独的项目来对这个解决方案进行单元测试,但还远远没有完成,只开始测试5个键盘。我尝试对2、3和4字节符号进行采样。我希望我选择的框架(开源项目)cocos2d-x能够找到更好的方法。这是在第2次和第3次仍然崩溃时完成的。因此,当我确信它接近于好到足以包含它时,我会提出一些东西。这是一种方法,无论是在Java方面,就像您所做的那样,还是在JNI方面,这都是更乏味的。Tom,感谢您的反馈。我看了几个星期这个问题,我仍然担心它遗漏了什么,但我仍然有信心我得到了大部分优势(仍然需要某种单元测试)。如果在制定真正的长期解决方案的同时,它将撞车率降低了90%(顺便说一句,到目前为止是100%),我对此表示“同意”。我去掉了UTF-8谈话的过度使用。cocos2d-x使用getNewStringUTF()会混淆主要问题。请在jni函数中显示热返回字节数组“如果您从未推送任何未修改的utf-8符号(即坚持使用ascii),您可能永远看不到问题。”是的,如中所述。请告诉我的健谈用户!“不要使用这个符号…我知道它在iOS中工作,但它会使每个Android用户崩溃…”他们认为这很酷…:/我开始剥离字符,然后我意识到几乎每种语言的键盘都会这样做。。。我必须找到更好的办法。汤姆,有什么建议吗?我想这可以归结为避免使用NewStringUTF,尤其是用户提供的数据。