76

Вчера Google представил в Google I/O новую систему уведомлений на основе новой Firebase. Я попробовал эту новую FCM (Firebase Cloud Messaging) с примером в Github.Значок уведомлений с новой системой обмена облаками Firebase

значок уведомления всегда 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()); 
    } 

} 
+0

firebase не имеет никакого отношения к тому, как вы создаете уведомление, пожалуйста, предоставьте изображение относительно того, что вы видите – tyczj

+0

точным. этот код поступает прямо из метода Firebase, а метод sendNotification() точно такой же для любого уведомления. Этот код отлично работает с GCM, но с FCM no. он всегда остается ic_launcher, используя новый веб-интерфейс для отправки сообщений – marco

+0

вы устанавливаете маленький значок, но не большой значок, если вы не отправляете push с тегом уведомлений в полезной нагрузке push, это не имеет никакого отношения к FCM – tyczj

ответ

161

К сожалению, это ограничение 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" /> 

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

+0

Благодарим за разъяснение. Ian – marco

+34

К сожалению, это делает консоль уведомлений Firebase бесполезной для производства, если только ваш значок запуска не выглядит польщенным. –

+1

@ Ян Парикмахер: любой план в Google изменить это поведение в ближайшем будущем? – skylve

8

В SHORT РЕШЕНИЕ

Это происходит только при отправке сообщений через консоль firebase, а не APIs

Проблема

Переключение от старого GCM к новой FirebaseMessagingService я думал, что это будет быть хорошим, чтобы проверить, поэтому я создал сообщения, используя консоль firebase, и только обнаружил, что когда приложение является фоном, мое пользовательское уведомление не работает, а Firebase onMessageReceived не вызывается, когда приложение в backgrou й

Решение

Я пытался создать сообщения от API, и только тогда я понял, что Firebase onMessageReceived не вызывается, когда приложение в фоновом режиме выпуска происходит только при создании сообщения из Firebase консоли, а не при отправке от API

+1

У вас есть ссылка на документацию о отправке уведомлений через API? – TALE

+0

Ссылка на API для отправки уведомлений через Firebase: https://firebase.google.com/docs/cloud-messaging/http-server-ref#notification-payload-support – TALE

+1

@ kaushik-bharadwaj У ВАС появилось столько заблуждений, рассмотрите приведенные выше ответы и забудьте о своих выводах. – Gabor

1

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

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

Notification screenshot

Вместо моего пользовательского значка в коде (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

Получил! Мои теги из теги в AndroidManifest.xml Здесь я горячий ответ http://stackoverflow.com/a/37352142/6366150 – Gonzalo

+0

Работает только с приложением переднего плана ... в фоновом режиме, все еще получая прежнее поведение – Gonzalo

+1

Вы поняли это? – noev

7

атм они работают по этому вопросу https://github.com/firebase/quickstart-android/issues/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"/> 
+0

как отобразить настроенный значок в лотке для уведомлений в зефире – Harsha

22

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

Это поможет вам получить обратный вызов onMessageReceived независимо, если ваше приложение находится в переднем или заднем плане, и вы можете создать свое собственное уведомление, то

+2

Это предложение предлагается в Firebase также вы можете показать уведомление любым способом, который вы предпочитаете, если вы полагаетесь на ввод данных вместо уведомления. – racs

+1

согласен. это должно быть отмечено как правильный ответ. или мой ответ ниже :) –

+1

Нет, это невозможно для людей, которым необходимо поддерживать совместимость с другими клиентами/устаревшими версиями, ожидающими уведомления. – Gabor

2

Просто установите targetSdkVersion до 19. Значок уведомления будет пестрым. Затем подождите, пока Firebase устранит эту проблему.

+4

: D Ничего себе, так где же список побочных эффектов? –

+0

@EugenPechanec да, компромисс заключается в том, что вы не сможете использовать какой-либо API, который доступен по 20+ – benleung

3

Существует также один уродливый, но рабочий путь. Декомпилируйте FirebaseMessagingService.class и измените его поведение. Затем просто поместите класс в нужный пакет в приложении yout, а 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, метод будет иметь различные названия в другой версии из-за запутывания.

5

Мое решение аналогично одному из ATom, но его проще реализовать. Вам не нужно создавать класс, полностью закрывающий FirebaseMessagingService, вы можете просто переопределить метод, который получает Intent (который является общедоступным, по крайней мере, в версии 9.6.1) и отображать информацию, отображаемую из дополнительных функций. «Хакерная» часть состоит в том, что имя метода действительно запутано и будет меняться каждый раз, когда вы обновляете Firebase sdk до новой версии, но вы можете быстро просмотреть его, проверив FirebaseMessagingService с помощью Android Studio и ищет общедоступный метод, который принимает Intent как единственный параметр. В версии 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()); 
    } 
} 
+0

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

+0

Спасибо! Это работает :) –

2

, если ваше приложение в фоновом режиме значок уведомления будет установлен OnMessage Получить метод, но если вы приложение находится на переднем плане значок уведомления будет один вы определили на манифест

enter image description here