Подтвердить что ты не робот

Нажатие на уведомление не открывает указанную деятельность

Я пытаюсь открыть Activity при нажатии на уведомление, а ниже - мой код.

Intent intent = new Intent(this.getApplicationContext(), NotificationActivity.class);
intent.putExtra("msgBody",messageBody);
intent.putExtra(Constants.NOTIF_INTENT_TYPE,Constants.NOTIF_INTENT_TYPE);

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                |Intent.FLAG_ACTIVITY_SINGLE_TOP
                |Intent.FLAG_ACTIVITY_CLEAR_TOP); //Tried with many options here

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 , intent,
                                         PendingIntent.FLAG_CANCEL_CURRENT);

Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.otp_icon)
                .setContentTitle("Push MSG")
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.notify(0, notificationBuilder.build());

Android Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.com.pushapp">

    <uses-sdk
        android:minSdkVersion="17"
        android:targetSdkVersion="21" />

    <supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_LOGS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:name=".AndroidPushApp"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher">
        <activity
            android:name=".PushSplashScreen"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".MainApplicationScreen"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
            </intent-filter>
        </activity>
        <activity
            android:name=".StartActivity"
            android:launchMode="singleTask"
            android:screenOrientation="portrait"
            android:uiOptions="splitActionBarWhenNarrow"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
            </intent-filter>
        </activity>

        <service android:name=".MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>

        <service android:name=".MyFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
        </service>

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <activity
            android:name=".NotificationActivity"
            android:exported="true"
            android:label="@string/title_activity">
            <intent-filter>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Когда я получаю уведомление от FCM, я вызываю это уведомление. NotificationActivity не открывается, когда я нажимаю на уведомление, а приложение открывается (splash screen->starting activity моего обычного потока приложений). Всякий раз, когда я получаю уведомление, когда приложение уже открыто, открывается NotificationActivity, но не когда приложение еще не открыто. Может ли кто-нибудь помочь мне в решении этого вопроса?

Примечание.. Повторяю, что NotificationActivity.class не открывается при нажатии на уведомление, когда приложение еще не открыто.

4b9b3361

Ответ 1

Согласно FCM Документация, для приема и обработки сообщений

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

Чтобы получать сообщения, используйте услугу, которая расширяет FirebaseMessagingService. Ваш сервис должен onMessageReceived callback, который предоставляется для большинства типов сообщений, со следующими исключениями:

1). Уведомления, когда ваше приложение находится в фоновом режиме. В в этом случае уведомление доставляется на системный лоток устройств. Пользователь по нажатию на уведомление открывает панель запуска приложения по умолчанию.

2). Сообщения с уведомлением и полезной нагрузкой данных, оба фона и на переднем плане. В этом случае уведомление доставляется в устройств, и полезная нагрузка данных поставляется в дополнительных о цели вашей деятельности по запуску.

введите описание изображения здесь

Итак, у нас есть два типа полезных нагрузок

1). Полезная нагрузка уведомлений

2). Загрузка данных

3). Оба (дополнительный тип, который мы можем рассмотреть).

Теперь давайте обсудим один за другим эти полезные нагрузки. Перед этим вам нужно понять, как вы можете отправить эти полезные нагрузки в свое приложение. Все, что вам нужно сделать, это использовать любой инструмент, который может выполнять HTTP POST Request. В моем случае я использую инструмент Postman, плагин Google Chrome.

Перед тем, как сделать HTTP POST Request для FCM, вам нужно рассмотреть три вещи:

1). URL-адрес запроса HTTP: https://fcm.googleapis.com/fcm/send

2). Заголовки запроса:

я). Content-Type: application/json

II). Авторизация: key = YOUR_SERVER_KEY

Ниже приведен снимок экрана для того, чтобы показать, как он выглядит.

введите описание изображения здесь

