Связь между Activity и GCMListenerService Android

Я работаю над приложением для Android с функцией push-уведомлений с использованием GCM. Я создал класс PushNotificationService, который расширяет GCMListenerService. Внутри onMessageReceived(String from, Bundle data) я могу получить сообщение в push-уведомлении.

Теперь я хочу получить доступ к методу внутри моего класса MainActivity всякий раз, когда в push-уведомлении принимается конкретное сообщение.

Ниже мой код: -

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

    }
}

Я хочу, чтобы метод beginTask() выполнялся всякий раз, когда получено сообщение «Начать задачу».

Я знаю, что один из подходов — через архитектуру Service->Interface->Activity, но я не могу использовать его, так как никогда не создаю объект PushNotificationService.

Пожалуйста помоги.

ОБНОВЛЕНИЕ:- Сейчас я использую библиотеку Otto, и ниже приведен мой код.

Добавлен новый 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");


    }
}

Проблема все еще не решена. Метод beginTask() внутри MainActivity.java по-прежнему не вызывается.


person Jhilmil Chatterjee    schedule 24.11.2015    source источник
comment
Вы не зарегистрировали свою активность, поэтому шина будет вызывать метод @Subscribe.   -  person Gowtham Raj    schedule 18.01.2017


Ответы (2)


Используйте библиотеки eventBus для облегчения этого процесса...

Я использую Otto для этого процесса http://square.github.io/otto/
Здесь — это другая библиотека eventBus https://greenrobot.github.io/EventBus/

Шаги:
1.Создайте событие из службы
2.Добавьте прослушиватель в действие
3.Если действие запущено, метод будет выполнен.

** РЕДАКТИРОВАТЬ 1: **
Я абстрагировал отто автобус следующим образом.

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

создайте экземпляр вышеуказанного объекта и попробуйте опубликовать событие

EDIT 2 для комментария Джкарло
Выполните следующие действия, чтобы найти состояние действия.

  1. В onResume вашей активности вызовите MyBus.getInstance().register(this).
  2. В вашей активности onPause вызовите MyBus.getInstance(). unregister(this).
  3. В вашем GCM IntentService перед публикацией сообщения

    if(MyBus.getInstance().isRegistered()){ //приложение работает //отправляем данные }else{ //показываем уведомление }

Надеюсь это поможет

person Gowtham Raj    schedule 24.11.2015
comment
спасибо за ответ ... это то, что я сделал 1. Скачал последнюю банку Отто и добавил ее в свой проект. - person Jhilmil Chatterjee; 24.11.2015
comment
Примите ответ, чтобы он был полезен для сообщества... Рад узнать, что вы решили проблему - person Gowtham Raj; 24.11.2015
comment
спасибо за ваш ответ ... я добавил банку otto в свой проект ... и внутри моего PushNotificationService я инициализировал шину как public static Bus bus = new Bus(ThreadEnforcer.ANY); и зарегистрировал ее как bus.register(this);. Затем я делаю bus.post(message); внутри onMessageReceived(String from, Bundle data). Внутри моей MainActivity я сделал @Subscribe public void beginTask(String str) { Log.d("GCM","message :- "+str); finish(); }. Но я не вижу сообщение журнала. Это правильно ? - person Jhilmil Chatterjee; 24.11.2015
comment
Однако это не работает... метод MainActivity не вызывается. Активность запущена, получено Push-сообщение, и приложение не аварийно завершает работу/выдает ошибку. ..... - person Jhilmil Chatterjee; 24.11.2015
comment
Закрытие мероприятия... из-за финишного звонка? - person Gowtham Raj; 24.11.2015
comment
нет, это не так ... действие все еще выполняется, и, кроме того, сообщение журнала также не печатается - person Jhilmil Chatterjee; 24.11.2015
comment
обновите мой код, как указано выше.. все еще нет результата... проблема все еще существует - person Jhilmil Chatterjee; 25.11.2015
comment
проверьте эту ссылку, это могло быть проблемой "> stackoverflow.com/questions/22278135/ - person Gowtham Raj; 25.11.2015
comment
Если действие находится на переднем плане (пользователи могут видеть его и взаимодействовать с ним), метод beginTask будет выполнен, верно? Мой вопрос следующий, можно ли узнать состояние активности в onMessageRecived? Мне нужно обновить пользовательский интерфейс, если активность видна, или просто отправить уведомление. - person JCarlosR; 30.03.2016

Вы можете использовать LocalBroadcastManager. Создайте LocalBroadcastManager объект mBroadcaster = LocalBroadcastManager.getInstance(this); на onCreate вашего GCMListener и отправьте трансляцию с помощью

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

Затем вы можете получить сообщение в MainActivity, используя BroadcastReceiver.

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

Также вам необходимо зарегистрировать и отменить регистрацию получателя в onStart и onStop вашей активности.

@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);
}
person Aayush Subedi    schedule 30.03.2016