32

How do I read all SMSes from a particular sender to me? E.g. I want to scan a) the body, and b) the date/time of all SMSes that came from 'TM-MYAMEX' to the phone.

Some websites seem to indicate this can be read from "content://sms/inbox". I couldn't figure out exactly how. Also not sure if it is supported on most phones. I am using a Galaxy S2.

KalEl
  • 8,978
  • 13
  • 47
  • 56

5 Answers5

47

try this way:

StringBuilder smsBuilder = new StringBuilder();
       final String SMS_URI_INBOX = "content://sms/inbox"; 
        final String SMS_URI_ALL = "content://sms/";  
        try {  
            Uri uri = Uri.parse(SMS_URI_INBOX);  
            String[] projection = new String[] { "_id", "address", "person", "body", "date", "type" };  
            Cursor cur = getContentResolver().query(uri, projection, "address='123456789'", null, "date desc");
             if (cur.moveToFirst()) {  
                int index_Address = cur.getColumnIndex("address");  
                int index_Person = cur.getColumnIndex("person");  
                int index_Body = cur.getColumnIndex("body");  
                int index_Date = cur.getColumnIndex("date");  
                int index_Type = cur.getColumnIndex("type");         
                do {  
                    String strAddress = cur.getString(index_Address);  
                    int intPerson = cur.getInt(index_Person);  
                    String strbody = cur.getString(index_Body);  
                    long longDate = cur.getLong(index_Date);  
                    int int_Type = cur.getInt(index_Type);  

                    smsBuilder.append("[ ");  
                    smsBuilder.append(strAddress + ", ");  
                    smsBuilder.append(intPerson + ", ");  
                    smsBuilder.append(strbody + ", ");  
                    smsBuilder.append(longDate + ", ");  
                    smsBuilder.append(int_Type);  
                    smsBuilder.append(" ]\n\n");  
                } while (cur.moveToNext());  

                if (!cur.isClosed()) {  
                    cur.close();  
                    cur = null;  
                }  
            } else {  
                smsBuilder.append("no result!");  
            } // end if  
            }
        } catch (SQLiteException ex) {  
            Log.d("SQLiteException", ex.getMessage());  
        }  

AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_SMS" />
Parag Chauhan
  • 35,760
  • 13
  • 86
  • 95
ρяσѕρєя K
  • 132,198
  • 53
  • 198
  • 213
  • 3
    It works very well thanks! i even tried with the "IN" clause and it works as expected...but...what about address format? In the "sql where" statement, if i search the address "3485152182" it works, but if i search for "348 5152182" or "348 5152 182" or "+393485152182" (same address with international prefix), the query 'll fail. Is there an elegant way to resolve this kind of problem? thanks! – GiveEmTheBoot Dec 16 '12 at 21:19
  • 1
    @GiveEmTheBoot : i think there is no common way to do this you can just use some string method's like "348 5152 182" in this case you can first trim this number then search it or "+393485152182 case you first remove "+" sign from number then search it – ρяσѕρєя K Dec 16 '12 at 22:59
  • @ProsperK...thank u very much! I was hoping in a simplier and elegant way to do this...maybe if sms addresses are stored in the same way/format of the ones in the contacts, i can achieve better my goal. Someone knows that? – GiveEmTheBoot Dec 18 '12 at 19:13
  • I'd like to know if the addresses stored in the field "address" of the sms table are the same to the ones stored in the contacts table. If my contact "Jack" has "348 8591236" as phone number in my contacts, do my sms table 'll contain contain exactly "348 8591236" in the address field? I hope i've been clearer now. – GiveEmTheBoot Dec 18 '12 at 19:36
  • 1
    @GiveEmTheBoot : yes you are right as number is stored in Contact List same user will see in SMS List if SMS is coming form same number . – ρяσѕρєя K Dec 18 '12 at 19:43
  • The first is to use this sql where clause "strrev(address) like " + android.telephony.PhoneNumberUtils.toCallerIDMinMatch("3435158138") + "%". It simply reverse the last N numbers of the phone number. – GiveEmTheBoot Dec 22 '12 at 21:14
  • Orelse use the sql function PHONE_NUMBERS_EQUAL in this way: "PHONE_NUMBERS_EQUAL(address, "3435158138")". This sql function works perfectly (it's used in a huge number of class in android such as ContactInfoCache) but it's part of non-public API, and so it's better to use it only if extremely necessary. – GiveEmTheBoot Dec 22 '12 at 21:15
  • @ρяσѕρєяK what does `type` represents in `projection` array? – Gopal Gopi Mar 22 '14 at 06:56
  • @ρяσѕρєяK can run it as a service and keep a tab on the incoming sms. – Sagar Devanga Jan 15 '15 at 06:11
  • @GopalGopi : `type` represents `MESSAGE_TYPE_SENT` (const value = 2), `MESSAGE_TYPE_INBOX` (const value = 1) etc. (https://developer.android.com/reference/android/provider/Telephony.TextBasedSmsColumns.html#MESSAGE_TYPE_DRAFT) – Bugs Happen Aug 24 '16 at 11:32
  • Can we pass more that one number or array to address. To get all the messages from that numbers @ρяσѕρєяK – Anjali Patel Oct 06 '17 at 08:21
  • how to add multiple conditions. i want to put address and date conditions (uri, projection, "address='123456789'", null, "date desc"); here address is only condition, i want only today's messages also from specific number – Usman Feb 07 '18 at 10:06
  • I have 2 sims in my phone! Is it possible to check which sim is receiving message? – Huzaifa Asif Oct 03 '19 at 07:07
3

try this, its a easy way for reading message from inbox.

public class ReadMsg extends AppCompatActivity {

ListView listView;
private static final int PERMISSION_REQUEST_READ_CONTACTS = 100;
ArrayList smsList;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_read_msg);
    listView = (ListView)findViewById(R.id.idList);

    int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS);

    if (permissionCheck == PackageManager.PERMISSION_GRANTED){
        showContacts();
    }else{
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_SMS},PERMISSION_REQUEST_READ_CONTACTS);
    }
}

