Pit*_*tel 42 unicode android utf-8 surrogate-pairs
我想在我的资源文件中使用这个 unicode字符.
但无论我做什么,我都以dalvikvm崩溃结束(使用Android 2.3和4.2.2测试):
W/dalvikvm( 8797): JNI WARNING: input is not valid Modified UTF-8: illegal start byte 0xf0
W/dalvikvm( 8797):              string: ''
W/dalvikvm( 8797):              in Landroid/content/res/StringBlock;.nativeGetString:(II)Ljava/lang/String; (NewStringUTF)
E/dalvikvm( 8797): VM aborting
F/libc    ( 8797): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 8797 (cz.ipex...)
Run Code Online (Sandbox Code Playgroud)
我在资源文件中尝试了这些版本:
<string name="geolocation_icon" translatable="false">📡</string> <!-- HTML -->
<string name="geolocation_icon" translatable="false">\uD83D\uDCE1</string> <!-- escaped unicode -->
<string name="geolocation_icon" translatable="false"></string> <!-- unicode character -->
Run Code Online (Sandbox Code Playgroud)
请注意,在代码中的Java String中使用它可以正常工作:
final String geolocation_icon = "\uD83D\uDCE1";
Run Code Online (Sandbox Code Playgroud)
    mvp*_*mvp 52
你的性格(U+1F4E1)是Unicode BMP外(基本多文种平面-范围U+0000至U+FFFF).
不幸的是,Android对非BMP角色的支持非常弱(如果有的话).UTF-8非BMP字符的表示需要4个字节(0xF0 0x9F 0x93 0xA1).但是,Android UTF-8解析器最多只能理解3个字节(请参见此处和此处).
当你使用UTF-16这个角色的代理形式表示时,它适用于你:"\uD83D\uDCE1".如果你能够UTF-16在修改的UTF-8(aka CESU-8)中编码每个代理字符- 它总共需要6个字节(UTF-8代理对的每个成员有3个字节),那么它就有可能.但是,Android也不CESU-8明确支持.
因此,您当前的解决方案 - 在源代码中将此符号硬编码为代理UTF-16对似乎最简单,至少在Android开始完全支持非BMP之前UTF-8.
更新:这似乎在Android 6.0中得到了部分修复.此提交已合并到Android 6中,并允许在XML资源中存在4字节UTF-8字符.它不是完美的解决方案 - 它只会自动将4字节UTF-8转换为适当的代理对.但是,它允许将它们从源代码移动到XML资源中.遗憾的是,在您的应用程序停止支持除6.0及更高版本之外的任何Android版本之前,您无法使用此解决方案.
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           24408 次  |  
        
|   最近记录:  |