为什么 `SmsMessage.createFromPdu` 返回一个数组?

4
在Android中,如果我想读取收到的短信,我将使用SmsMessage.createFromPdu,但这将返回一个SmsMessage数组。为什么会这样呢?难道不应该只有一个单独的SmsMessage吗?是因为长短信可能被分成几个部分吗?如果是这样,那么这些SmsMessage是否都具有相同的发件人地址?
2个回答

4
经过大量的研究,以下是答案:

是的,您收到的这些消息是更大信息的分解部分。

SmsMessage数组包含可能与彼此无关(不同的发送者)的消息。安卓为什么会混淆它们?我不知道。您应该始终通过SmsMessage.getDisplayOriginatingAddress()循环遍历它们并将它们按组分组。然后,对于每组消息,从SmsMessage.getDisplayMessageBody()附加它们的正文以重建更大的消息。

以下是来自GTalk应用源代码的示例(感谢@hungryghost):
private static Map<String, String> RetrieveMessages(Intent intent) {
    Map<String, String> msg = null; 
    SmsMessage[] msgs;
    Bundle bundle = intent.getExtras();

    if (bundle != null && bundle.containsKey("pdus")) {
        Object[] pdus = (Object[]) bundle.get("pdus");

        if (pdus != null) {
            int nbrOfpdus = pdus.length;
            msg = new HashMap<String, String>(nbrOfpdus);
            msgs = new SmsMessage[nbrOfpdus];

            // There can be multiple SMS from multiple senders, there can be a maximum of nbrOfpdus different senders
            // However, send long SMS of same sender in one message
            for (int i = 0; i < nbrOfpdus; i++) {
                msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);

                String originatinAddress = msgs[i].getDisplayOriginatingAddress();

                // Check if index with number exists                    
                if (!msg.containsKey(originatinAddress)) { 
                    // Index with number doesn't exist                                               
                    // Save string into associative array with sender number as index
                    msg.put(msgs[i].getOriginatingAddress(), msgs[i].getDisplayMessageBody()); 

                } else {    
                    // Number has been there, add content but consider that
                    // msg.get(originatinAddress) already contains sms:sndrNbr:previousparts of SMS, 
                    // so just add the part of the current PDU
                    String previousparts = msg.get(originatinAddress);
                    String msgString = previousparts + msgs[i].getMessageBody();
                    msg.put(originatinAddress, msgString);
                }
            }
        }
    }

    return msg;
}

1
它返回一个数组,以支持连接的多部分短信(用于超过正常 ~160 字符限制的消息)。每个消息可能具有不同的原始地址,具体取决于它们是否共享相同的标头信息。

http://en.wikipedia.org/wiki/Concatenated_SMS

http://en.wikipedia.org/wiki/Protocol_data_unit

短信可能不按顺序发送,并且可能来自不同的发送者。请参考以下链接,了解如何连接多部分短信,其中包括一个良好的代码示例。

如何处理多部分短信的讨论

用于连接PDU的gtalksms代码


谢谢。另外,数组中的消息是否按正确顺序排列?在第一篇文章中,它说消息很难按正确顺序到达。Android 是否会在我获取数组时处理好这个问题? - AxiomaticNexus
抱歉,我可能错了。在重建您的多部分短信时,您应该检查原始地址。我已编辑答案并添加了描述该过程的链接。 - hungryghost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接