Search code examples
androidsmspdu

Why does `SmsMessage.createFromPdu` return an array?


In Android, if I want to read an incoming SMS, I would use SmsMessage.createFromPdu, but this returns an array of SmsMessages. Why is that? Why not just a single SmsMessage? Is it because long messages could be divided into several? If so, does that mean I can count on all these SmsMessages to have the same originating address?


Solution

  • After doing tons of research, here's the deal:

    Yes, these messages that you get are the broken down pieces of a larger message.

    The array of SmsMessages contains messages that may or may not be related to each other (different senders). Why Android mixes them up like that? I don't know. You should always loop through them and group them by SmsMessage.getDisplayOriginatingAddress(). Then, for each group of messages, append their bodies from SmsMessage.getDisplayMessageBody() to reconstruct the larger message.

    Here's an example from the GTalk app source (thanks @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;
    }