Android Open Source - RavenChat G C M Broadcast Receiver






From Project

Back to project page RavenChat.

License

The source code is released under:

Copyright (c) 2014 Sumit Gouthaman. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Softwar...

If you think the Android project RavenChat listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.sumitgouthaman.raven;
/*  w  ww. jav  a 2  s  .  c  o m*/
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.sumitgouthaman.raven.IntentHelpers.IntentCreator;
import com.sumitgouthaman.raven.models.Contact;
import com.sumitgouthaman.raven.models.Message;
import com.sumitgouthaman.raven.models.MessageTypes;
import com.sumitgouthaman.raven.persistence.Persistence;
import com.sumitgouthaman.raven.services.DispatchRejectionMessageIntentService;
import com.sumitgouthaman.raven.utils.SimpleNotificationMaker;
import com.sumitgouthaman.raven.utils.SimpleSoundNotificationMaker;
import com.sumitgouthaman.raven.utils.crypto.EncryptionUtils;

import org.json.JSONException;
import org.json.JSONObject;

/**
 * Receiver that is triggered when a message is received. It takes appropriate action based on the
 * type and validity of the message
 */
public class GCMBroadcastReceiver extends BroadcastReceiver {
    /**
     * inBackground determines if the receiver is running in the background, or it has been
     * registered by a foreground activity.
     * If in fact an activity has registered the receiver, it suppresses things like notifications
     * and triggers UI update.
     */
    boolean inBackground;

    ChatThreadActivity chatThreadActivity; //Reference to the activity that registered the receiver
    Context context; //Current context

    /**
     * Constructor called when the receiver is being invoked in the background.
     * It sets the inBackground variable to True
     */
    public GCMBroadcastReceiver() {
        inBackground = true;
    }

