Как узнать текущую (верхнюю) активность из onMessageReceived (из FirebaseMessagingService)?

Я искал везде, но просто не могу понять, как получить текущую (верхнюю) активность запущенного приложения Android.

Хорошо, мой сценарий состоит в том, что я получил полезные данные Firebase Cloud Messaging Data, когда приложение находится на переднем плане, и вызывается onMessageReceived (из подкласса FirebaseMessagingService). Мне нужно выяснить, какой экран просматривает пользователь, а затем принять решение отклонить (завершить ()) его или отправить некоторые данные (с помощью Extras / Bundle) и обновить вид.

Итак, как мне узнать, что является текущим представлением / действием, обсудить или отправить некоторые данные и заставить представление обновиться?

Спасибо!

3 ответа

Решение

Кто-то опубликовал правильный ответ, а затем удалил его, поэтому я опубликую его снова:

Вам не нужно определять верхнюю активность. Каждое из ваших действий должно слушать некоторый сигнал от FirebaseMessagingService и принять соответствующие меры. Сигнал может быть Intent трансляция на LocalBroadcastManagerили вы могли бы использовать какую-то шину событий.

Так же, как продолжение уже принятого ответа Кевина Крумвиде, вот некоторые детали реализации одного возможного способа следовать его подходу (любые ошибки мои):

Создать многоразовый BroadcastReceiver

public class CurrentActivityReceiver extends BroadcastReceiver {    
    private static final String TAG = CurrentActivityReceiver.class.getSimpleName();
    public static final String CURRENT_ACTIVITY_ACTION = "current.activity.action";
    public static final IntentFilter CURRENT_ACTIVITY_RECEIVER_FILTER = new IntentFilter(CURRENT_ACTIVITY_ACTION);

    private Activity receivingActivity;

    public CurrentActivityReceiver(Activity activity) {
        this.receivingActivity = activity;
    }

    @Override
    public void onReceive(Context sender, Intent intent) {
        Log.v(TAG, "onReceive: finishing:" + receivingActivity.getClass().getSimpleName());

        if (<your custom logic goes here>) {
            receivingActivity.finish();
        }
    }
}

Создавать и использовать этот BroadcastReceiver в каждом из ваших действий

public class MainActivity extends AppCompatActivity {

    private BroadcastReceiver currentActivityReceiver;

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

        currentActivityReceiver = new CurrentActivityReceiver(this);
        LocalBroadcastManager.getInstance(this).
            registerReceiver(currentActivityReceiver, CurrentActivityReceiver.CURRENT_ACTIVITY_RECEIVER_FILTER);
    }

    @Override
    protected void onPause() {
        LocalBroadcastManager.getInstance(this).
            unregisterReceiver(currentActivityReceiver);
        currentActivityReceiver = null;
        super.onPause();
    }
}

Наконец, отправьте соответствующую трансляцию из вашего FirebaseMessagingService

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
       Intent localMessage = new Intent(CurrentActivityReceiver.CURRENT_ACTIVITY_ACTION);   
       LocalBroadcastManager.getInstance(MyApplication.this).
            sendBroadcast(localMessage);
    }

}

Этот код регистрирует и отменяет регистрацию currentActivityReceiver таким образом, чтобы гарантировать, что широковещательный приемник активен, только когда активность активна.

Если в вашем приложении имеется большое количество Activity, вы можете захотеть создать абстрактный базовый класс Activity и поместить в него код onResume и onPause, а другие ваши Activity наследуют от этого класса.

Вы также можете добавить данные в Intent с именем "localMessage" в onMessageReceived (например, с помощью localMessage.putExtra()) и позднее получить эти данные в приемнике.

Одним из преимуществ ответа Кевина является то, что его подход не требует каких-либо дополнительных разрешений (например, GET_TASKS).

Кроме того, как указал Кевин, есть и другие, более удобные способы передачи сообщений вокруг вашего приложения, кроме BroadcastReceiver (например, EventBus и Otto). ИМХО, это здорово, но они требуют дополнительной библиотеки, которая добавит некоторые подсчеты методов. И, если ваше приложение уже использует BroadcastReceivers во многих других местах, вы можете почувствовать, что по эстетическим соображениям и из-за необходимости обслуживания вы не хотите иметь два способа передачи сообщений в приложении. (Тем не менее, EventBus довольно крутой, и я чувствую, что он менее громоздкий, чем BroadcastReceivers.)

Мы получаем текущий передний план

    ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
ComponentName cn = am.getRunningTasks(1).get(0).topActivity;

требуется разрешение

<uses-permission android:name="android.permission.GET_TASKS"/>