3). Тело: В этом мы будем иметь JSON для Notification и Data Payloads.

  • Итак, начиная с Полезная нагрузка уведомления, это самый простой из всех. В этом случае onMessageReceived() вызывается только тогда, когда приложение находится в Foreground. Для всех остальных случаев это a System Tray Notification, который открывается при нажатии Launcher Activity при нажатии. Это полезно, если вы не хотите контролировать Notifications своими собственными и не очень много данных, с которыми нужно иметь дело, когда приходит Notification. Вы даже можете управлять звуком, значком и click_action (только когда приложение находится в Foreground) без написания кода в onMessageReceived(). Один пример тела такого HTTP POST Request прилагается на скриншоте ниже.

введите описание изображения здесь

Для открытия желаемого Activity при отправке параметра click_action вы должны использовать приведенный ниже код в onMessageReceived().

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    if (null != remoteMessage.getNotification().getClickAction()) {
            startActivity(remoteMessage.getNotification().getClickAction(), null, this);
    }
}

и ниже - ваш метод startActivity():

public void startActivity(String className, Bundle extras, Context context) {
    Class cls = null;
    try {
        cls = Class.forName(className);
    } catch (ClassNotFoundException e) {
        //means you made a wrong input in firebase console
    }
    Intent intent = new Intent(context, cls);
    if (null != extras) {
        intent.putExtras(extras);
    }
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
            | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    context.startActivity(intent);
}

ПРИМЕЧАНИЕ. Этот ключ click_action будет работать только тогда, когда приложение находится в Foreground, для всех остальных случаев, когда приложение находится в фоновом режиме и закрытый, он не работает. Он даже не открывает Launcher Activity, в случае Background и Closed, если этот параметр указан.

  • Теперь появляется Data Payload. Это похоже на ту, что мы имеем в GCM. Это очень важно, если мы хотим обрабатывать все элементы Notification ourselve так же, как все мы делали в случае GCM. Пример тела такого HTTP POST Request показан ниже.

введите описание изображения здесь

Таким образом, в этом случае onMessageReceived() вызывается каждый раз, и это будет работать так же, как и GCM, что очень полезно для всех нас. Вы должны Override onMessageReceived(), как показано ниже.

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    Map<String, String> data = remoteMessage.getData();
    if (null != data && 0 < data.size()) {
        if (data.containsKey("custom_key_1")) {
            sendNotification(data.get("custom_key_1"));
        }
    }
}

private void sendNotification(String messageBody) {
        Intent intent = new Intent(this, DesiredActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_ic_notification)
                .setContentTitle("FCM Message")
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
  • И последнее, но не менее важное: мы можем отправить как Notification, так и Data Payloads. В этом случае onMessageReceived() вызывается, когда приложение находится в Foreground. Для фона и закрытого состояния Notification входит в системный лоток, похожий на Notification Payload, но единственное отличие состоит в том, что мы можем иметь data extras, а также, чтобы мы могли перенаправить пользователя на желаемый Activity при нажатии на Notification. Ниже приведен пример тела такого HTTP POST Request. Пример тела такого HTTP POST Request показан ниже.

введите описание изображения здесь

При нажатии на Notification в системном лотке он откроет Launcher Activity и вам нужно Override onCreate() вашего Launcher Activity, чтобы получить data extras и перенаправить пользователя на желаемый Activity. Ниже приведен код, вы должны написать onCreate() своего Activity, чтобы перенаправить пользователя на желаемый Activity.

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if(getIntent().hasExtra("custom_key_1") && getIntent().getStringExtra("custom_key_1")
            .equals("custom_value_1")){
        startActivity(new Intent(this, DesiredActivity.class));
        finish();
        return;
    }

    // other operations
}

Другим случаем для этого типа является, когда ваш Launcher Activity определяется как launchMode="true" в manifest, а когда Notification Прибывает, ваш Launcher Activity находится в Foreground. Поэтому, когда вы нажимаете "Уведомление", вам нужно Override метод onNewIntent() в Launcher Activity, чтобы открыть желаемый Activity. Ниже приведен пример кода для него.

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    if (getIntent().hasExtra("custom_key_1") && getIntent().getStringExtra("custom_key_1")
                .equals("custom_value_1")) {
            startActivity(new Intent(this, DesiredActivity.class));
            finish();
    }
}

Короче говоря, я бы сказал, что хорошо использовать тип Data Payload, поскольку он обеспечивает большую гибкость и контроль над Notification и, что более важно, поскольку все мы используем GCM, поэтому этот тип - это то, что мы все хотели бы предпочесть.

