我正在开发一个android sms网关项目,它接收来自不同国家/地区的客户端应用程序的短信。在客户端应用程序中,我使用{, }, [
和]
来标识作为SMS发送到网关的消息的某些部分的开头和结尾。如this链接中所示,这些字符是转义的特殊字符。有时,网关收到的短信无法解码转义字符,它将分别显示为_(, _), _<
和_>
。这可以通过以下方式处理。
我不想采用选项1,因为解决方案不会向后兼容,支持产品可能会变得困难。
我想采取选项2,但我不确定我究竟能做到这一点。特别是,我不确定可以使用哪些不同的转义字符(_
是其中之一)以及如何检测转义码。
这个问题主要出现在越野短信中。
非常感谢任何帮助。
答案 0 :(得分:3)
您有几个选择:
使用Android短信解码系统(相对较好,不完美但足够好)
遵循GSM规范,您可以进行以下解码:
在解码每个字符时,您必须验证字符是否是“默认字符集”的一部分,或者它是否是“扩展字符集”的转义。转义字符为 0x1B ,这告诉解码器,然后下一个字符必须来自“扩展字符集”。如果您的解码器没有找到该字符在“扩展字符集”中,那么通过GSM规范,它必须首先尝试在“默认字符集”中找到该字符。如果它也不在“默认字符集”中,则必须使用空格字符。
例如:
if (escaped) {
char ext = (char) GSMUtils.BYTE_TO_CHAR_ESCAPED[val];
// if no character defined then do fall back
ext = ext != -1 ? ext : (char) GSMUtils.BYTE_TO_CHAR[val];
// if no character defined then fall back to <space>
return ext != -1 ? ext : ' ';
} else {
char ch = (char) GSMUtils.BYTE_TO_CHAR[val];
// if no character defined then fall back to <space>
return ch != -1 ? ch : ' ';
}
其中GSMUtils.BYTE_TO_CHAR_ESCAPED和GSMUtils.BYTE_TO_CHAR是int []的
private static final int[] BYTE_TO_CHAR = {
0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC,
0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5,
0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
0x03A3, 0x0398, 0x039E, 0x00A0, 0x00C6, 0x00E6, 0x00DF, 0x00C9,
0x0020, 0x0021, 0x0022, 0x0023, 0x00A4, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
0x00A1, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0x0058, 0x0059, 0x005A, 0x00C4, 0x00D6, 0x00D1, 0x00DC, 0x00A7,
0x00BF, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007A, 0x00E4, 0x00F6, 0x00F1, 0x00FC, 0x00E0,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
};
和
private static final int[] BYTE_TO_CHAR_ESCAPED = {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, 0x000C, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 0x005E, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
0x007B, 0x007D, -1, -1, -1, -1, -1, 0x005C,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 0x005B, 0x007E, 0x005D, -1,
0x007C, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 0x20AC, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
};
我可能会补充说,解码问题不一定只是一个跨国问题。由于扩展字符集中有许多字符经常用于国家短信中。
Here是来自3GPP的信息的根源,指定如何处理默认/扩展字符集。特别注意每张桌子下面的笔记!!