52

Update: GCM is deprecated, use FCM

How to refresh activity on receiving gcm push notification if my app is open. I have an activity which contains listview filled with data from the server. I want to refresh my activity (here adding one more item to listview) , if I receive gcm push notification(which also contains some data).

  • One alternative is to add timer that periodically do server requests and update the list adapter data but I don't want these because it will take much resources.
  • Do I need to add broadcast receiver which will trigger on receiving gcm push which further request for newer server data and update my activity UI?

Dear commentors, please read the question carefully, I only need to refresh the list (if app is open and that particular activity is open) else no need for same.

Amrit Pal Singh
  • 7,116
  • 7
  • 40
  • 50

7 Answers7

143

Took me a few hours to figure it out. Posting here in case anyone anyone else has the same problem.

The idea is that you have to register your activity as a broadcast receiver. The easiest way to do this is like so:

//register your activity onResume()
@Override
public void onResume() {
    super.onResume();
    context.registerReceiver(mMessageReceiver, new IntentFilter("unique_name"));
}

//Must unregister onPause()
@Override
protected void onPause() {
    super.onPause();
    context.unregisterReceiver(mMessageReceiver);
}


//This is the handler that will manager to process the broadcast intent
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {

        // Extract data included in the Intent
        String message = intent.getStringExtra("message");

        //do other stuff here
    }
};

The above code goes in the activity that you want to 'listen' for events.

Now, how do we send data to this 'listener'? Go to your push notification handler(or from where you want to update your activity) and when you receive a notification call this function:

// This function will create an intent. This intent must take as parameter the "unique_name" that you registered your activity with
static void updateMyActivity(Context context, String message) {

    Intent intent = new Intent("unique_name");

    //put whatever data you want to send, if any
    intent.putExtra("message", message);

    //send broadcast
    context.sendBroadcast(intent);
}

When you call the above function, your activity should receive it.

Note: Your activity must be running/open to receive the broadcast intent

Note2: I switched to a library called 'otto'. It does actually the same thing but easier, 'broadcasts events' thoughout the app. Here's a link http://square.github.io/otto/

casillas
  • 16,351
  • 19
  • 115
  • 215
Arthur
  • 3,636
  • 5
  • 19
  • 25
  • @connector thanks for the answer, adding broadcast receiver works well to update activity UI – Amrit Pal Singh Aug 04 '14 at 05:53
  • 1
    For this I used a LocalBroadcastManager instead, it could be more efficient I'm not sure. Thanks for your answer though I'm finally getting somewhere! – Daniel Wilson Sep 24 '14 at 15:03
  • 5
    Thanks for your solution, for the people that is new to Android like me, in IntentFilter("unique_name") you have to replace "unique_name" with the same filter action of the broadcast receiver that you are using to receive the PUSH (I have followed the example of Google DEV https://developer.android.com/google/gcm/client.html), if you are using this example you have to change it to IntentFilter("com.google.android.c2dm.intent.RECEIVE") – Stornu2 May 22 '15 at 07:06
  • @connector:- I have done with approach 2, it's quite easy to implement and sharing such complex things around the application. – Adarsh Yadav Jul 29 '15 at 13:20
  • 1
    For some reason I could not get broadcast when I used `unique_name` while creating the intent itself like `Intent intent = new Intent("unique_name")`. It only worked when I set the `unique_name` as an action using `intent.setAction("unique_name")`. – vishalmullur Jan 12 '16 at 19:29
  • 1
    You can say all of this in one sentence but its always nice to have 101 lesson for fresh developers, plus 1 :) – Srneczek Sep 21 '16 at 19:45
3

I'm assuming your GCMBroadcastReceiver is in it's own .java file?

As far as refreshing an activity, I would also like to know the answer to that question.

But for knowing if a particular activity is active or not, meaning on screen just add a boolean (call it something like "active") and set it to true in your activity's onResume() event, and to false in the onPause() event:

protected void onResume()
{
    super.onResume();

    active = true;;
}

protected void onPause()
{
    super.onPause();

    active = false;
}

Your active variable would be a boolean which is global or static. This way you know if a particular activity is in "front".

Hope that helps a bit.

PaulG
  • 6,920
  • 12
  • 54
  • 98
2

The accept answer is indeed correct for the "Refreshing activity on receiving gcm push notification" (I've upvoted it too). But if you only want to update a ListView that's being displayed you don't need a broadcast receiver.

Your GCM listener service can update the database using a ContentProvider rather than inserting a direct sql query.

Then you can rely on the notifyChange method on the ContentResolver to do the trick.

Notify registered observers that a row was updated. To register, call registerContentObserver(). By default, CursorAdapter objects will get this notification. If syncToNetwork is true, this will attempt to schedule a local sync using the sync adapter that's registered for the authority of the provided uri. No account will be passed to the sync adapter, so all matching accounts will be synchronized.

e4c5
  • 52,766
  • 11
  • 101
  • 134
  • 1
    Thanks a lot @e4c5 for your suggestions (upvoted your answer too), it will be helpful further if you provide some code snippet/example of whatever you have mentioned in your above answer alike accepted answer. – Amrit Pal Singh Oct 09 '15 at 12:45
  • 1
    Ok will create a sample will be a bit complecated because of the code involved in setting up a contentprovider (of course for someone already using a contentprovider that does not matter) but I will give it a shot. – e4c5 Oct 09 '15 at 12:49
  • It would be highly appreciated if you come up with some sample code, this surely will benefit guys looking to solve this problem using content provider :) – Amrit Pal Singh Oct 09 '15 at 12:55
1

If your app is already running then try to override the onNewIntent method

Amanni
  • 1,924
  • 6
  • 31
  • 51
0

Seems there is an easier way. In the OnMessageReceived method of the GCM Listener, you can just do the update from there instead of sending the notification. You can use the same code you would have used if processing the notification. If you're doing StartActivity from the listener, you have to use the ActivityFlags.NewTask flag.

fbs419
  • 51
  • 5
0

To sum it up in single sentence: If you want to refresh activity, broadcast your custom event when notification arrives and register your activity as broadcast receiver of that event

Srneczek
  • 2,143
  • 1
  • 22
  • 26
-4
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setAction(Long.toString(System.currentTimeMillis()));
PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
prasad thangavel
  • 173
  • 1
  • 2
  • 11
  • 2
    Read the question carefully, your code is for starting activity if user clicks on gcm notification, my problem is different, problem here is that activity which needs to refresh is already open – Amrit Pal Singh Mar 07 '14 at 14:40
  • How to start a new activity was just what I wanted having incorporated the quick start tutorial into an existing app and trying to display the message content in a new activity. This SO trail now has both a new and a refresh existing code snippets. Hopefully it will help others just starting out on the updated GCM functionality. – G O'Rilla Aug 06 '15 at 13:28