3

I'm reading SMS and MMS data from my Galaxy S6. All of the SMS messages have a date field like this 1456252633000. The number is the unix timestamp * 1000. The MMS messages that I sent (not received) have date fields like so: 1440628863 the timestamp is proper in unix time format. However, the MMS messages I receive have timestamp completely off, like this: 1454881665.

The two last timestamps above are consecutive, but the second one shows as though it's months before. Why is this so? Is there something I'm doing wrong here?

EDIT

I read this (How do the retrieve the date of the mms from content://mms.) and turns out that my issue is similar. The date is stuck in 1970. But even after converting it to milliseconds (1440185636 * 1000) I still get the wrong date...

EDIT 2

I'm trying to convert using the values as longs, however, still shows the date as months off.

For reference, it was 2/9/2016. I'm getting 8/26/2015 when I do the conversion. The reference timestamp is: 1440603051L * 1000L.

EDIT 3

Here is some code:

    ContentResolver contentResolver = context.getContentResolver();
    Cursor c = contentResolver.query(Telephony.Mms.CONTENT_URI, null, filter, null, null);
    JSONArray array = new JSONArray();

    try {
        if (c.moveToFirst()) {
            do {
                try {
                    String[] cols = c.getColumnNames();
                    String id = c.getString(c.getColumnIndexOrThrow("_id"));
                    JSONObject msg = populateFromMmsPart(id);

                    if (msg != null) {
                        msg.put("id", id);
                        msg.put("read", c.getString(c.getColumnIndexOrThrow("read")).contains("1"));
                        msg.put("time", c.getString(c.getColumnIndexOrThrow("date")));
                        msg.put("m_id", c.getString(c.getColumnIndexOrThrow("m_id")));
                        msg.put("received", c.getString(c.getColumnIndexOrThrow("msg_box")).contains("1"));
                        msg.put("thread_id", c.getString(c.getColumnIndexOrThrow("thread_id")));

                        array.put(msg);
                    }

                } catch (JSONException j) {
                    j.printStackTrace();
                }
            } while (c.moveToNext());
        }
    } catch (Exception e) {
        e.printStackTrace();

    } finally {
        c.close();
    }

private JSONObject populateFromMmsPart(String msgId) {
    ContentResolver contentResolver = context.getContentResolver();
    Uri messages = Uri.parse("content://mms/part");
    Cursor c = contentResolver.query(messages, null, "_id=" + msgId, null, null);
    JSONObject msg = null;

    if (c.moveToFirst()) {
        try {
            String mid = c.getString(c.getColumnIndex("mid"));
            String type = c.getString(c.getColumnIndex("ct"));

            if (!"application/smil".equals(type)) {
                // Put all the addresses in one place
                msg = new JSONObject();
                msg.put("address", getAddressesForMmsMessages(mid));
                msg.put("mid", mid);
                msg.put("type", type);

                if ("text/plain".equals(type)) {
                    // MMS is just plain text, so get the text
                    String data = c.getString(c.getColumnIndex("_data"));
                    String body;
                    if (data != null) {
                        body = getMmsText(msgId);
                    } else {
                        body = c.getString(c.getColumnIndex("text"));
                    }
                    msg.put("msg", body);
                }
            }
        } catch (JSONException j) {
            j.printStackTrace();
        }
    }

    c.close();
    return msg;
}

Previously I was doing:

ContentResolver contentResolver = context.getContentResolver();
final String[] projection = new String[]{"*"};
Uri uri = Uri.parse("content://mms-sms/conversations/");
Cursor query = contentResolver.query(uri, projection, "thread_id=109", null, null);

And I was getting the below error:

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
Community
  • 1
  • 1
KVISH
  • 12,923
  • 17
  • 86
  • 162

1 Answers1

1

In the populateFromMmsPart() method, you're querying for records in the part table whose _id matches the message ID from the mms table. However, the _id in the part table is the ID for the part, not the message. The message ID is in the mid column. This is apparently causing a mix-up when a message ID happens to match a part ID for an older message.

Change your query as follows.

Cursor c = contentResolver.query(messages, null, "mid=" + msgId, null, null);

Also, in the populateFromMmsPart() method, you only handle the first row of the returned Cursor. That Cursor is going to have (at least) three rows. One will be application/smil, one will be text/plain, and the other one(s) will be the MIME type(s) for the attachment(s). You need to iterate over that Cursor to get them all. As you have it now, you're just calling c.moveToFirst(), and handling that one row.

Mike M.
  • 38,532
  • 8
  • 99
  • 95
  • I tried that already...Still shows the date as months off. For reference, it was 2/9/2016. I'm getting 8/26/2015 when I do `1440603051L * 1000L` – KVISH Mar 26 '16 at 00:18
  • Oh, I thought you were getting dates in 1970. Can you please post your query and date calculations? – Mike M. Mar 26 '16 at 00:22
  • Also, what model of phone are you using? – Mike M. Mar 26 '16 at 00:29
  • Samsung Galaxy S6. – KVISH Mar 26 '16 at 00:29
  • Its weird because many other apps (for SMS) I downloaded and they handle MMS properly. Seems something wrong. I'm also not able to use `content://mms-sms/conversations` as documented in other places. – KVISH Mar 26 '16 at 00:30
  • OK, I have access to an S6. Gimme a little bit to run a test. – Mike M. Mar 26 '16 at 00:31
  • I just tested on an S6, and it worked just fine for me. I gotta think there's a mistake in your code. If you wanna post your query, and date calculations and formatting methods, we can take a look. – Mike M. Mar 26 '16 at 00:59
  • I just posted some code. Did you get the `content://mms-sms/conversations` to work also?? Weird. That threw exceptions for me each time. Right now I'm getting sms and mms separately. – KVISH Mar 26 '16 at 01:02
  • When you query the `content://mms-sms/conversations` URI, you have to provide a valid thread ID, or it'll throw an `IllegalStateException` of "Unrecognized URI". I'll take a look at your code here in a minute, as soon as I get a chance. – Mike M. Mar 26 '16 at 01:05
  • Interesting. I tried it many times that way and it never worked... I could be doing something wrong. – KVISH Mar 26 '16 at 01:45
  • Maybe. I do know you've got a mistake in one of the queries you've posted, so it's possible. In the query in the `populateFromMmsPart()` method, the _where_ clause should be `"mid=" + msgId`, not `"_id=" + msgId`. In the `part` table, `_id` is the ID for the part, not the message. `mid` is the message ID. I'm not sure how you end up displaying your message list, but that might account for the wrong date, like if the message ID happens to match the part ID for an old message from 8/26/2015. – Mike M. Mar 26 '16 at 01:57
  • But i'm getting the `_id` from `content://mms`. How can I get the `mid` from there? – KVISH Mar 26 '16 at 01:59
  • That is the `mid`. The `_id` from the `mms` table is the `mid` in the `part` table. You just need to change that _where_ clause. – Mike M. Mar 26 '16 at 02:02
  • Thanks for the help! If I could just ask one more, why is it that when I do the `mid=msgId` I get all the `type` as `application/smil`? I have `image/jpeg` and `text/plain`? I based it off of this page: http://stackoverflow.com/questions/3012287/how-to-read-mms-data-in-android – KVISH Mar 26 '16 at 02:10
  • 1
    In the `populateFromMmsPart()` method, you only handle the first row of the returned `Cursor`. That `Cursor` is going to have (at least) three rows. One will be `application/smil`, one will be `text/plain`, and the other one(s) will be the MIME type(s) for the attachment(s). You need to iterate over that `Cursor` to get them all. As you have it now, you're just calling `c.moveToFirst()`, and handling that one row. – Mike M. Mar 26 '16 at 02:23
  • Did that fix ya? Cool. Just FYI, I edited my post to the actual answer. Glad we got it figured out. Cheers! – Mike M. Mar 26 '16 at 02:55