Detecting MMS messages on Android

Dima Kolomiyets picture Dima Kolomiyets · Mar 16, 2011 · Viewed 17.2k times · Source

I was searching through the internet for this topic and couldn't find any satisfying answer... I'm trying to detect MMS messages (incoming at least for start). And I've decided to go through the way of detecting changes in the contents. I've downloaded Android codes and made sure that I'm using correct content provider: "content://mms" (in android.provider.Telephony.Mms class) and I'm using all needed permissions (from Mms application) I've come up with a sample application that detects incoming MMS messages, how ever it does not detect them. here is the application:

package com.kolomiyets.MMStesting;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.widget.TextView;

public class MMStesting extends Activity {

public static final String MMSMON_RECEIVED_MMS = "MMStesting.intent.action.MMSMON_RECEIVED_MMS";

Uri mmsInURI = Uri.parse("content://mms");

ContentObserver mmsObserver = new ContentObserver(null) {
    @Override
    public void onChange(boolean selfChange) {

        Thread mmsNotify = new Thread(){
            @Override
            public void run() {
                Intent mIntent = new Intent(MMSMON_RECEIVED_SMS);
                sendBroadcast(mIntent);
                super.run();
            }
        };
        mmsNotify.start();
        super.onChange(selfChange);
    }
};

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    BroadcastReceiver mmsMonitorBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            TextView log = (TextView)findViewById(R.id.mms_log);
            log.append("\n MMS Received;");
        }
    };

    IntentFilter mIntentFilter = new IntentFilter();
    mIntentFilter.addAction(MMSMON_RECEIVED_MMS);

    registerReceiver(mmsMonitorBroadcastReceiver, mIntentFilter);

    getApplicationContext().getContentResolver().registerContentObserver(mmsInURI, true, mmsObserver);
    getApplicationContext().getContentResolver().notifyChange(mmsInURI, mmsObserver);


}

@Override
protected void onDestroy() {
    getApplicationContext().getContentResolver().unregisterContentObserver(mmsObserver);
    super.onDestroy();
}
}

and the manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.kolomiyets.MMStesting"
  android:versionCode="1"
  android:versionName="1.0">
<uses-sdk android:minSdkVersion="4" />

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_MMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INSTALL_DRM"/>


<application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".MMStesting"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

</application>

So far I tried "content://mms-sms" and application starts detecting something endlessly after device receives MMS message. There is no indication about new MMS in the status bar(as it should be), however the message appears in the incoming messages o_O...

Also I tried putting "content://sms" and everything works as it supposed to (detection of incomming and outgoing SMSs and even MMSs o_O)

Do I misunderstand something? Is there a way to correct my app so it would detect changes in "content://mms"? If it does not work in this app, than I won't be able to use this content in my database requests? If I'll detect changes with "content://sms" how can I distinguish between SMS and MMS? (I'd like to get what is in MMS as well). Or may be the best idea is just taking all those classes from android sources and trying to modify them the way I want? ...But I would'n like to do it)))

Here is a

grepcode.com: Telephony class that contains MMS calass (also this site is convenient for browsing android source code)

This information somewhat describes, how to retrieve information from MMS messages that are in the database. However, I still can't figure out the way to detect ingoing and outgoing MMS messages.

It looks like to me that I have to to monitor "content://sms" in order to detect MMSs (since "content://sms" reacts on incoming MMSs and "content://mms" does not), and than work with "content://mms" over Cursor and ContentResolver.

But I'm not sure this is a right way... Also I don't understand what actually Part (or PduPart) represents... will i get a complete picture by retrieving Part from MMS or it will be a part of the picture? And is there any difference between "content://mms//part" and "content://mms/part/"?

Here is also an interesting moment with WAP Push Messages. As far as I've understood these represent some kind of some special SMS messages with hyper links, and they are also used to transfer configurations from mobile provider to client's phone. This class:

code.google.com: MmsReceiver.java is supposed to detect MMS messages with help of WAP Push Massages.

I really can't make sense out of it. How?

Answer

kencorbin picture kencorbin · Jun 16, 2011

Detecting an incomming MMS message is easy, just put in broadcast receiver monitoring WAP_PUSH_RECIEVED events, as in...

<receiver android:name=".PushReceiver">
  <intent-filter>
    <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
    <data android:mimeType="application/vnd.wap.mms-message" />
  </intent-filter>
</receiver>

Making sense out of what you get is a lot harder. I managed to decode everything I wanted from the WAP_PUSH_RECEIVED intent by cloning the PDU parsing code from the Mms app.

Retrieving the actual contents from the part files is what I am still working on, which is how I found this topic in the first place.