Biểu tượng thông báo với hệ thống nhắn tin đám mây Firebase mới


132

Hôm qua Google đã trình bày tại Google I / O hệ thống thông báo mới dựa trên Firebase mới. Tôi đã thử FCM mới này (Firebase Cloud Messaging) với ví dụ trên Github.

Biểu tượng của thông báo luôn là ic_launcher mặc dù tôi đã khai báo một khả năng rút tiền cụ thể

Tại sao ? Dưới đây là mã chính thức để xử lý tin nhắn

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 không liên quan gì đến cách BẠN tạo thông báo, vui lòng cung cấp hình ảnh như những gì bạn đang thấy
tyczj

1
chính xác. mã này xuất phát trực tiếp từ Firebase và phương thức sendNotification () hoàn toàn giống nhau cho bất kỳ thông báo nào. Mã này hoạt động tốt với GCM, nhưng với FCM thì không. nó luôn luôn là ic_launcher, sử dụng giao diện web mới để gửi tin nhắn
marco

bạn đặt biểu tượng nhỏ nhưng không phải biểu tượng lớn, trừ khi bạn đang gửi một lần đẩy bằng thẻ thông báo trong tải trọng đẩy, nó không liên quan gì đến FCM
tyczj

Nó có hiển thị biểu tượng thông báo tùy chỉnh của bạn khi ứng dụng ở phía trước không? Nó ổn với tôi. Tuy nhiên, khi ứng dụng ở chế độ nền, nó phải sử dụng một số loại trình xử lý FCM mặc định, vì tất cả các cài đặt thông báo bị bỏ qua (biểu tượng, âm thanh, ánh sáng, rung, v.v. không thể tùy chỉnh).
Shinypenguin

Câu trả lời:


267

Thật không may, đây là một hạn chế của Thông báo Firebase trong SDK 9.0.0-9.6.1. Khi ứng dụng ở chế độ nền, biểu tượng trình khởi chạy sẽ được sử dụng từ bảng kê khai (có pha màu Android cần thiết) cho các tin nhắn được gửi từ bảng điều khiển.

Tuy nhiên, với SDK 9.8.0, bạn có thể ghi đè mặc định! Trong AndroidManifest.xml, bạn có thể đặt các trường sau để tùy chỉnh biểu tượng và màu sắc:

<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" />

Lưu ý rằng nếu ứng dụng ở phía trước (hoặc tin nhắn dữ liệu được gửi), bạn hoàn toàn có thể sử dụng logic của riêng mình để tùy chỉnh màn hình. Bạn cũng luôn có thể tùy chỉnh biểu tượng nếu gửi tin nhắn từ API HTTP / XMPP.


1
@Ian Barber: có kế hoạch nào tại Google để thay đổi hành vi này trong tương lai gần không?
skylve

1
Nhóm nhận thức được vấn đề và đang tìm cách khắc phục.
Arthur Thompson

1
Bất kỳ cập nhật về điều này? Tôi nghĩ rằng tôi đã hỏi bởi vì đã có trường hợp khi một kỹ sư Google chỉ đơn giản là quên đẩy miếng vá.
CQM

7
Ah, tôi đã làm cho nó hoạt động với 9.8.0. Để giúp đỡ người khác, hãy nhớ biểu tượng trên thanh trạng thái của bạn phải đáp ứng các yêu cầu: developer.android.com/guide/practices/ui_guferences/ ,. Của tôi đã không và do đó căn cứ hỏa lực chỉ mặc định cho các hình trắng tiêu chuẩn thay vì sử dụng biểu tượng được chỉ định trong tệp kê khai.
zaifrun

3
Nếu bạn tình cờ thử điều này và thấy rằng biểu tượng nhỏ hơn các thông báo khác, hãy đảm bảo bạn đang sử dụng một vectơ có thể vẽ (và không phải là png). Điều đó đã giải quyết nó cho tôi.
riper

35

Sử dụng triển khai máy chủ để gửi tin nhắn đến máy khách của bạn và sử dụng loại dữ liệu của tin nhắn thay vì loại thông báo của tin nhắn.

Điều này sẽ giúp bạn có được một cuộc gọi lại onMessageReceivedkhông phân biệt nếu ứng dụng của bạn ở chế độ nền hoặc tiền cảnh và sau đó bạn có thể tạo thông báo tùy chỉnh của mình


2
Đây cũng là giải pháp được đề xuất trong tài liệu Firebase, bạn có thể hiển thị thông báo theo bất kỳ cách nào bạn muốn nếu bạn dựa vào việc đẩy dữ liệu thay vì thông báo.
cuộc đua

1
Vâng đồng ý. điều này nên được đánh dấu là một câu trả lời đúng. hoặc câu trả lời của tôi dưới đây :)
Phát triển

3
Không, không khả thi đối với những người cần duy trì khả năng tương thích với các phiên bản khách hàng / di sản khác mong đợi thông báo.
Gabor

Chúng tôi có các ứng dụng trong sản xuất đã mong đợi một loại thông báo đẩy và chúng tôi đã mở rộng thành phần phụ trợ (phức tạp) đó để thêm dữ liệu cho các khách hàng mới. Nhưng chúng tôi không thể xóa hỗ trợ cho các phiên bản cũ của ứng dụng.
Gabor

