如何拦截Android上的丰富通信消息

时间:2016-04-30 10:33:23

标签: android broadcastreceiver sms chat intentfilter

我想拦截Rich Communication消息(在某​​些网络上称为Vodafone聊天)。我已成功实现了一个使用意图过滤器和广播接收器的SMS接收器,效果很好。但是,如果SMS是Rich Communication消息,接收器永远不会被调用。

在我的清单中:

<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>

我的广播接收器看起来像这样:

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
    }
}

这一切都很有效,除非文本消息是Rich Communication(或聊天)消息,因此永远不会调用onReceive()。

Android文档中没有任何内容,所以我假设它将成为供应商特定的意图,但它是什么?

1 个答案:

答案 0 :(得分:2)

经过一些逆向工程后,我已经找到并回答了三星设备。我查看了根据三星设备上的Messages应用程序的清单,以找到意图。然后我设置了自己的接收器并检查了Bundle附加组件是否有任何有用的数据。

在清单中:

    <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>

获得额外许可:

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

接收器代码如下所示:

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);
                }
            }
        }
    }
}

在“参与者”中,额外的是以“tel:”为前缀的电话号码,消息文本在主题包中。

当然,这只适用于三星设备,因为它不是一个已发布的API,如果没有通知就显然会有变化,所以它未知它将用多长时间,或者它适用于三星上的所有Android版本。但是,这有助于我拦截传入聊天的次数。

完整的操作列表如下所示,但只有上面显示的两个在捆绑附加功能中有用。其他意图的额外数据在Parcels中,并且在逆向工程中需要相当多的努力。

    <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"/>