【问题标题】:Why is a "@" being translated to "¿" when sent through SMS on Android 2.3?为什么在 Android 2.3 上通过 SMS 发送“@”会被翻译成“¿”?
【发布时间】:2014-03-17 17:44:27
【问题描述】:

我正在开发一个通过 SMS 向远程设备发送命令的 Android 应用程序。这些命令都是常规的文本消息,其中一些以前缀A@@ 开头。为了测试应用程序,我使用 Android 4.3 手机和 Android 2.3 手机向其他手机发送了一些“命令”。

当我在 Android 4.3 手机上运行该应用程序时,接收端的 SMS 在任何设备上都可以正常显示,但如果我使用 Android 2.3 发送命令,它们会在 Android 4.3 手机上以A¿¿ 形式接收但在 Android 2.3 或 iPhone 上与A@@ 一样正常到达。在目标设备(它使用 GSM 调制解调器)上,消息类似于A(字符“A”加上两个空格 - ASCII 0x20),所以我怀疑发件人使用了不同的编码。我觉得奇怪的是@ 符号甚至不是扩展的 ASCII 字符,所以我想知道为什么它会被编码为 ASCII 以外的其他字符集。

谁能解释这里发生了什么?如果 Android 2.3 设备真的使用了另一种编码,有没有办法在发送 SMS 之前将其强制为 ASCII?

发送代码如下:

@Override
public void sendCommand(String command) {
    //TODO: Send SMS with 'command' as its text message
    SmsManager sms=SmsManager.getDefault();
    PendingIntent piSent=PendingIntent.getBroadcast(this, 0,
                                       new Intent("SMS_SENT"), 0);
    PendingIntent piDelivered=PendingIntent.getBroadcast(this, 0,
                                            new Intent("SMS_DELIVERED"), 0);
    String phone = txtPhone.getText().toString();
    sms.sendTextMessage(phone, null, command, piSent, piDelivered);
}

其中参数command 始终是前缀与其他文本的连接,如下所示:

String SmsPrefix = new String("A@@");
sendCommand(SmsPrefix + "AT+DEACT");

更新:

有人暗示我的问题可能与运营商有关,而不是与 Android 系统本身有关。我住在巴西,我的 Android 2.3 设备使用运营商 TIM,就像我们使用的 iPhone 一样。 Android 4.3 设备使用运营商Claro。我发现,如果我拿到TIM SIM 卡并将其放在Android 4.3 设备上,接收端也会显示乱码@,因此运营商TIM 似乎正在搞乱通过他们发送的短信网络。我将尝试下面@PMunch 的新建议,以便我们可以找到解决方法,但我们可以确定它已经不是从 Android 2.3 到 4.3 更正的某种错误。

【问题讨论】:

  • 使用任何相关代码发布您的发送功能。

标签: android encoding sms


【解决方案1】:

看起来确实是编码问题。可能是您尝试以 ASCII 格式发送,但接收方尝试以不同的编码对其进行解析。如果您在发送方和接收方都明确指定编码,它应该可以工作。

编辑:

这将获取字符数组并使用 US-ASCII 编码从中创建一个字符串。

String newString = new String(oldString.getBytes("US-ASCII"), "US-ASCII"));

EDIT2:

原来 GSM 不使用常规的 US-ASCII,而是使用它自己的 GSM alphabet。似乎正在发生的事情是@(ASCII 0x40)直接转换为 GSM 字母表为¡(倒置感叹号,GSM 0x40)。这不会影响常规文本字符,因为它们共享相同的地址(加号 0x2B 也是如此)。然后,当转换回来时,它会尝试将它假设为 GSM-alphabet 的内容转换为 ASCII,这意味着早期 @ 符号的 0x40 现在是一个倒置的感叹号。这是一个在常规 ASCII 中不存在的符号,因此被一个未知字符符号取代,显然是 Android 2.3 中的一个倒置问号和 GSM 接收器中的一个空格。在 Android 2.3 和 Android 4.3 之间似乎已经修复了从 ASCII 到 GSM 的转换不足的问题。

如果您尝试使用new String ("A@@","ISO-8859-1") 向Android 指定这是一个ASCII 字符串,它可能会自行进行转换。如果不是,您可能必须自己做(this 之类的东西可能会有所帮助)。如果 @ 是您需要支持的唯一特殊字符,那么您当然可以自己编码该单个字符(@@ 为 \0\0)。

EDIT3:

Edit2 包含多个操作,您尝试了什么?解释整个 GSM/ASCII 的东西: ASCII 使用它的前 32 个字符作为控制字符。这些字符被认为对 GSM 来说是不必要的,因此它们被替换为其他字符。用于终止字符串的计算机上的空字符不用于文本消息。它们设置为 140 个八位字节,任何空白空间都简单地用填充字符填充。所以 ASCII 中的空字符 0x00 用于其他东西,@ 字符。如果您查看 GSM 字母表和 ASCII 字母表,您会看到前 32 个字符被希腊字符和其他一些字符替换。如果您查看其余字符,它们大多位于正确的位置,@ 字符就是其中之一。例如,如果您尝试输入_,您应该会得到类似的结果。当您说@A 出现时,您的意思是A@@ 变成A 还是AAA?在查看 Unicode Inc. 提供的 Unicode 转换时,我还发现了一些有趣的东西:

0x00 is NULL (when followed only by 0x00 up to the end of (fixed byte length) message, possibly also up to FORM FEED. But 0x00 is also the code for COMMERCIAL AT when some other character (CARRIAGE RETURN if nothing else) comes after the 0x00.

因此,如果您尝试仅发送A@@,那么最后两个@s 可能会被解释为填充字符而不是@ 字符。无论您所在地区的运营商似乎在它们之间进行了一些转换,您是否尝试将带有sendDataMessage 的字符作为原始数据字节发送?来自 telephony.GsmAlphabet 的函数 byte[] stringToGsm7BitPacked(String data) throws EncodeException 应该有助于将您的字符串转换为 GSM 字母表。

【讨论】:

  • 我想过,但是 sendTextMessage 没有指定编码的参数。尽管String 可以使用string.getBytes("US-ASCII") 之类的方式输出特定的编码,但它会输出一个字节数组,而不是sendTextMessage 所期望的String
  • 如果结果有效,请随时接受我的回答。
  • 不幸的是,关于 EDITEDIT2 的提案都无法修复 @ 字符。使用\0\0 强制GSM 字符集@ 在另一端显示为A。无论如何,我投票赞成将 char 0x40 转换为 ASCII 中的无效字符而其他字符没有的可能解释。但是我们仍然不能确定为什么一些接收运营商的字符错了,而另一些则没有(我测试了从TIMClaroVivo 的发送,它从TIM 到达时搞砸了到TIMTIMOI 它应该到达)。
  • PMunch,问题似乎真的是运营商做的某种映射,因为无论我发送多少@,无论他们是单独还是在一起,每个人都无关紧要被改变。不过我同意你的建议,发送数据短信可以解决问题。假设消息是由二进制数据组成的,即使是一个位的差异也会使其本质上被破坏,因此运营商将它们弄乱是没有意义的。事实上,我刚刚测试了this code,它工作正常,不再搞乱@ 字符。
  • 上述代码的介绍可以看here
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多