Ồ tôi đồng ý. Đó là một vấn đề khác. Tôi khuyên bạn nên đọc kỹ tài liệu trước khi tích hợp. Ngoài ra để kiểm tra kỹ lưỡng trước khi phát hành vào sản xuất. Vấn đề có thể tránh được nếu ứng dụng được kiểm tra tốt trước khi ra mắt. Dù sao, bạn đã có một cái gì đó để học.
geekoraul

9

atm họ đang làm việc về vấn đề đó https://github.com/firebase/quickstart-android/issues/4

khi bạn gửi thông báo từ bảng điều khiển Firebase sẽ sử dụng biểu tượng ứng dụng của bạn theo mặc định và hệ thống Android sẽ chuyển biểu tượng đó thành màu trắng khi ở trong thanh thông báo.

Nếu bạn không hài lòng với kết quả đó, bạn nên triển khai FirebaseMessagingService và tạo thông báo theo cách thủ công khi bạn nhận được tin nhắn. Chúng tôi đang nghiên cứu một cách để cải thiện điều này nhưng hiện tại đó là cách duy nhất.

chỉnh sửa: với SDK 9.8.0 thêm vào AndroidManifest.xml

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

Cách hiển thị khay thông báo biểu tượng tùy chỉnh trong marshmallow
Harsha

6

Giải pháp của tôi tương tự như giải pháp của ATom, nhưng dễ thực hiện hơn. Bạn không cần phải tạo một lớp che phủ hoàn toàn FirebaseMessagingService, bạn chỉ có thể ghi đè phương thức nhận Intent (công khai, ít nhất là trong phiên bản 9.6.1) và lấy thông tin được hiển thị từ các tính năng bổ sung. Phần "hacky" là tên phương thức thực sự bị xáo trộn và sẽ thay đổi mỗi khi bạn cập nhật sdk Firebase lên phiên bản mới, nhưng bạn có thể tra cứu nhanh bằng cách kiểm tra FirebaseMessagingService với Android Studio và tìm kiếm một phương thức công khai một ý định là tham số duy nhất. Trong phiên bản 9.6.1, nó được gọi là zzm. Đây là cách dịch vụ của tôi trông như thế nào:

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 cho tên khóa có an toàn 100% cho tất cả các phiên bản không?
pedroooo

3

Chỉ cần đặt targetSdkVersion thành 19. Biểu tượng thông báo sẽ được tô màu. Sau đó chờ Firebase khắc phục sự cố này.


7
: D Wow, vậy danh sách các tác dụng phụ ở đâu?
Eugen Pechanec

@EugenPechanec có, sự đánh đổi là bạn không thể sử dụng một số API có sẵn trên 20+
benleung

3

Cũng có một cách xấu xí nhưng làm việc. Dịch ngược FirebaseMessagingService. Class và sửa đổi hành vi của nó. Sau đó, chỉ cần đặt lớp vào đúng gói trong ứng dụng yout và dex sử dụng nó thay vì lớp trong chính lib nhắn tin. Nó khá dễ dàng và làm việc.

Có phương pháp:

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));
}

Mã này là từ phiên bản 9.4.0, phương thức sẽ có các tên khác nhau trong phiên bản khác nhau vì obfuscation.


3

nếu ứng dụng của bạn ở chế độ nền, biểu tượng thông báo sẽ được đặt trên phương thức Nhận thông báo nhưng nếu ứng dụng của bạn ở phía trước thì biểu tượng thông báo sẽ là biểu tượng bạn đã xác định trên bảng kê khai

nhập mô tả hình ảnh ở đây


2

Tôi đang kích hoạt thông báo của mình từ bảng điều khiển FCM và thông qua HTTP / JSON ... với cùng một kết quả.

Tôi có thể xử lý tiêu đề, thông báo đầy đủ, nhưng biểu tượng luôn là một vòng tròn trắng mặc định:

Ảnh chụp màn hình thông báo

Thay vì biểu tượng tùy chỉnh của tôi trong mã (setSmallIcon hoặc setSmallIcon) hoặc biểu tượng mặc định từ ứng dụng:

 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
Hiểu rồi! Các thẻ <service> của tôi không có thẻ <application> trong AndroidManifest.xml Ở đây tôi rất nóng câu trả lời stackoverflow.com/a/37352142/6366150
Gonzalo

Chỉ hoạt động với ứng dụng tiền cảnh đang chạy ... trong nền vẫn có hành vi tương tự trước đó
Gonzalo

Khi ứng dụng trên nền tảng biểu tượng thông báo theo yêu cầu sắp hoạt động tốt nhưng trong nền ứng dụng nhận biểu tượng hình vuông màu trắng, hãy giúp tôi
Harsha

1

ghi chép lại cái đó

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

ngay xuống <application.....>

nhập mô tả hình ảnh ở đây


0

Nghĩ rằng tôi sẽ thêm một câu trả lời cho câu hỏi này, vì vấn đề của tôi rất đơn giản nhưng khó nhận thấy. Cụ thể, tôi đã sao chép / dán một phần tử siêu dữ liệu hiện có khi tạo phần tử của tôi com.google.firebase.messaging.default_notification_icon, sử dụng một android:valuethẻ để chỉ định giá trị của nó. Điều này sẽ không hoạt động cho biểu tượng thông báo và một khi tôi đã thay đổi nó thành android:resourcemọi thứ hoạt động như mong đợi.


Tương tự với default_notification_colormeta, nó cần phải là android:resource- cài đặt như android:valuesẽ không hoạt động
flochtililoch
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.