private void showContacts() {
    Uri inboxURI = Uri.parse("content://sms/inbox");
    smsList = new ArrayList();
    ContentResolver cr = getContentResolver();


    Cursor c = cr.query(inboxURI,null,null,null,null);
    while (c.moveToNext()){
        String Number = c.getString(c.getColumnIndexOrThrow("address")).toString();
        String Body= c.getString(c.getColumnIndexOrThrow("body")).toString();
        smsList.add("Number: "+ Number + "\n" + "Body: "+ Body );
    }
        c.close();
    ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, smsList);
    listView.setAdapter(adapter);
}

}

Add this permission into Manifests.

<uses-permission android:name="android.permission.READ_SMS"></uses-permission>
Tabish khan
  • 772
  • 8
  • 11
2
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        inbox = (Button) findViewById(R.id.inbox);
        list = (ListView) findViewById(R.id.list);
        arlist = new ArrayList<String>();
        inbox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Uri inboxUri = Uri.parse("content://sms/inbox");
                String[] reqCols = {"_id", "body", "address"};
                ContentResolver cr = getContentResolver();
                Cursor cursor = cr.query(inboxUri, reqCols, "address='+919456'", null, null);
                adapter = new SimpleCursorAdapter(getApplicationContext(), R.layout.msg_content_layout, cursor,
                        new String[]{"body", "address"}, new int[]{R.id.txt1, R.id.txt2});
                list.setAdapter(adapter);
            }
        });

    }

Here I have added the number +919456 as the value of the address field.

Apart from this you need to add the READ_SMS permission to manifest:

ivarni
  • 17,658
  • 17
  • 76
  • 92
Anubhav
  • 1,984
  • 22
  • 17
  • Will this match a phone number, in any of its formats, with spaces and without, with the international country code and without? – Flimm Nov 23 '18 at 16:01
2

you can do this in few line of code

String[] phoneNumber = new String[] { "+923329593103" }; 
Cursor cursor1 = getContentResolver().query(Uri.parse("content://sms/inbox"), new String[] { "_id", "thread_id", "address", "person", "date","body", "type" }, "address=?", phoneNumber, null);
                 StringBuffer msgData = new StringBuffer();
                if (cursor1.moveToFirst()) { 
                    do {


                       for(int idx=0;idx<cursor1.getColumnCount();idx++)
                       {
                           msgData.append(" " + cursor1.getColumnName(idx) + ":" + cursor1.getString(idx));
                       }

                    } while (cursor1.moveToNext());
                } else {

                     edtmessagebody.setText("no message from this contact"+phoneNumber);
                }
Adiii
  • 54,482
  • 7
  • 145
  • 148
  • Will this match a phone number, in any of its formats, with spaces and without, with the international country code and without? – Flimm Nov 23 '18 at 16:02
1
public class SmsController extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
SmsMessage msgs[] = null;
Bundle bundle = intent.getExtras();
try {
    Object pdus[] = (Object[]) bundle.get("pdus");
    msgs = new SmsMessage[pdus.length];
    for (int n = 0; n < pdus.length; n++) {
        byte[] byteData = (byte[]) pdus[n];
        msgs[n] = SmsMessage.createFromPdu(byteData);
    }
} catch (Exception e) {

}
for (int i = 0; i < msgs.length; i++) {
    String message = msgs[i].getDisplayMessageBody();
    if (message != null && message.length() > 0) {
        String from = msgs[i].getOriginatingAddress();
        if(FROM.contains("TM-MYAMEX")){
            String  body = message ;
            Date datetime = new Date() ;
            } 
        }
    }
  }
 }
}

I'm not sure of what does "TM-MYAMEX" means but here is the code to get all SMS.

Date = new Date()beacause its under a BroadcastReceiverthen the tme you get the message its the current time.

Hope this help.

113408
  • 3,364
  • 6
  • 27
  • 54
  • **TM-MYAMEX** means this message is received from American Express. I just wanted to know if you pass this value in the address while quering like this `cr.query(inboxUri, null, "address='TM-MYAMEX'", null, null);` returns 0 SMS. Does anyone know how to get SMS from these senders?? – yashhy Apr 14 '17 at 12:07