Jhilmil Chatterjee
Jhilmil Chatterjee

Reputation: 583

Communication between Activity and GCMListenerService Android

I am working on an android application with push notification feature using GCM. I have created a class called PushNotificationService which extends GCMListenerService. Inside the onMessageReceived(String from, Bundle data) I am able to get the message in the push notification.

Now, I want to access a method inside my MainActivity class whenever a particular message is received in the push.

Below is my code :-

PushNotificationService.java

public class PushNotificationService extends GcmListenerService {

@Override
    public void onMessageReceived(String from, Bundle data) {
        // TODO Auto-generated method stub
        super.onMessageReceived(from, data);



         String message = data.getString("message");

         if(message.equalsIgnoreCase("Begin Task"))
            {

                    //call method from MainActivity.class

            }

        }
}

MainActivty.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    public void beginTask()

    {

        Log.d("GCM","Message Received from Server");
        finish();

    }
}

I want the beginTask() method to execute whenever the message "Begin Task" is received.

I know one approach is via Service->Interface->Activity architecture but I am not able to use this as I never create an object of PushNotificationService.

Please help.

UPDATE :- I am now using Otto Library and below is my code.

Added new MyBus.java

public class MyBus extends Bus {
    private static Bus bus;
    //isRegistered is used to track the current registration status
    private static boolean isRegistered;
    private Handler handler = new Handler(Looper.getMainLooper());

    public MyBus() {
        if (bus == null) {
            //ANY will allow event bus to run even with services
            //and broadcast receivers
            bus = new Bus(ThreadEnforcer.ANY);
        }
    }

    @Override
    public void register(Object obj) {
        //The bus is registered when an activity starts
        bus.register(obj);
        isRegistered = true;
    }

    @Override
    public void unregister(Object obj) {
        //The bus is unregistered when an activity goes to background
        bus.unregister(obj);
        isRegistered = false;
    }

    @Override
    public void post(final Object event) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            //post the event in main thread or background thread
            bus.post(event);
        } else {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    bus.post(event);
                }
            });
        }
    }

    public boolean isRegistered(){
        return isRegistered;
    }
}

PushNotificationService.java

public class PushNotificationService extends GcmListenerService {

@Override
    public void onMessageReceived(String from, Bundle data) {
        // TODO Auto-generated method stub
        super.onMessageReceived(from, data);

        MyBus myBus = new MyBus();
        myBus.register(myBus);

         String message = data.getString("message");

         if(message.equalsIgnoreCase("Begin Task"))
            {

                    myBus.post(message);

            }

        }
}

MainActivity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    @Subscribe
    public void beginTask()

    {

        Log.d("GCM","Message Received from Server");


    }
}

The problem is still not solved. The beginTask() inside MainActivity.java is still not getting called.

Upvotes: 1

Views: 2219

Answers (2)

Aayush Subedi
Aayush Subedi

Reputation: 191

You can use LocalBroadcastManager. Create a LocalBroadcastManager object mBroadcaster = LocalBroadcastManager.getInstance(this); on onCreate of your GCMListener and send broadcast with

@Override
public void onCreate() {
    super.onCreate();
    mBroadcaster = LocalBroadcastManager.getInstance(this);
}

@Override
public void onMessageReceived(String from, Bundle data) {
    super.onMessageReceived(from, data);

     String message = data.getString("message");

     if(message.equalsIgnoreCase("Begin Task")) {
        Intent i = new Intent();
        i.setAction("yourPackageName");
        i.putExtra("DATA", yourData);
        mBroadcaster.send(i);
    }
}

Then you can receive message in MainActivity using a BroadcastReceiver.

BroadCastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            beginTask();
        }
};

Also you need to register and unregister the receiver in onStart and onStop of your activity

@Override
protected void onStart() {
    super.onStart();
    IntentFilter filter = new IntentFilter();

    filter.addAction("yourPackageName);
    LocalBroadcastManager.getInstance(this).registerReceiver((mBroadcastReceiver), filter);
}

@Override
protected void onStop() {
    super.onStop();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
}

Upvotes: 3

Gowtham Raj
Gowtham Raj

Reputation: 2955

Use eventBus libraries to facilitate this process...

I use Otto for this process http://square.github.io/otto/
Here is an another eventBus library https://greenrobot.github.io/EventBus/

Steps:
1.Create an event from the service
2.Add a listener in the activity
3.If the activity is running the method will be executed

**EDIT 1 : **
I have abstracted the otto bus like this.

package com.mypackage.eventBus;

import android.os.Handler;
import android.os.Looper;

import com.squareup.otto.Bus;
import com.squareup.otto.ThreadEnforcer;

/**
 * Created by gowtham on 10/6/15.
 */
public class MyBus extends Bus {
    private static Bus bus;
    //isRegistered is used to track the current registration status
    private static boolean isRegistered;
    private Handler handler = new Handler(Looper.getMainLooper());

    public MyBus() {
        if (bus == null) {
            //ANY will allow event bus to run even with services
            //and broadcast receivers
            bus = new Bus(ThreadEnforcer.ANY);
        }
    }

    @Override
    public void register(Object obj) {
        //The bus is registered when an activity starts
        bus.register(obj);
        isRegistered = true;
    }

    @Override
    public void unregister(Object obj) {
        //The bus is unregistered when an activity goes to background
        bus.unregister(obj);
        isRegistered = false;
    }

    @Override
    public void post(final Object event) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            //post the event in main thread or background thread
            bus.post(event);
        } else {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    bus.post(event);
                }
            });
        }
    }

    public boolean isRegistered(){
        return isRegistered;
    }
}

create an instance of the above object and try posting event

EDIT 2 for Jcarlo's comment
Follow these steps to find the state of the activity.

  1. In your activity's onResume call MyBus.getInstance().register(this).
  2. In your activity's onPause call MyBus.getInstance().unregister(this).
  3. In your GCM IntentService before posting the message

    if(MyBus.getInstance().isRegistered()){ //app is alive //post data }else{ //show notification }

Hope this helps

Upvotes: 3

Related Questions