Categories
android mms

How to Read MMS Data in Android?

78

I want to read MMS data I have seen the part table in the mmssms.db where the mms entries are stored; I am using a cursor and I want to know the appropriate URI; I am using “content://mms-sms/conversations” and the Column names of “Address”(Sent to), “Text” or “Subject” and “Data” column name of image.

I have seen the schema of mmssms.db and Their Column of part Table.

2

  • The mmssms.db database is part of the firmware and is not accessible by Android applications. The content://mms-sms/conversations content provider is not part of the SDK and should not be accessed by Android applications.

    Jun 10, 2010 at 11:12

  • I am doing something similar HERE! stackoverflow.com/questions/11556633/…

    Jul 30, 2012 at 7:48

11

The answer by Christian is excellent. However, the method for getting the sender’s address did not work for me. The Long.parseLong statement doesn’t do anything except possibly throw an exception and new String(…) ?.

On my device the cursor count is 2 or more. The first typically has a “type” of 137 and the others have a “type” of 151. I cannot find where this is documented, but one can deduce 137 is “from” and 151 is “to”. Thus, if I run the method as is, I do not get an exception, and it returns the last row, which is a recipient and only one of several in many cases.

Also AFAICT the selection is not necessary as all the rows have the same msg_id. However, it doesn’t hurt.

This is what works for me to get the sender’s address:

public static String getMMSAddress(Context context, String id) {
    String addrSelection = "type=137 AND msg_id=" + id;
    String uriStr = MessageFormat.format("content://mms/{0}/addr", id);
    Uri uriAddress = Uri.parse(uriStr);
    String[] columns = { "address" };
    Cursor cursor = context.getContentResolver().query(uriAddress, columns,
            addrSelection, null, null);
    String address = "";
    String val;
    if (cursor.moveToFirst()) {
        do {
            val = cursor.getString(cursor.getColumnIndex("address"));
            if (val != null) {
                address = val;
                // Use the first one found if more than one
                break;
            }
        } while (cursor.moveToNext());
    }
    if (cursor != null) {
        cursor.close();
    }
    // return address.replaceAll("[^0-9]", "");
    return address;
}

I didn’t care about whether it is all numeric, but I included a way to eliminate everything but numerals as a comment if that is desired. It can easily be modified to return all the recipients, as well.

I assume it worked for him. It looks like it would give the right answer if the exception occurred on the first row.

2

  • 1

    I wouldn’t try to call parseLong on the contact_id field; treat it as a string. In fact, it’s quite possible that it could be an email address or something, in the case of email-to-mms gateways.

    Nov 22, 2012 at 17:36

  • 4

    To clarify the type constants, they come from the PduHeaders class: 0x97 / 151 is PduHeaders.TO and 0x89 / 137 is PduHeaders.FROM. Other valid values for reference are: 0x81 / 129 is PduHeaders.BCC and 0x82 / 130 is PduHeaders.CC. See also Telephony.Mms.Addr.

    – zelanix

    Jun 18, 2015 at 22:26

5

I’ve just been struggling with this; however, I finally got it to work and I thought this thread might benefit from my experience.

I could query on content://mms-sms/conversations/ (Telephony.Threads.CONTENT_URI) and get addresses and parts as helpfully described in the thread, but I found that this URI would not retrieve threads that only had MMS messages in them – for example, threads with more than two correspondents.

After doing some digging in the AOSP MMS app source, I found that it was using a variant on Telephony.Threads.CONTENT_URI to generate its conversation list – it was adding the parameter “simple” with the value “true”. when I added this parameter, I found that the provider would query a completely different table, which did indeed have all the SMS and MMS threads in it.

This table has a completely different schema from the regular Telephony.Threads.CONTENT_URI one (???); this is the projection that the AOSP app is using —

public static final String[] ALL_THREADS_PROJECTION = {
    Threads._ID, Threads.DATE, Threads.MESSAGE_COUNT, Threads.RECIPIENT_IDS,
    Threads.SNIPPET, Threads.SNIPPET_CHARSET, Threads.READ, Threads.ERROR,
    Threads.HAS_ATTACHMENT
};

The _ID here is the ID of the thread – so an ID into Telephony.Sms.CONTENT_URI or Telephony.Mms.CONTENT_URI.

After I discovered this bizarre detail, things started to work a lot better! Note however that the DATE column in the “simple=true” variant is not reliable, i had to use the date from the most recent Sms or Mms message instead.

Another thing I should probably mention is that in order to get a proper list of messages for a particular thread, I had to query on both the Mms and Sms providers, then combine the results into one list, then sort them by date.

I verified behaviour on Android 5.x and 7.x.

I hope this helps a bit more.