Примечание. Некоторые устройства имеют проблемы с получением уведомлений в Предпосылки, поскольку я нашел некоторые запросы по тому же здесь. Кроме того, на время, я изучал эти случаи, мой телефон ASUS не получал уведомления в фоновом режиме для любого из перечисленных выше типов. Так не уверен, что проблема с этими устройствами.

Ответ 2

Вы можете указать любой Activity, который будет приемником для push-уведомлений:

<intent-filter>
    <action android:name="PACKAGE_NAME.MESSAGE"/>
    <category android:name="android.intent.category.DEFAULT"/>
</intent-filter>

Этот фильтр намерений для активности указывает, какая активность будет запущена в ответ на push-уведомление (PACKAGE_NAME - ваш пакет приложений для Android)

Итак, вы можете добавить этот фильтр намерений в свой Activity, который вы хотите открыть, нажав кнопку Push-уведомления.

Ответ 3

Если вы подробно читаете документы firebase, есть два типа полезных нагрузок

  • Полезная нагрузка данных
  • Полезная нагрузка уведомлений

Полезная нагрузка данных вызывает обратный вызов onMessageReceived(), когда приложение является как передним, так и фоном. Это не относится к полезной нагрузке на уведомление, которая вызывает обратный вызов только в состоянии переднего плана. Итак, если вы используете полезную нагрузку данных, эта проблема должна быть решена.

Ответ 4

Проверьте этот код и сообщите мне.

        Intent intent = new Intent(this, LoginActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        pendingIntent = PendingIntent.getActivity(this, 0, intent,
                PendingIntent.FLAG_ONE_SHOT);

Ответ 5

Вы должны использовать FLAG_UPDATE_CURRENT в pendingIntent.

PendingIntent pendingIntent = PendingIntent.getActivity(this, notificationId /* Request code */, intent,
            PendingIntent.FLAG_UPDATE_CURRENT);

а также передать тот же идентификатор на notificationManager

 notificationManager.notify(notificationId /* ID of notification */, notificationBuilder.build());

Ответ 6

Это намеренное поведение. Если ваше приложение находится в фоновом режиме, уведомление создается системой Android, у которой нет действия pendingIntent. Так что это не работает. В случае переднего плана это работает, потому что уведомление создается вашим кодом.

Пожалуйста, проверьте документ в приведенной ниже ссылке. https://firebase.google.com/docs/notifications/android/console-device#receive_and_handle_messages

Ответ 7

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

Вы можете просто сделать следующие две вещи для дальнейшего изучения:

  • После создания уведомления используйте команду оболочки "adb shell dumpsys activity я [ваше имя пакета]", чтобы увидеть ваше уведомление подробно, чтобы подтвердить, что это действительно то, что вы хотите. Не забудьте заменить "[ваше имя пакета]" на ваше собственное имя пакета;

  • Отслеживание журнала событий в течение времени, которое вы воспроизводите, используя "adb logcat -v threadtime -b events".

Отправьте оба из них, и мы можем получить что-то полезное о том, что происходит не так под капотом.

Ответ 8

Задайте ожидающие действия, как показано ниже.

Intent intent = new Intent(this.getApplicationContext(), NotificationActivity.class);
intent.putExtra("msgBody",messageBody);
intent.putExtra(Constants.NOTIF_INTENT_TYPE,Constants.NOTIF_INTENT_TYPE);

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

добавьте его в свое уведомление, используя

.setContentIntent(pendingIntent);

Ответ 9

Я использую это в своем FirebaseMessagingService:

/**
 * Create and show a simple notification containing the received FCM message.
 *
 * @param messageBody FCM message body received.
 */
private void sendNotification(String title, String messageBody, String data) {
    Intent intent = new Intent(this, MainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT);

    Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(getApplicationContext())
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(title)
            .setContentText(messageBody)
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);

    NotificationManager notificationManager =
            (NotificationManager) getSystemService(this.NOTIFICATION_SERVICE);

    notificationManager.notify(id++ /* ID of notification */, notificationBuilder.build());
}