ไอคอนการแจ้งเตือนพร้อมระบบ Firebase Cloud Messaging ใหม่


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 เริ่มต้นบางประเภทเนื่องจากการตั้งค่าการแจ้งเตือนทั้งหมดจะถูกละเว้น (ไอคอนเสียงไฟสั่น ฯลฯ ไม่สามารถปรับแต่งได้)
shinepenguin

คำตอบ:


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
ทีมตระหนักถึงปัญหานี้และกำลังดำเนินการแก้ไข
Arthur Thompson

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
ไม่เป็นไปไม่ได้สำหรับผู้ที่ต้องการรักษาความเข้ากันได้กับไคลเอนต์อื่น ๆ / เวอร์ชันเดิมที่คาดหวังการแจ้งเตือน
Gabor

เรามีแอปที่ใช้งานจริงซึ่งคาดว่าจะมีการแจ้งเตือนประเภทพุชอยู่แล้วและเราได้ขยายองค์ประกอบแบ็กเอนด์ (ที่ซับซ้อน) นั้นเพื่อเพิ่มข้อมูลสำหรับลูกค้าใหม่ แต่เราไม่สามารถลบการรองรับแอปเวอร์ชันเดิมได้
Gabor

ฉันเห็นด้วย นั่นเป็นอีกปัญหาหนึ่ง ฉันขอแนะนำให้อ่านเอกสารอย่างละเอียดก่อนที่จะรวมเข้าด้วยกัน รวมทั้งทดสอบอย่างละเอียดก่อนปล่อยสู่การผลิต ปัญหานี้สามารถหลีกเลี่ยงได้หากแอปได้รับการทดสอบอย่างดีก่อนเปิดตัว อย่างไรก็ตามคุณมีบางสิ่งที่ต้องเรียนรู้
geekoraul

9

atm พวกเขากำลังแก้ไขปัญหานั้น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"/>

วิธีแสดงถาดการแจ้งเตือนไอคอนที่กำหนดเองในขนมหวาน
Harsha

6

โซลูชันของฉันคล้ายกับของ 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());
    }
}

gcm.notification.title สำหรับชื่อคีย์ปลอดภัย 100% สำหรับทุกเวอร์ชันหรือไม่
pedroooo

3

เพียงตั้งค่า targetSdkVersion เป็น 19 ไอคอนการแจ้งเตือนจะเป็นสี จากนั้นรอให้ Firebase แก้ไขปัญหานี้


7
: D ว้าวรายการผลข้างเคียงอยู่ที่ไหน?
Eugen Pechanec

@EugenPechanec ใช่ข้อเสียคือคุณอาจไม่สามารถใช้ API บางตัวที่มีให้บริการใน 20+
benleung

3

นอกจากนี้ยังมีวิธีหนึ่งที่น่าเกลียด แต่ใช้งานได้ แยกไฟล์ FirebaseMessagingService.class และแก้ไขลักษณะการทำงาน จากนั้นใส่คลาสเป็นแพ็กเกจที่ถูกต้องในแอพ yout และ dex ใช้แทนคลาสใน messaging lib เอง มันค่อนข้างง่ายและทำงาน

มีวิธีการ:

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

หากแอปของคุณทำงานอยู่เบื้องหลังไอคอนการแจ้งเตือนจะถูกตั้งค่าบนเมธอดรับข้อความ แต่หากแอปของคุณอยู่เบื้องหน้าไอคอนการแจ้งเตือนจะเป็นไอคอนที่คุณกำหนดไว้ในไฟล์ Manifest

ป้อนคำอธิบายภาพที่นี่


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

เมื่อแอปอยู่ในพื้นหลังไอคอนการแจ้งเตือนที่น่าสนใจกำลังมาและทำงานได้ดี แต่ในพื้นหลังของแอปได้รับไอคอนสี่เหลี่ยมสีขาวโปรดช่วยฉันด้วย
Harsha

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จะไม่ทำงาน
flochtiloch
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.