Android - Create SMS from PDU deprecated API?
Asked Answered
P

4

27

I want to create an app that gets notified when an SMS arrives and processes that SMS, but reading the reference for the createFromPdu function, it states that:

This method will soon be deprecated and all applications which handle incoming SMS messages by processing the SMS_RECEIVED_ACTION broadcast intent must now pass the new format String extra from the intent into the new method createFromPdu(byte[], String) which takes an extra format parameter. This is required in order to correctly decode the PDU on devices that require support for both 3GPP and 3GPP2 formats at the same time, such as dual-mode GSM/CDMA and CDMA/LTE phones.

However the createFromPdu(byte[], String) function is missing from both the documentation and the SDK.

What should I do? I need to support these dual-sim dual-mode phones.

Pulcheria answered 18/9, 2013 at 15:22 Comment(3)
How about duplicating that method into your own library?Innes
Why you need the method "createFromPdu" to process an incoming sms? I do with a broadcastreceiver and works on every device. What's your real problem?Typhoeus
yes Create SMS from PDU deprecated APIKovrov
F
29

In short, use this:

SmsMessage smsMessage;

if (Build.VERSION.SDK_INT >= 19) { //KITKAT         
    SmsMessage[] msgs = Telephony.Sms.Intents.getMessagesFromIntent(intent);              
    smsMessage = msgs[0];            
} else {             
    Object pdus[] = (Object[]) bundle.get("pdus");             
    smsMessage = SmsMessage.createFromPdu((byte[]) pdus[0]);          
}
Ferguson answered 4/8, 2015 at 18:12 Comment(3)
some devices give me classcastexception on the else condition under bundle.get("pdus")Monanthous
@Monanthous I am about to use this solution, so can you please reply on which api level you get the classcastexception ?Bookstand
It works perfectly fine in both APIs, you just forgot to add Bundle bundle = intent.getExtras(); before creating the pdus[] object. Thank you.Prindle
F
2

You don't mention which Android version you're targeting but given the date of the question I'm assuming Jelly Bean 4.x.

At the time of writing this, we're at Lollipop MR1 and the deprecation note about using createFromPdu with the format parameter still stands:

https://android.googlesource.com/platform/frameworks/opt/telephony/+/android-5.1.0_r3/src/java/android/telephony/SmsMessage.java

Instead of using that API directly however, you can use the Telephony provider API getMessagesFromIntent: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.2_r1/android/provider/Telephony.java/#686

That method considers the PDU format (and the subscription ID in Lollipop for Multi SIM devices) and gives you an array of SmsMessage instances.

An example of how it's used can be seen in Google's MMS app:

https://android.googlesource.com/platform/packages/apps/Mms/+/master/src/com/android/mms/transaction/SmsReceiverService.java (see handleSmsReceived)

Fane answered 8/4, 2015 at 20:58 Comment(1)
I clicked on grepcode.com link and it did not respond...appears to be a dead link.Millrace
T
2

createFromPdu(byte[]) is deprecated from SDK_INT 23 so you have to use

createFromPdu((byte[]) , format);

here is my code to get incoming SMS

i am using SMSReceiver class as an innerclass of an Activity.

this is my working code

public class SamplaActivity extends BaseActivity {
    SMSReceiver otp;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);

        otp=new SMSReceiver();


........
........
    }

  @Override
    protected void onResume() {
        super.onResume();

//        register broadcast receiver
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.provider.Telephony.SMS_RECEIVED");
        registerReceiver(otp, filter);
    }
@Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(otp);
    }

    private class SMSReceiver extends BroadcastReceiver {
        private Bundle bundle;
        private SmsMessage currentSMS;
        private String message;

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

            if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
                bundle = intent.getExtras();
                if (bundle != null) {
                    Object[] pdu_Objects = (Object[]) bundle.get("pdus");
                    if (pdu_Objects != null) {

                        for (Object aObject : pdu_Objects) {

                            currentSMS = getIncomingMessage(aObject, bundle);

                            String senderNo = currentSMS.getDisplayOriginatingAddress();

                            message = currentSMS.getDisplayMessageBody();
                            Toast.makeText(OtpActivity.this, "senderNum: " + senderNo + " :\n message: " + message, Toast.LENGTH_LONG).show();
                        }
                        this.abortBroadcast();
                        // End of loop
                    }
                }
            } // bundle null
        }
    }

private SmsMessage getIncomingMessage(Object aObject, Bundle bundle) {
    SmsMessage currentSMS;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        String format = bundle.getString("format");
        currentSMS = SmsMessage.createFromPdu((byte[]) aObject, format);
    } else {
        currentSMS = SmsMessage.createFromPdu((byte[]) aObject);
    }

    return currentSMS;
}

}
Twopenny answered 27/6, 2016 at 10:28 Comment(0)
F
0

sorry for late response but it may help anyway. apart from checking the android version and if it is above M and extract sing format. I would suggest to use:

compile 'me.everything:providers-android:1.0.1'

Manifest

<uses-permission android:name="android.permission.READ_SMS" />

And in your codes

public List<Sms> mySmses(Context context)throws Exception{
    TelephonyProvider telephonyProvider = new TelephonyProvider(context);
    List<Sms> smses = telephonyProvider.getSms(TelephonyProvider.Filter.INBOX).getList();
    if(smses.isEmpty()){
        throw new Exception("No SMS found");
    }
    return smses;
}

Remember to use AsyncTask to fetch SMSes(consuming the above method) as this is a long running operation. It may crash your app(in certain occasion) if it is executed on the UI thread.

This library saved my time. Hope it will do the same to someone.

Futility answered 11/12, 2017 at 23:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.