Піктограма сповіщень з новою системою обміну повідомленнями Firebase


132

Вчора Google представив в Google I / O нову систему сповіщень на основі нової Firebase. Я спробував цей новий FCM (Firebase Cloud Messaging) із прикладом на Github.

Піктограма сповіщення завжди являє собою ic_launcher, незважаючи на те, що я оголосив певний доступний варіант

Чому? Тут нижче офіційного коду для обробки повідомлення

public class AppFirebaseMessagingService extends FirebaseMessagingService {

    /**
     * Called when message is received.
     *
     * @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
     */
    // [START receive_message]
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        // If the application is in the foreground handle both data and notification messages here.
        // Also if you intend on generating your own notifications as a result of a received FCM
        // message, here is where that should be initiated. See sendNotification method below.
        sendNotification(remoteMessage);
    }
    // [END receive_message]

    /**
     * Create and show a simple notification containing the received FCM message.
     *
     * @param remoteMessage FCM RemoteMessage received.
     */
    private void sendNotification(RemoteMessage remoteMessage) {

        Intent intent = new Intent(this, MainActivity.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);

// this is a my insertion looking for a solution
        int icon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? R.drawable.myicon: R.mipmap.myicon;
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(icon)
                .setContentTitle(remoteMessage.getFrom())
                .setContentText(remoteMessage.getNotification().getBody())
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

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

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

}

firebase не має нічого спільного з тим, як ви створюєте сповіщення, будь ласка, надайте зображення щодо того, що ви бачите
tyczj

1
точний. цей код надходить прямо з Firebase, а метод sendNotification () точно такий же для будь-якого сповіщення. Цей код добре працює з GCM, але з FCM немає. він завжди залишається ic_launcher, використовуючи новий веб-інтерфейс для надсилання повідомлень
marco

ви встановлюєте маленьку піктограму, але не велику піктограму, якщо ви не надсилаєте натискання з тегом сповіщень у навантажувальному навантаженні, воно не має нічого спільного з FCM
tyczj

Чи відображається ваша спеціальна піктограма сповіщень, коли програма стоїть на передньому плані? Це працює для мене. Однак, коли програма знаходиться у фоновому режимі, вона повинна використовувати якийсь обробник FCM за замовчуванням, оскільки всі налаштування сповіщення ігноруються (піктограму, звук, світло, вібрацію тощо неможливо налаштувати).
shinypenguin

Відповіді:


267

На жаль, це було обмеженням повідомлень Firebase у SDK 9.0.0-9.6.1. Коли програма знаходиться у фоновому режимі, піктограма запуску використовується з маніфесту (з необхідним відтінком Android) для повідомлень, що надсилаються з консолі.

З SDK 9.8.0, однак, ви можете змінити за замовчуванням! У своєму AndroidManifest.xml ви можете встановити наступні поля для налаштування значка та кольору:

<meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/notification_icon" />
<meta-data android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/google_blue" />

Зауважте, що якщо додаток стоїть на передньому плані (або надсилається повідомлення про передачу даних), ви можете повністю використовувати власну логіку для налаштування дисплея. Ви також можете завжди налаштувати піктограму, якщо надсилаєте повідомлення з HTTP / XMPP API.


1
@Ian Barber: якийсь план Google змінити цю поведінку найближчим часом?
skylve

1
Команда обізнана з проблемою і працює над виправленням.
Артур Томпсон

1
будь-яке оновлення з цього приводу? подумав, що запитаю, тому що були обставини, коли інженер Google просто забув натиснути патч.
CQM

7
Ах, я змусив його працювати з 9.8.0. Щоб допомогти іншим, пам’ятайте, що значок рядка стану повинен відповідати вимогам: developer.android.com/guide/practices/ui_guidelines/… . Міна не зробила і, таким чином, Firebase просто за замовчуванням застосовується до стандартного білого квадрату, а не використовувати піктограму, вказану в маніфесті.
zaifrun

3
Якщо ви намагаєтеся це спробувати і виявите, що піктограма менша, ніж інші сповіщення, переконайтеся, що ви використовуєте векторний малюнок (а не png). Це вирішило це для мене.
riper

