Android FCM failed to post notification on channel

2019-02-19 09:08发布

问题:

I am sending push notification message from Firebase console to my app running on emulator.

The MyFirebaseMessagingService class looks like this:

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    private static final String TAG = MyFirebaseMessagingService.class.getSimpleName();

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.d(TAG, "From: " + remoteMessage.getFrom());

        if(remoteMessage.getData().size() > 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        }

        if(remoteMessage.getNotification() != null) {
            Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
        }

        Intent intent = new Intent(this, SplashActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

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

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "my_channel_01");
        notificationBuilder.setContentTitle("FCM Notification");
        notificationBuilder.setContentText(remoteMessage.getNotification().getBody());
        notificationBuilder.setAutoCancel(true);
        notificationBuilder.setSmallIcon(R.mipmap.ic_launcher_round);
        notificationBuilder.setContentIntent(pendingIntent);
        notificationBuilder.setChannelId("my_channel_01");

        NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, notificationBuilder.build());

    }
}

The constructor for NotificationCompat.Builder for API 26 now takes two params one is Context and another is String channelId. So I just assigned a random string to my channel.

But when I send the message from the firebase console the app on emulator gives me an error TOAST saying:

Failed to post notification on channel "my_channel_01"

What am I doing wrong?

回答1:

When your build specifies a targetSdkVersion of 26, and you run on an API level 26 device or emulator, you must both specify a channel ID when constructing NotificationCompat.Builder, and also create the channel.

You could use a method like this:

public static final String NOTIF_CHANNEL_ID = "my_channel_01";

...

@RequiresApi(Build.VERSION_CODES.O)
private void createNotifChannel(Context context) {
    NotificationChannel channel = new NotificationChannel(NOTIF_CHANNEL_ID,
            "MyApp events", NotificationManager.IMPORTANCE_LOW);
    // Configure the notification channel
    channel.setDescription("MyApp event controls");
    channel.setShowBadge(false);
    channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);

    NotificationManager manager = context.getSystemService(NotificationManager.class);

    manager.createNotificationChannel(channel);
    Log.d(TAG, "createNotifChannel: created=" + NOTIF_CHANNEL_ID);
}

And because it is only needed for API 26 and requires that level, invoke it like this:

// The channel need only be created for API 26 devices.  For devices
// running an API less the 26, there is no way to create a channel and the
// channel ID specified in the constuctor to NotificationCompat.Builder is
// merely a placeholder.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    createNotifChannel(this);
}

It does no harm to recreate the NotificationChannel, which provides some flexibility in where you do it. If your app has multiple entry points (activity, broadcast receiver, etc) take care to ensure the channel is created for all cases. You can also ensure it is only created once using NotificationManager.getNotificationChannel():

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    if (manager.getNotificationChannel(NOTIF_CHANNEL_ID) == null) {
        createNotifChannel(this);
    }
}