Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
129 views
in Technique[技术] by (71.8m points)

java - Create PDU for Android that works with SmsMessage.createFromPdu() (GSM 3gpp)

Goal: (NOTE: The answer selected generates a GSM (3gpp) PDU) for CDMA (3gpp2) please refer here

To create a PDU that can be passed into SmsMessage.createFromPdu(byte[] pdu). I'm "Broadcasting an Intent" to one of my BroadcastReciever that listens for SMS messages.

One BroadcastReciever

Using android.provider.Telephony.SMS_RECEIVED for "real" SMS's

Using a custom intent-filter action for these new "application SMS's".

@Override
public void onReceive(Context context, Intent intent) {

    Bundle bundle = intent.getExtras();

    if (bundle != null) {
        Object[] pdusObj = (Object[]) bundle.get("pdus");
        SmsMessage[] messages = new SmsMessage[pdusObj.length];

        // getting SMS information from Pdu.
        for (int i = 0; i < pdusObj.length; i++) {
            messages[i] = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
        }

        for (SmsMessage currentMessage : messages) {
            //the currentMessage.getDisplayOriginatingAddress() 
            //or .getDisplayMessageBody() is null if I Broadcast a fake sms
            Log.i("BB", "address:"+currentMessage.getDisplayOriginatingAddress()+" message:"+currentMessage.getDisplayMessageBody());
    ...

So I want my BroadcastReciever to be able to handle both types of messages without adding extra code

(yes I know I can have a different BroadcastReciever for the different intent-filter action but I would like to actually pull this off as I know it can be done, I'm stubborn)

Research:

I've been doing research all day/night. I've tried writing my own even though I'm very terrible with the math and conversions and creating a suitable algorithm. I've looked over Stack topics on PDUs, and Create PDU Android but the link is broken in the answer. I even Looked at com.google.android.mms.pdu source code

so far I've only been able to create a PDU without a "originating address" using some code from http://www.wrankl.de/JavaPC/SMSTools.html

PDU:

destination: 555 message: helloworld

"1100038155f50000aa0ae8329bfdbebfe56c32"

Which obviously isn't valid...

Side Notes:

I don't plan on doing anything with the PDU besides local use, I do not want hard coded PDU's in my code because I'm not reusing the PDU.

If there is anything I can add to the code I'm using to add in a "originating address", that will work. Or does anyone have info on a Library I'm not aware of?

Thanks

Updates:

tried

byte[] by =(byte[])(SmsMessage.getSubmitPdu("12345", "1234", "hello", false).encodedMessage);

which gives me the following (in hex representation)

"0000100200000000000000000000000004010203040000000e000320ec400107102e8cbb366f00"

did't work

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Maybe this snippet doesn't have many detail fields like you want but for my simple purpose it can invoke notification like another sms.

    private static void createFakeSms(Context context, String sender,
        String body) {
    byte[] pdu = null;
    byte[] scBytes = PhoneNumberUtils
            .networkPortionToCalledPartyBCD("0000000000");
    byte[] senderBytes = PhoneNumberUtils
            .networkPortionToCalledPartyBCD(sender);
    int lsmcs = scBytes.length;
    byte[] dateBytes = new byte[7];
    Calendar calendar = new GregorianCalendar();
    dateBytes[0] = reverseByte((byte) (calendar.get(Calendar.YEAR)));
    dateBytes[1] = reverseByte((byte) (calendar.get(Calendar.MONTH) + 1));
    dateBytes[2] = reverseByte((byte) (calendar.get(Calendar.DAY_OF_MONTH)));
    dateBytes[3] = reverseByte((byte) (calendar.get(Calendar.HOUR_OF_DAY)));
    dateBytes[4] = reverseByte((byte) (calendar.get(Calendar.MINUTE)));
    dateBytes[5] = reverseByte((byte) (calendar.get(Calendar.SECOND)));
    dateBytes[6] = reverseByte((byte) ((calendar.get(Calendar.ZONE_OFFSET) + calendar
            .get(Calendar.DST_OFFSET)) / (60 * 1000 * 15)));
    try {
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        bo.write(lsmcs);
        bo.write(scBytes);
        bo.write(0x04);
        bo.write((byte) sender.length());
        bo.write(senderBytes);
        bo.write(0x00);
        bo.write(0x00); // encoding: 0 for default 7bit
        bo.write(dateBytes);
        try {
            String sReflectedClassName = "com.android.internal.telephony.GsmAlphabet";
            Class cReflectedNFCExtras = Class.forName(sReflectedClassName);
            Method stringToGsm7BitPacked = cReflectedNFCExtras.getMethod(
                    "stringToGsm7BitPacked", new Class[] { String.class });
            stringToGsm7BitPacked.setAccessible(true);
            byte[] bodybytes = (byte[]) stringToGsm7BitPacked.invoke(null,
                    body);
            bo.write(bodybytes);
        } catch (Exception e) {
        }

        pdu = bo.toByteArray();
    } catch (IOException e) {
    }

    Intent intent = new Intent();
    intent.setClassName("com.android.mms",
            "com.android.mms.transaction.SmsReceiverService");
    intent.setAction("android.provider.Telephony.SMS_RECEIVED");
    intent.putExtra("pdus", new Object[] { pdu });
    intent.putExtra("format", "3gpp");
    context.startService(intent);
}

private static byte reverseByte(byte b) {
    return (byte) ((b & 0xF0) >> 4 | (b & 0x0F) << 4);
}

Hope you will find something useful

Update :

 public static final SmsMessage[] getMessagesFromIntent(
                Intent intent) {
            Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
            byte[][] pduObjs = new byte[messages.length][];

            for (int i = 0; i < messages.length; i++) {
                pduObjs[i] = (byte[]) messages[i];
            }
            byte[][] pdus = new byte[pduObjs.length][];
            int pduCount = pdus.length;
            SmsMessage[] msgs = new SmsMessage[pduCount];
            for (int i = 0; i < pduCount; i++) {
                pdus[i] = pduObjs[i];
                msgs[i] = SmsMessage.createFromPdu(pdus[i]);
            }
            return msgs;
        }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...