12

According to the 4.4 SMS APIs, the new version provides functionality to:

allow apps to read and write SMS and MMS messages on the device

I can't find any information on this functionality, nor any samples in the new SDK. This is what I have so far for reading new incoming messages.

However, I would like to read existing messages stored on the deivce:

// Can I only listen for incoming SMS, or can I read existing stored SMS?
SmsMessage[] smsList = Telephony.Sms.Intents.getMessagesFromIntent(intent);
for(SmsMessage sms : smsList) {
    Log.d("Test", sms.getMessageBody())
}

Please note: I know about using the SMS Content Provider, however this method is unsupported. According to the linked APIs, I should be able to do this in a supported way.

Community
  • 1
  • 1
CodingIntrigue
  • 75,930
  • 30
  • 170
  • 176

3 Answers3

32

It looks like you would be able to use this class to get it working. The package is Telephony.Sms.Conversations.

Although the following code uses the content provider method, this is now an official API added in API Level 19 (KitKat) for reading the SMS messages.

public List<String> getAllSmsFromProvider() {
  List<String> lstSms = new ArrayList<String>();
  ContentResolver cr = mActivity.getContentResolver();

  Cursor c = cr.query(Telephony.Sms.Inbox.CONTENT_URI, // Official CONTENT_URI from docs
                      new String[] { Telephony.Sms.Inbox.BODY }, // Select body text
                      null,
                      null,
                      Telephony.Sms.Inbox.DEFAULT_SORT_ORDER); // Default sort order

  int totalSMS = c.getCount();

  if (c.moveToFirst()) {
      for (int i = 0; i < totalSMS; i++) {
          lstSms.add(c.getString(0));
          c.moveToNext();
      }
  } else {
      throw new RuntimeException("You have no SMS in Inbox"); 
  }
  c.close();

  return lstSms;
}
Joe Birch
  • 371
  • 2
  • 7
hichris123
  • 10,145
  • 15
  • 56
  • 70
  • Fantastic, thank you! It looks like this is the same as the API @longilong posted, except it is now *officially documented* so I'm happy enough to use it. – CodingIntrigue Nov 14 '13 at 08:34
  • If you can update the answer to explain that it is now an official part of the API and show some code, I can mark this as the answer. – CodingIntrigue Nov 14 '13 at 20:06
  • I updated the code on your answer to better illustrate the usage of the new API. Thanks again! – CodingIntrigue Nov 15 '13 at 08:17
  • What URI is used to write sms to sms provider if my app is default sms app? Is there similar documented URI for writing messages to inbox and sent items? – seema Apr 21 '15 at 12:46
  • Telephony.Sms.Inbox.CONTENT_URI provides illegal argument exception Unknown URL while deleting messages from inbox. Any idea how it can be resolved? – seema Apr 22 '15 at 06:50
  • I am getting below compile time error. Field requires API level 19 (current min is 14): android.provider.Telephony.Sms.Inbox#CONTENT_URI . After adding @SuppressLint("NewApi") error resolved. Is it works for older versions? – Prashanth Debbadwar Apr 18 '16 at 11:03
  • how to get address?? – Prashanth Debbadwar Jan 20 '17 at 14:33
  • @hichris123 This works nicely, thanks. But what is the reference to `Telephony.Sms.Conversations` about? The linked document simply shows three string constants and one field. – Old Geezer Sep 27 '17 at 05:12
1

I did it like the following. Create SMSObject:

public class SMSObject {
  private String _id;
  private String _address;
  private String _msg;
  private String _readState; // "0" for have not read sms and "1" for have
                            // read sms
  private String _time;
  private String _folderName;

  //+ getter and setter methods and 

  @Override
  public String toString() {
    return "SMSObject [_id=" + _id + ", _address=" + _address + ", _msg="
            + _msg + ", _readState=" + _readState + ", _time=" + _time
            + ", _folderName=" + _folderName + "]";
}

And here a simple function, which simply logs all current SMS-Objects

private void readSMS() {
    List<SMSObject> lstSms = new ArrayList<SMSObject>();
    SMSObject objSms = new SMSObject();
    Uri message = Uri.parse("content://sms/");
    ContentResolver cr = this.getContentResolver();

    Cursor c = cr.query(message, null, null, null, null);
    // this.startManagingCursor(c);
    int totalSMS = c.getCount();
    Log.d("SMS Count->", "" + totalSMS);
    if (c.moveToFirst()) {
        for (int i = 0; i < totalSMS; i++) {

            objSms = new SMSObject();
            objSms.setId(c.getString(c.getColumnIndexOrThrow("_id")));
            objSms.setAddress(c.getString(c
                    .getColumnIndexOrThrow("address")));
            objSms.setMsg(c.getString(c.getColumnIndexOrThrow("body")));
            objSms.setReadState(c.getString(c.getColumnIndex("read")));
            objSms.setTime(c.getString(c.getColumnIndexOrThrow("date")));
            if (c.getString(c.getColumnIndexOrThrow("type")).contains("1")) {
                objSms.setFolderName("inbox");
            } else {
                objSms.setFolderName("sent");
            }

            lstSms.add(objSms);

            Log.d("SMS at " + i, objSms.toString());

            c.moveToNext();
        }
    }
    // else {
    // throw new RuntimeException("You have no SMS");
    // }
    c.close();

    // return lstSms;

}
longi
  • 11,104
  • 10
  • 55
  • 89
  • 2
    This uses the unsupported `content://sms/` content resolver. The question is specifically about using the Telephony API to do this in a *supported* fashion. – CodingIntrigue Nov 11 '13 at 13:51
  • oh sorry... didn't recognize this – longi Nov 11 '13 at 13:53
  • It wasn't clear from the question, I updated to clarify this :) – CodingIntrigue Nov 11 '13 at 13:54
  • @RGraham I just took a look into the API. It looks like you can only read new SMS, but not already received ones. Since there is only one App managing SMS contents now, this would make sense in a way.. But the documentation is really poor... – longi Nov 13 '13 at 08:47
0

I found this some days ago, can't remember from what site; You can only restore messages if the user has chosen to make the app the default sms app. This may or may not answer your question fully. I haven't tried this yet

  1. Query the current default SMS app's package name and save it.

    String defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(context);
    
  2. Request the user change the default SMS app to your app in order to restore SMS messages (you must be the default SMS app in order to write to the SMS Provider).

    Intent intent = new Intent(context, Sms.Intents.ACTION_CHANGE_DEFAULT);
    intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, context.getPackageName());
    startActivity(intent);
    
Pontus Backlund
  • 1,017
  • 1
  • 10
  • 17
  • Added clarification to the question. I am only interested in *reading* SMS and really would prefer not to set my app as the default SMS app. – CodingIntrigue Nov 11 '13 at 13:26