如何在Android资源中使用unicode?

我想在我的资源文件中使用这个 Unicode字符。

但无论我做什么,我都以dalvikvm崩溃(Android 2.3和4.2.2testing)结束:

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...) 

我在我的资源文件中试过这些版本:

 <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 --> 

请注意,在代码中使用Javastring工作正常:

 final String geolocation_icon = "\uD83D\uDCE1"; 

您的字符( U+1F4E1 )在Unicode BMP(基本多语言平面 – 范围从U+0000U+FFFF )之外。

不幸的是,Android对非BMP字符的支持非常薄弱(如果有的话)。 非BMP字符的UTF-8表示需要4个字节( 0xF0 0x9F 0x93 0xA1 )。 但是,Android的UTF-8分析器只能理解3个字节的最大值(见这里这里 )。

当你使用这个字符的UTF-16代理forms表示法时,它适用于你: "\uD83D\uDCE1" 。 如果你能够在修改的UTF-8 (又名CESU-8 )中编码每个替代UTF-16字符 – 总共需要6个字节( UTF-8 3个字节用于代理对的每个成员),那么这将是可能的。 但是,Android也不明确支持CESU-8

所以,你现在的解决scheme – 在代码UTF-16对源代码进行硬编码似乎是最简单的,至less在Android开始全面支持非BMP UTF-8

更新 :这似乎是在Android 6.0中部分修复。 此提交已合并到Android 6中,并允许在XML资源中存在4字节的UTF-8字符。 它不是完美的解决scheme – 它会自动将4字节的UTF-8转换为适当的代理对。 但是,它允许将它们从源代码移到XML资源中。 不幸的是,你不能使用这个解决scheme,直到你的应用程序停止支持除6.0和更高版本之外的任何Android版本。

Interesting Posts