    /**
     * Constructor called when register is registered from an activity
     * @param notify - if false, no notifications are created for normal messages
     * @param cta - The activity registering the receiver
     */
    public GCMBroadcastReceiver(boolean notify, ChatThreadActivity cta) {
        this.inBackground = notify;
        this.chatThreadActivity = cta;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        this.context = context;
        Bundle extras = intent.getExtras();
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
        // The getMessageType() intent parameter must be the intent you received
        // in your BroadcastReceiver.
        String messageType = gcm.getMessageType(intent);

        if (!extras.isEmpty()) {  // has effect of unparcelling Bundle
            /*
             * Filter messages based on message type. Since it is likely that GCM
             * will be extended in the future with new message types, just ignore
             * any message types you're not interested in, or that you don't
             * recognize.
             */
            if (GoogleCloudMessaging.
                    MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
                Persistence.addDebugMessages(context, "Send error: " + extras.toString());
            } else if (GoogleCloudMessaging.
                    MESSAGE_TYPE_DELETED.equals(messageType)) {
                Persistence.addDebugMessages(context, "Deleted messages on server: " +
                        extras.toString());
                // If it's a regular GCM message, do some work.
            } else if (GoogleCloudMessaging.
                    MESSAGE_TYPE_MESSAGE.equals(messageType)) {
                // This loop represents the service doing some work.
                String recd = extras.getString("data");
                int recdMessageType = -1;
                String recdMessageText = "----";

                //Try parsing the data object received
                try {
                    JSONObject data = new JSONObject(recd);
                    recdMessageType = data.getInt("messageType");
                    recdMessageText = data.getString("messageText");
                } catch (JSONException nfe) {
                    Persistence.addDebugMessages(context, "Coundn't parse message type");
                }

                if (recdMessageType == MessageTypes.DEBUG_MESSAGE) {
                    /**
                     * Debug messages can be used to check if messages are being received correctly
                     */
                    Persistence.addDebugMessages(context, "Received: " + "Message of type: " + recdMessageType + " => " + recdMessageText);
                    PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
                            new Intent(context, DebugActivity.class), 0);
                    if (inBackground) {
                        SimpleNotificationMaker.sendNotification(context, "Raven: DEBUG MESSAGE", recdMessageText, contentIntent);
                    } else {
                        SimpleSoundNotificationMaker.sendNotification(context);
                    }
                } else if (recdMessageType == MessageTypes.PAIRING_MESSAGE) {
                    /**
                     * Message sent by a device after scanning code.
                     */
                    try {
                        /**
                         * First we check if the message has a cipherText field.
                         * If yes, it is attempting an encrypted connection. Else, it is a
                         * un-encrypted one.
                         */
                        JSONObject recdObject = new JSONObject(recdMessageText);
                        String cipherText = recdObject.optString("cipherText", null);
                        if (cipherText != null) {
                            //Encryption is supported
                            String cachedKey = Persistence.getCachedKey(context);
                            if (cachedKey == null) {
                                //No key cached
                                //Refuse connection
                                String targetRegID = recdObject.getString("registrationID");
                                Intent rejectionIntent = new Intent(context, DispatchRejectionMessageIntentService.class);
                                rejectionIntent.putExtra("registrationID", targetRegID);
                                context.startService(rejectionIntent);
                            } else {
                                //Key is present in cache
                                //Check if the key is the one which the new contact used
                                String plainText = EncryptionUtils.decrypt(cipherText, cachedKey);
                                try {
                                    /**
                                     * Parse necessary fields from the object and save contact
                                     */
                                    JSONObject pairingRequest = new JSONObject(plainText);
                                    Contact newContact = new Contact();
                                    newContact.username = pairingRequest.getString("username");
                                    newContact.secretUsername = pairingRequest.getString("secretUsername");
                                    newContact.registrationID = pairingRequest.getString("registrationID");
                                    newContact.encKey = cachedKey;
                                    Persistence.addNewContact(context, newContact);

                                    Intent chatThreadIntent = IntentCreator.getChatThreadIntent(context, newContact.secretUsername);
                                    PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
                                            chatThreadIntent, PendingIntent.FLAG_CANCEL_CURRENT);
                                    String notifMessage = String.format(context.getString(R.string.contact_has_paired_encrypted), newContact.username);
                                    SimpleNotificationMaker.sendNotification(context, context.getString(R.string.contact_added), notifMessage, contentIntent);
                                } catch (JSONException je) {
                                    //The key used was not the same
                                    //Refuse connection
                                    String targetRegID = recdObject.getString("registrationID");
                                    Intent rejectionIntent = new Intent(context, DispatchRejectionMessageIntentService.class);
                                    rejectionIntent.putExtra("registrationID", targetRegID);
                                    context.startService(rejectionIntent);
                                }
                            }
                        } else {
                            //Not an encrypted connection
                            JSONObject pairingRequest = new JSONObject(recdMessageText);
                            Contact newContact = new Contact();
                            newContact.username = pairingRequest.getString("username");
                            newContact.secretUsername = pairingRequest.getString("secretUsername");
                            newContact.registrationID = pairingRequest.getString("registrationID");
                            Persistence.addNewContact(context, newContact);
                            Intent chatThreadIntent = IntentCreator.getChatThreadIntent(context, newContact.secretUsername);
                            PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
                                    chatThreadIntent, PendingIntent.FLAG_CANCEL_CURRENT);
                            String notifMessage = String.format(context.getString(R.string.contact_has_paired), newContact.username);
                            SimpleNotificationMaker.sendNotification(context, context.getString(R.string.contact_added), notifMessage, contentIntent);
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                } else if (recdMessageType == MessageTypes.MORNAL_MESSAGE) {
                    /**
                     * Regular person to person message
                     */
                    try {
                        JSONObject newMessage = new JSONObject(recdMessageText);
                        String secretUsername = newMessage.getString("secretUsername");
                        Contact user = Persistence.getUser(context, secretUsername);

                        if (user != null) {
                            String username = user.username;
                            String encKey = user.encKey;
                            Message message = new Message();
                            message.messageText = newMessage.getString("messageText");
                            /**
                             * If encryption key is set for the contact, decrypt the messageText
                             * field
                             */
                            if (encKey != null) {
                                message.messageText = EncryptionUtils.decrypt(message.messageText, encKey);
                            }
                            message.receivedMessage = true;
                            message.timestamp = System.currentTimeMillis();

                            //Save the message against the appropriate contact
                            Persistence.addMessage(context, secretUsername, message);

                            //Trigger notification
                            Intent chatThreadIntent = IntentCreator.getChatThreadIntent(context, secretUsername);
                            PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
                                    chatThreadIntent, PendingIntent.FLAG_CANCEL_CURRENT);
                            if (!inBackground && chatThreadActivity != null && chatThreadActivity.secretUsername.equals(secretUsername)) {
                                SimpleSoundNotificationMaker.sendNotification(context);
                                chatThreadActivity.refreshThread();
                            } else {
                                SimpleNotificationMaker.sendNotification(context, context.getString(R.string.notif_title_messag_recd), username + ": " + message.messageText, contentIntent);
                            }
                        }

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                } else if (recdMessageType == MessageTypes.REMOVE_CONTACT) {
                    /**
                     * Message sent for un-pairing
                     */
                    String toBeRemoved = recdMessageText;
                    Contact user = Persistence.getUser(context, toBeRemoved);
                    if (user != null) {
                        String username = user.username;

                        //Create notification informing of the un-pairing
                        String notifMessage = String.format(context.getString(R.string.contact_has_unpaired), username);
                        Intent messageListIntent = new Intent(context, MessageListActivity.class);
                        PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
                                messageListIntent, PendingIntent.FLAG_CANCEL_CURRENT);
                        SimpleNotificationMaker.sendNotification(context, context.getString(R.string.contact_unpaired), notifMessage, contentIntent);

                        //Delete the contact from message
                        Persistence.clearContact(context, toBeRemoved);
                    }
                } else if (recdMessageType == MessageTypes.REGISTRATION_UPDATE) {
                    /**
                     * Indicates that one of the contacts has had a change in its registration ID
                     */
                    try {
                        JSONObject registrationUpdateOb = new JSONObject(recdMessageText);
                        String contactSecretUsername = registrationUpdateOb.getString("secretUsername");
                        String newRegId = registrationUpdateOb.getString("registrationID");
                        Persistence.updateRegistrationID(context, contactSecretUsername, newRegId);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                } else if (recdMessageType == MessageTypes.SELF_DESTRUCTING_MESSAGE) {
                    /**
                     * Message that only triggers a notification and a screen to display.
                     * This message is not persisted.
                     */
                    try {
                        JSONObject selfDestructingMessageOb = new JSONObject(recdMessageText);
                        String contactSecretUsername = selfDestructingMessageOb.getString("secretUsername");
                        String message = selfDestructingMessageOb.getString("message");

                        Contact user = Persistence.getUser(context, contactSecretUsername);
                        String encKey = user.encKey;

                        if (encKey != null) {
                            message = EncryptionUtils.decrypt(message, encKey);
                        }

                        int destryAfter = selfDestructingMessageOb.getInt("destroyAfter");
                        Intent selfDestructingMessageIntent = new Intent(context, SelfDestructingMessageDisplay.class);
                        selfDestructingMessageIntent.putExtra("secretUsername", contactSecretUsername);
                        selfDestructingMessageIntent.putExtra("destroyAfter", destryAfter);
                        selfDestructingMessageIntent.putExtra("message", message);
                        PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
                                selfDestructingMessageIntent, PendingIntent.FLAG_CANCEL_CURRENT);
                        SimpleNotificationMaker.sendNotification(context, context.getString(R.string.read_once_message), context.getString(R.string.can_read_only_once), contentIntent, true);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                } else if (recdMessageType == MessageTypes.USERNAME_UPDATE) {
                    /**
                     * Indicates that one of the contacts has changed their username.
                     * It triggers a corresponding change in the persistence layer.
                     */
                    try {
                        JSONObject updateUsernameMessageOb = new JSONObject(recdMessageText);
                        String contactSecretUsername = updateUsernameMessageOb.getString("secretUsername");
                        String newUsername = updateUsernameMessageOb.getString("username");
                        String oldUsername = Persistence.getUser(context, contactSecretUsername).username;
                        Persistence.updateContactUsername(context, contactSecretUsername, newUsername);
                        Contact user = Persistence.getUser(context, contactSecretUsername);
                        if (user != null) {
                            String username = user.username;
                            String userRegID = user.registrationID;
                            String encKey = user.encKey;
                            Intent chatThreadIntent = IntentCreator.getChatThreadIntent(context, contactSecretUsername);
                            PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
                                    chatThreadIntent, PendingIntent.FLAG_CANCEL_CURRENT);
                            String message = oldUsername + " " + context.getString(R.string.is_now) + " " + newUsername;
                            SimpleNotificationMaker.sendNotification(context, context.getString(R.string.contact_renamed), message, contentIntent, true);
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                } else if (recdMessageType == MessageTypes.REJECT_CONNECTION_KEY_INVALID) {
                    /**
                     * Indicates that a pairing request this device sent to another device was
                     * rejected by the other device.
                     */
                    try {
                        JSONObject updateUsernameMessageOb = new JSONObject(recdMessageText);
                        String contactSecretUsername = updateUsernameMessageOb.getString("secretUsername");
                        Contact user = Persistence.getUser(context, contactSecretUsername);
                        if (user != null) {
                            String username = user.username;
                            Persistence.clearContact(context, contactSecretUsername);
                            String title = context.getString(R.string.pairing_rejected);
                            String message = String.format(context.getString(R.string.contect_claims_key_expired), username);
                            //Create notification
                            Intent messageListIntent = new Intent(context, MessageListActivity.class);
                            PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
                                    messageListIntent, PendingIntent.FLAG_CANCEL_CURRENT);
                            SimpleNotificationMaker.sendNotification(context, title, message, contentIntent);
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        //Consume the broadcast
        abortBroadcast();
    }


}




Java Source Code List

com.sumitgouthaman.raven.AddContactActivity.java
com.sumitgouthaman.raven.ChatThreadActivity.java
com.sumitgouthaman.raven.DebugActivity.java
com.sumitgouthaman.raven.DispatchGCMMessage.java
com.sumitgouthaman.raven.GCMBroadcastReceiver.java
com.sumitgouthaman.raven.MessageListActivity.java
com.sumitgouthaman.raven.NFCPairing.java
com.sumitgouthaman.raven.SelfDestructingMessageCompose.java
com.sumitgouthaman.raven.SelfDestructingMessageDisplay.java
com.sumitgouthaman.raven.SettingsActivity.java
com.sumitgouthaman.raven.ShareViaRaven.java
com.sumitgouthaman.raven.IntentHelpers.IntentCreator.java
com.sumitgouthaman.raven.listadapters.ChatThreadAdapter.java
com.sumitgouthaman.raven.listadapters.MessageListAdapter.java
com.sumitgouthaman.raven.models.Contact.java
com.sumitgouthaman.raven.models.MessageListItem.java
com.sumitgouthaman.raven.models.MessageTypes.java
com.sumitgouthaman.raven.models.Message.java
com.sumitgouthaman.raven.persistence.Persistence.java
com.sumitgouthaman.raven.services.DispatchMessageIntentService.java
com.sumitgouthaman.raven.services.DispatchNameUpdateMessageIntentService.java
com.sumitgouthaman.raven.services.DispatchRegUpdateMessageIntentService.java
com.sumitgouthaman.raven.services.DispatchRejectionMessageIntentService.java
com.sumitgouthaman.raven.services.TTSService.java
com.sumitgouthaman.raven.utils.CheckPlayServices.java
com.sumitgouthaman.raven.utils.MessageDispatcher.java
com.sumitgouthaman.raven.utils.RandomStrings.java
com.sumitgouthaman.raven.utils.SimpleNotificationMaker.java
com.sumitgouthaman.raven.utils.SimpleSoundNotificationMaker.java
com.sumitgouthaman.raven.utils.StringToQRBitmap.java
com.sumitgouthaman.raven.utils.TimestampFormatter.java
com.sumitgouthaman.raven.utils.crypto.Base64Utils.java
com.sumitgouthaman.raven.utils.crypto.EncryptionUtils.java
com.sumitgouthaman.raven.utils.crypto.KeyGeneratorUtils.java