35

Використовуйте реалізацію сервера для відправки повідомлень на клієнт і використання даних типів повідомлень , а не повідомлення типу повідомлень.

Це допоможе вам отримати зворотний виклик onMessageReceivedнезалежно від того, чи ваша програма перебуває у фоновому режимі чи на передньому плані, і ви зможете генерувати своє власне сповіщення тоді


2
Це рішення, що пропонується і в документах Firebase, ви можете показувати сповіщення будь-яким зручним способом, якщо ви покладаєтесь на натискання даних замість сповіщення.
racs

1
так, згоден. це слід позначити як правильну відповідь. або моя відповідь нижче :)
Developine

3
Ні, це неможливо для людей, яким потрібно підтримувати сумісність з іншими клієнтами / застарілими версіями, які очікують сповіщення.
Габор

У виробництві є додатки, які вже очікують типу сповіщення, і ми розширили цей (складний) запускний компонент для додавання даних для нових клієнтів. Але ми не можемо видалити підтримку застарілих версій нашого додатка.
Габор

О, я згоден. Це ще одна проблема. Я б запропонував уважно прочитати документи перед інтеграцією. Також ретельно протестуйте перед випуском у виробництво. Проблему можна було б уникнути, якби програма була протестована задовго до запуску. У будь-якому випадку вам було чому навчитися.
geekoraul

9

atm вони працюють над цим питанням https://github.com/firebase/quickstart-android/isissue/4

коли ви надсилаєте сповіщення з консолі Firebase, використовує значок додатка за замовчуванням, і система Android перетворить цей значок у білий колір, коли знаходиться на панелі сповіщень.

Якщо ви незадоволені цим результатом, вам слід застосувати FirebaseMessagingService і створити сповіщення вручну, коли ви отримаєте повідомлення. Ми працюємо над тим, щоб покращити це, але поки це єдиний шлях.

редагувати: за допомогою SDK 9.8.0 додати до AndroidManifest.xml

<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/my_favorite_pic"/>

як відобразити індивідуальний лоток повідомлень із значками в зефірі
Харша

6

Моє рішення схоже на рішення ATom, але простіше у виконанні. Вам не потрібно створювати клас, який повністю затінює FirebaseMessagingService, ви можете просто перекрити метод, який отримує Намір (який є загальнодоступним, принаймні у версії 9.6.1) та взяти інформацію, яка відображатиметься з додатків. "Хакі" частина полягає в тому, що назва методу дійсно затуманена і збирається змінювати щоразу, коли ви оновлюватимете sdk Firebase до нової версії, але ви можете швидко знайти його, ознайомившись з FirebaseMessagingService з Android Studio і шукаючи відкритий метод, який займає Намір як єдиний параметр. У версії 9.6.1 це називається zzm. Ось як виглядає моя послуга:

public class MyNotificationService extends FirebaseMessagingService {

    public void onMessageReceived(RemoteMessage remoteMessage) {
        // do nothing
    }

    @Override
    public void zzm(Intent intent) {
        Intent launchIntent = new Intent(this, SplashScreenActivity.class);
        launchIntent.setAction(Intent.ACTION_MAIN);
        launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* R    equest code */, launchIntent,
                PendingIntent.FLAG_ONE_SHOT);
        Bitmap rawBitmap = BitmapFactory.decodeResource(getResources(),
                R.mipmap.ic_launcher);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_notification)
                .setLargeIcon(rawBitmap)
                .setContentTitle(intent.getStringExtra("gcm.notification.title"))
                .setContentText(intent.getStringExtra("gcm.notification.body"))
                .setAutoCancel(true)
                .setContentIntent(pendingIntent);

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

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

gcm.notification.title для ключового імені на 100% безпечний для всіх версій?
pedroooo

3

Просто встановіть targetSdkVersion на 19. Піктограма сповіщення буде кольоровою. Потім зачекайте, коли Firebase виправить цю проблему.


