19

I'm developing an SMS program and I want to get conversations.
I wrote the code below and it works fine, but I wonder if it could be more efficient

This is for geting conversation threads

       Uri SMS_INBOX = Uri.parse("content://sms/conversations/");
    Cursor c = getContentResolver().query(SMS_INBOX, null, null, null, "date desc");

        startManagingCursor(c);
        String[] count = new String[c.getCount()];
        String[] snippet = new String[c.getCount()];
        String[] thread_id = new String[c.getCount()];

        c.moveToFirst(); 
        for (int i = 0; i < c.getCount(); i++) {
            count[i] = c.getString(c.getColumnIndexOrThrow("msg_count"))
                    .toString();
            thread_id[i] = c.getString(c.getColumnIndexOrThrow("thread_id"))
                    .toString();
            snippet[i] = c.getString(c.getColumnIndexOrThrow("snippet"))
                    .toString();
            //Toast.makeText(getApplicationContext(), count[i] + " - " + thread_id[i]+" - "+snippet[i] , Toast.LENGTH_LONG).show();
            c.moveToNext();
        }
        c.close();

for getting addresses according to conversation thread

    for(int ad = 0; ad < thread_id.length ; ad++)
    {
    Uri uri = Uri.parse("content://sms/inbox");
    String where = "thread_id="+thread_id[ad]; 
    Cursor mycursor= getContentResolver().query(uri, null, where ,null,null); 
    startManagingCursor(mycursor);

    String[] number = new String[mycursor.getCount()];


    if(mycursor.moveToFirst()){
            for(int i=0;i<mycursor.getCount();i++){
                    number[i]=mycursor.getString(mycursor.getColumnIndexOrThrow("address")).toString();

                    mycursor.moveToNext();
            }
    }
    mycursor.close();

and finally checking the adresses (if in contact list) and adding to a list

     for(int i =0 ; i < numaralar.length ;i++)
    {


    String a = numaralar[i].substring(0,1);



    if(!a.equals("+")){ kisiismi = numaralar[i]; }


    ContentResolver localContentResolver = getApplicationContext().getContentResolver();
       Cursor contactLookupCursor =  
        localContentResolver.query(
                 Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, 
                 Uri.encode(numaralar[i])), 
                 new String[] {PhoneLookup.DISPLAY_NAME, PhoneLookup._ID}, 
                 null, 
                 null, 
                 null);
        try {
        while(contactLookupCursor.moveToNext()){
             String contactName = contactLookupCursor.getString(contactLookupCursor.getColumnIndexOrThrow(PhoneLookup.DISPLAY_NAME));
             kisiismi = contactName;
         }
        }catch (Exception e) {
         kisiismi = numaralar[i].toString(); 

        }
          finally {
              //Toast.makeText(getApplicationContext(), ad + kisiismi + " " + count[ad], Toast.LENGTH_LONG).show();
              myArr.add(kisiismi);
              contactLookupCursor.close();
         }

    }    

Are there any way to make this process easier?

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Sercan Aktan
  • 231
  • 2
  • 6
  • Is it possible to get the conversation between the two user(me and who send me msg) from Conversations = "content://sms/conversations". if so how ? – Developer Jan 09 '13 at 19:28
  • 8
    This should have not been closed. The user is clearly asking for an efficient way to get the Threads of messages according to the contact number or name, just as the native message application does. I would also like an answer for that – Parvaz Bhaskar Aug 04 '13 at 08:36
  • 6
    I agree, this should not have been closed. Hopefully someone can at least answer in the form of a comment... – Pkmmte Sep 29 '13 at 02:38
  • perhaps it would get better responses on http://codereview.stackexchange.com/? – Uri Agassi Apr 05 '14 at 07:04
  • I made it this way: https://stackoverflow.com/a/53575165/3557894 – nuamehas Dec 01 '18 at 21:45

2 Answers2

1

Since it is a simple SQLite query and the Contact provider can be accessed in a similar way, you should try to get the job done in SQL by GROUPING via number, timestamp and maybe thrad_id and then matching the results to a query to the contact provider (also via SQLite)

The documentation holds a pretty good description of all available columns. https://developer.android.com/reference/android/provider/ContactsContract.PhoneLookupColumns.html

DooMMasteR
  • 277
  • 2
  • 13
  • Unfortunately, not. Content Providers don't expose grouping clauses. Unless it has a specific URI for this extra purpose, you're out of luck; you need to go the long route, that is... – Gábor Jan 12 '15 at 16:00
1

From KitKat onwards, we have a specific Uri for this: content://mms-sms/messages/byphone. But before that, this is what we can come up with:

Set<Integer> conversationIds = new HashSet<Integer>();
String numbers = "+xxxxxxxxxx,+yyyyyyyyyy";

final String[] PROJECTION = { Sms._ID, Sms.THREAD_ID };
final String SELECTION = Sms.ADDRESS + " IN (" + numbers.replaceAll("[^,]+", "?") + ")";
final String[] selectionArgs = numbers.split(",");

Cursor cursor = context.getContentResolver().query(Sms.CONTENT_URI, PROJECTION, SELECTION, selectionArgs, null);
int threadColumn = cursor.getColumnIndexOrThrow(Sms.THREAD_ID);

while (cursor.moveToNext())
  conversationIds.add(cursor.getInt(threadColumn));
cursor.close();

return conversationIds;

There is no easy way to do the same with MMS messages because they don't keep their address in the database, you have to query each and every one separately. If you need to do it repeatedly, a viable solution is to cache MMS-to-phone number relations in a database of your own.

You can then use the identifiers accumulated in conversationIds to query the individual conversations. Note that if you want to merge different coversations belonging to the same contact, you can reuse the same query selection pattern above with passing in all ids as IN (?,...,?) at once.

Gábor
  • 9,466
  • 3
  • 65
  • 79