Paul Netherwood
Paul Netherwood

Reputation: 446

How do I intercept a rich communication message on Android

I'd like to intercept a Rich Communication message (know as Chat on some networks like Vodafone). I've successfully implemented an SMS receiver using an intent filter and broadcast receiver which works great. However if the SMS is a Rich Communication message the receiver never gets called.

In my manifest:

<receiver
    android:name=".IncomingSMS"
    android:enabled="true"
    android:exported="true">
    <intent-filter android:priority="999">
        <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
    </intent-filter>
</receiver>

and my broadcast receiver looks like this:

public class IncomingSMS extends WakefulBroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        // Retrieves a map of extended data from the intent.
        final Bundle bundle = intent.getExtras();

        if (bundle != null)
        {
            final Object[] pdusObj = (Object[]) bundle.get("pdus");

            SmsMessage currentMessage;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            {
                String format = bundle.getString("format");
                currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[0], format);

            }
            else
            {
                //noinspection deprecation
                currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[0]);
            }

            String number = currentMessage.getDisplayOriginatingAddress();

            Intent serviceintent = new Intent(context, ChargingMonitorService.class);
            serviceintent.putExtra(NUMBER, number);
            startWakefulService(context, serviceintent);

        } // bundle is null
    }
}

This all works perfectly except if the text message is a Rich Communication (or chat) message the onReceive() is never called.

There is nothing in the Android docs so I'm assuming its going to be a vendor specific intent but what is it?

Upvotes: 4

Views: 2831

Answers (1)

Paul Netherwood
Paul Netherwood

Reputation: 446

After a bit of reverse engineering I've figured out and answer for Samsung devices. I looked at the manifest of the Messages app on a rooted Samsung device to find the intents. I then setup my own receiver and inspected the Bundle extras for any useful data.

In the manifest:

    <receiver
        android:name=".RCSReceiver"
        android:permission="com.samsung.rcs.permission.RCS_APP_PERMISSION"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <category android:name="com.samsung.rcs.framework.instantmessaging.category.ACTION"/>
            <category android:name="com.samsung.rcs.framework.instantmessaging"/>
            <action android:name="com.samsung.rcs.framework.instantmessaging.action.RECEIVE_CHAT_INVITATION"/>
            <action android:name="com.samsung.rcs.framework.instantmessaging.action.RECEIVE_PARTICIPANT_INSERTED"/>
            <action android:name="com.samsung.rcs.framework.instantmessaging.action.RECEIVE_PARTICIPANT_UPDATED"/>
        </intent-filter>
    </receiver>

with the additional permission:

<uses-permission android:name="com.samsung.rcs.im.READ_PERMISSION"/>

And the receiver code looks like this:

public class RCSReceiver extends BroadcastReceiver
{
    private static final String RECEIVE_CHAT_INVITATION = "com.samsung.rcs.framework.instantmessaging.action.RECEIVE_CHAT_INVITATION";
    private static final String RECEIVE_PARTICIPANT_UPDATED = "com.samsung.rcs.framework.instantmessaging.action.RECEIVE_PARTICIPANT_UPDATED";
    private static final String RECEIVE_PARTICIPANT_INSERTED = "com.samsung.rcs.framework.instantmessaging.action.RECEIVE_PARTICIPANT_INSERTED";
    private Logger log = LoggerFactory.getLogger(MainActivity.class);

    @Override
    public void onReceive(Context context, Intent intent)
    {
        log.debug("RCS Receiver");
        String action = intent.getAction();

        Bundle bundle = intent.getExtras();
        if(bundle != null)
        {
            if (RECEIVE_PARTICIPANT_UPDATED.equals(action) || RECEIVE_PARTICIPANT_INSERTED.equals(action))
            {
                String participant = bundle.getString("participant");
                if (participant != null)
                {
                    String number = participant.substring(4); // get the string after "tel:"
                    log.debug("Chat number is: " + number);
                }
            }
            else if (RECEIVE_CHAT_INVITATION.equals(action))
            {
                String subject = bundle.getString("subject");
                if(subject != null)
                {
                    log.debug("Chat subject: " + subject);
                }
            }
        }
    }
}

In the "participant" extra was the telephone number prefixed with "tel:" and the message text was in the subject bundle extra.

This, of course, will only work on Samsung devices and since its not a published API is obviously subject to change without notice so its unknown how long it will work for or if it works on all versions of Android on Samsung. However, it served my purpose of intercepting the number of an incoming chat.

The full list of actions is below however only the two shown above had anything useful in the bundle extras. The extra data for the other intents were in Parcels and would require quite a bit more effort in reverse engineering.

    <action android:name="com.samsung.rcs.framework.instantmessaging.action.RECEIVE_TYPING_NOTIFICATION"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.RECEIVE_CHAT_CLOSED"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.RECEIVE_NEW_MESSAGE"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.DELETE_MESSAGES_RESPONSE"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.DELETE_CHATS_RESPONSE"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.RECEIVE_CHAT_INVITATION"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.SEND_MESSAGE_RESPONSE"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.RECEIVE_MESSAGE_NOTIFICATION_STATUS"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.RECEIVE_SEND_MESSAGE_RESPONSE"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.ADD_PARTICIPANTS_RESPONSE"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.RECEIVE_MESSAGE_INSERTED"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.RECEIVE_PARTICIPANT_INSERTED"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.RECEIVE_PARTICIPANT_UPDATED"/>
    <action android:name="com.samsung.rcs.framework.instantmessaging.action.GET_IS_COMPOSING_ACTIVE_URIS_RESPONSE"/>

Upvotes: 3

Related Questions