7
: D Вау, так де ж список побічних ефектів?
Євген Печанець

@EugenPechanec так, компроміс полягає в тому, що ви, можливо, не зможете використовувати деякі API, доступні 20+
benleung

3

Існує також один потворний, але робочий спосіб. Декомпілюйте FirebaseMessagingService.class і змініть його поведінку. Потім просто поставте клас до потрібного пакету у вашому додатку та dex використовує його замість класу у самій вікні обміну повідомленнями. Це досить легко і працездатно.

Існує метод:

private void zzo(Intent intent) {
    Bundle bundle = intent.getExtras();
    bundle.remove("android.support.content.wakelockid");
    if (zza.zzac(bundle)) {  // true if msg is notification sent from FirebaseConsole
        if (!zza.zzdc((Context)this)) { // true if app is on foreground
            zza.zzer((Context)this).zzas(bundle); // create notification
            return;
        }
        // parse notification data to allow use it in onMessageReceived whe app is on foreground
        if (FirebaseMessagingService.zzav(bundle)) {
            zzb.zzo((Context)this, intent);
        }
    }
    this.onMessageReceived(new RemoteMessage(bundle));
}

Цей код походить від версії 9.4.0, метод матиме різні назви в різній версії через обфускування.


3

якщо ваша програма знаходиться у фоновому режимі, значок сповіщення буде встановлено методом прийому повідомлень, але якщо програма є на передньому плані, значок сповіщення буде тим, який ви вказали в маніфесті

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


2

Я запускаю свої сповіщення з консолі FCM та через HTTP / JSON ... з тим же результатом.

Я можу обробляти заголовок, повне повідомлення, але піктограма завжди є білим колом за замовчуванням:

Скріншот сповіщення

Замість мого спеціального значка в коді (setSmallIcon або setSmallIcon) або піктограми за замовчуванням у додатку:

 Intent intent = new Intent(this, MainActivity.class);
    // use System.currentTimeMillis() to have a unique ID for the pending intent
    PendingIntent pIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);

    if (Build.VERSION.SDK_INT < 16) {
        Notification n  = new Notification.Builder(this)
                .setContentTitle(messageTitle)
                .setContentText(messageBody)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(pIntent)
                .setAutoCancel(true).getNotification();
        NotificationManager notificationManager =
                (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        //notificationManager.notify(0, n);
        notificationManager.notify(id, n);
    } else {
        Bitmap bm = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);

        Notification n  = new Notification.Builder(this)
                .setContentTitle(messageTitle)
                .setContentText(messageBody)
                .setSmallIcon(R.drawable.ic_stat_ic_notification)
                .setLargeIcon(bm)
                .setContentIntent(pIntent)
                .setAutoCancel(true).build();

        NotificationManager notificationManager =
                (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        //notificationManager.notify(0, n);
        notificationManager.notify(id, n);
    }

1
Зрозумів! мої теги <service> поза тегом <application> в AndroidManifest.xml Тут я гарячу відповідь stackoverflow.com/a/37352142/6366150
Gonzalo

Працює лише з запущеним додатком переднього плану ... у фоновому режимі все ще спостерігається та ж попередня поведінка
Gonzalo

коли додаток у forground цей значок сповіщення зберігача працює добре, але у фоновому режимі програми отримує піктограму білого квадрата, будь ласка, допоможіть мені
Харша

1

написати це

<meta-data 
         android:name="com.google.firebase.messaging.default_notification_icon"
         android:resource="@drawable/ic_notification" />

прямо вниз <application.....>

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


0

Думав, що я додам відповідь до цього, оскільки моя проблема була простою, але важко помітною. Зокрема, я створив копіювати / вставляти існуючий елемент метаданих під час створення свого com.google.firebase.messaging.default_notification_icon, який використовував android:valueтег для визначення його значення. Це не працюватиме для піктограми сповіщень, і одного разу я змінив її на android:resourceвсе, що працювало, як очікувалося.


Те ж саме стосується і default_notification_colorмета, він повинен бути android:resource- встановлення, як android:valueне буде працювати
flochtililoch
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.