Base64 incompatible with 7-bit GSM encoding?

2.6k Views Asked by At

Since I am not able to compress a 256-byte long md5-like string within 160 characters, I decided to use Multi-part message in Android to divide the SMS into several parts and the receiver will listen the SMS then combine those messages.

I use the combination algorithm from here: Android - receiving long SMS (multipart)

And after a few testing I found that the SMS I sent was totally messed, though I encoded them with Base64 before sending.

Thinking the SMS is a 7-bit Encoding method I thought it might be the encoding problem.

But I have successfully sent Base 64 encoded message, but it was short and within 1 SMS.

My question is:

If it is a encoding problem, then why I can send a totally readable Base64 encoded messages within 160 characters, but cannot get a readable result when sending messages exceeding 160 characters?

I've attached my code here: The string I intend to send:

static final String bigNum = "C196BA05AC29E1F9C3C72D56DFFC6154A033F1477AC88EC37F09BE6C5BB95F51C296DD20D1A28A067CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE428782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE619ECACC7E0B51652A8776D02A425567DED36EABD90CA33A1E8D988F0BBB92D02D1D20290113BB562CE1FC856EEB7CDD92D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BFFAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E5320121496DC65B3930E38047294FF877831A16D5228418DE8AB275D7D75651CEFED65F78AFC3EA7FE4D79B35F62A0402A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83";

The Code

private void sendMsg (String phoneNum, String msg) {
    SmsManager sms = SmsManager.getDefault();
    ArrayList<String> parts = sms.divideMessage(msg);
    sms.sendMultipartTextMessage(phoneNum, null, parts, null, null);
}

public void onStart() {
    super.onStart();
    final String bigNum64 = Base64.encodeToString(bigNum.getBytes(), 0);
    button.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            sendMsg("5554", bigNum64);
            textView.setText(bigNum64);
        }
    });
}

public void onResume() {
    super.onResume();
    Bundle receiver = getIntent().getExtras();
    if (receiver != null) {
        String msg = receiver.getString("SMS");
        textView.setText("Received" + msg);
    }
}
}

The SMS Receiver:

public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
    Bundle bundle = intent.getExtras();
    Object[] pdus = (Object[]) bundle.get("pdus");
    SmsMessage[] messages = new SmsMessage[pdus.length];
    String body = "";
    for (int i = 0; i < pdus.length; i++) {
        messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
    }
    SmsMessage sms = messages[0];
    try {
        if (messages.length == 1 || sms.isReplace()) {
            body = sms.getDisplayMessageBody();

        }
        else {
            StringBuilder bodyText = new StringBuilder();
            for (int i = 0; i < messages.length; i++) {
                bodyText.append(messages[i].getMessageBody());
            }
            body = bodyText.toString();
        }
    }
    catch (Exception e) {

    }
    Intent start = new Intent(context, SendLongSMSActivity.class);
    start.putExtra("SMS", body);
    start.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(start);
}

Thanks for your help!

Related Post: Any way to compress a 256 bytes "MD5-like" string into 160 bytes or less?

Even if I give a rather simple long string, like

"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"

and no matter with or without Base64 encoding, the receiver cannot get the correct results.

UPDATE #2

When using real phone for testing, the receiver can receive correct message without base 64, it was due to the emulator garbled the text.

Question now closed.

Thanks for everyone who helps! And thanx @Dan

UPDATE:

The string "0123456789ABCDEF..." without base64, divided into 2 parts:

part [0]    "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF012345678" 

part [1]    "9ABCDEF0123456789ABCDEF"   

Here's the divided base64 string of the "0123456789ABCDEF...:

part[0] "MDEyMzQ1Njc4OUFCQ0RFRjAxMjM0NTY3ODlBQkNERUYwMTIzNDU2Nzg5QUJDREVGMDEyMzQ1Njc4\nOUFCQ0RFRjAxMjM0NTY3ODlBQkNERUYwMTIzNDU2Nzg5QUJDREVGMDEyMzQ1Njc4OUFCQ0RFRjAx"    

part[1] "\nMjM0NTY3ODlBQkNERUYwMTIzNDU2Nzg5QUJDREVGMDEyMzQ1Njc4OUFCQ0RFRjAxMjM0NTY3ODlB\nQkNERUY=\n"    
1

There are 1 best solutions below

3
On BEST ANSWER

It appears that the sms divide is adding \n characters after every 77 characters and at the end, just strip those from your string and it will decode properly.