当应用程序未运行时,如何堆叠Firebase云消息通知?

6
我正在使用Firebase Cloud Messaging将推送通知从我的服务器发送到我的Android应用程序。
当应用程序正在运行时,通知被分组到我的FirebaseMessagingService中,因此它们会被堆叠在一起。这很好。
然而,当应用程序未运行时,通知不会被分组,每个通知都会单独显示。这不太好。
如何确保即使应用程序未运行,通知也会被分组在一起?
以下是我的FirebaseMessagingService的代码:
public class MyFcmListenerService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        RemoteMessage.Notification notification = remoteMessage.getNotification();

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)

                .setSmallIcon(R.drawable.notif_white)
                .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.notif_white))
                .setContentTitle(getResources().getString(R.string.app_name))
                .setContentText(notification.getBody())
                .setAutoCancel(true)
                .setPriority(2)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent)
                .setGroup("1")
                .setGroupSummary(true)
                .setOnlyAlertOnce(true);


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

        }
    }

请提供一些代码,用于处理传入的消息并创建通知。 - glethien
已添加代码,请查看。 - The Cook
@The Cook 你好,我也遇到了同样的问题,你找到了解决方案吗? - Murli
抱歉,我的通知仍然无法堆叠。 - The Cook
对于需要群组通知解决方案的人,请在此处查看答案:https://stackoverflow.com/questions/56848513/how-to-display-notification-in-group-using-setgroup-in-android 还可以在这里查看: https://www.developer.com/mobile/android/creating-bundled-notifications-with-android/ - ming chen
3个回答

7
Firebase在应用程序处于后台或被杀死时不会调用您的onMessageReceived,而且您无法自定义通知。系统生成的通知将显示。
要使Firebase库在所有情况下调用您的onMessageReceived,包括:
a)前台
b)后台
c)被杀死
您不能在向Firebase API发送请求时将JSON键“notification”放入其中,而应使用“data”,请参见以下内容。
例如,以下消息将不会调用onMessageReceived()
{
  "to": "/topics/test",
  "notification": {
    "title" : "title",
    "message": "data!"
   }
}

但这会起作用

{
  "to": "/topics/test",
   "data": {
       "title":"title",
       "message":"data!"
   }
} 

请查看此链接,其中详细描述了Firebase消息类型。例如:

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

    Log.d(TAG, "From: " + remoteMessage.getFrom());

    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        sendNotification(remoteMessage.getData().get("message").toString(), remoteMessage.getData().get("title").toString());
    }

}

private void sendNotification(String message, String title) {
        int requestID = (int) System.currentTimeMillis();
        Intent intent = new Intent(this, activityCompat);
        
        PendingIntent pendingIntent = PendingIntent.getActivity(this, requestID, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.small_logo)
                .setContentTitle(title)
                .setContentText(message).setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .setStyle(new NotificationCompat.BigTextStyle()
                        .bigText(messageBody))
                .setTicker(messageBody);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationBuilder.getNotification().flags |= Notification.FLAG_AUTO_CANCEL;
        Notification notification = notificationBuilder.build();

        notificationManager.notify(0, notification);

}

1
我可以确认这是有效的。然而,如果您的应用程序被关闭或处于深度睡眠状态,通知只会在应用程序被唤醒后才会到达。 - anandbibek

6

如果您想将两个或多个通知(在消息列表中指定)堆叠起来,并使它们看起来像GMail样式的通知,您可以为您的通知添加收件箱样式,如下所示:

    private void showNotification(Context mContext, String title, List messages, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {

    final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
            mContext);

    NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();

    for(int i=0;i<messages.size();i++)
        inboxStyle.addLine(messages.get(i));

    Notification notification;
    notification = mBuilder.setTicker(title)
            .setAutoCancel(true)
            .setContentTitle(title)
            .setContentIntent(resultPendingIntent)
            .setSound(alarmSound)
            .setStyle(inboxStyle)
            .setWhen(getTimeMilliSec(timeStamp))
            .setSmallIcon(R.drawable.notification_small_icon)
            .setLargeIcon(R.drawable.notification_large_icon)
            .setDeleteIntent(PendingIntent.getBroadcast(mContext,101,new Intent(mContext, NotificationDismissedReceiver.class),PendingIntent.FLAG_CANCEL_CURRENT))
            .build();

    NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(NConfig.NOTIFICATION_ID, notification);
    }

如果你注意到了,我还为我的通知添加了“删除意图”,它会触发NotificationDismissedReceiver(广播接收器),其主要工作是清除已被滑动手势解除的通知消息,这样下一次只有新的通知消息才会堆叠在一起。
public class NotificationDismissedReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    // TODO: This method is called when the BroadcastReceiver is receiving
    // an Intent broadcast.
    messages.clear();
}
}

主要逻辑是将所有未读/未划掉的通知收集到一个列表中,即消息。以下是FirebaseMessagingService的onMessageReceive()方法:
    public void onMessageReceived(RemoteMessage remoteMessage) {
    Log.e(TAG, "From: " + remoteMessage.getFrom());

    if (remoteMessage == null)
        return;

    if (remoteMessage.getData()!=null && remoteMessage.getData().size() > 0) 
    {

        try {
            JSONObject json = new JSONObject(remoteMessage.getData().toString());
            Log.e(TAG, "Notification Data: " + json);
            Title = json.get("title").toString();
            Message = json.get("body").toString();
            messages.add(Message);

        } catch (Exception e) {
            Log.e(TAG, "Exception: " + e.getMessage());
        }
     }

       showNotification(...);
     }

当应用程序处于前台时,FirebaseMessagingService的onMessageReceive()方法可以正常执行,但当您的应用程序处于后台或已被关闭时,该方法不会执行。为了使它执行,您必须从服务器端发送的JSON消息中省略通知部分,仅包含数据部分,如下所示:
       var data = new
       {
           to = token,
        //   notification = new
        //   {
        //       body = messageBody,   //Omitting notification part of data
        //       title = messageTitle,
        //       icon = "myicon",
        //},
        data = new
        {
               body = messageBody,  // adding all notification information inside data
               title = messageTitle,
               icon = "myicon",
           }
       };

通过这样做,您的消息现在变成了数据消息,这意味着无论您的应用程序处于后台还是前台,它都将始终执行FirebaseMessagingService的onMessageReceive()方法。
希望这个解释可以帮到你。

在我的情况下,当应用程序被杀死或长时间处于后台时,onMessageReceive()会执行,但不会从数据库中创建所有通知以及组摘要通知。虽然当应用程序在前台时它工作得很好。此外,在应用程序被杀死时通过从通知托盘滑动删除通知时,删除广播不会被调用。我只从我的服务器获取通知数据。你能告诉我我做错了什么吗? - Sumit Kumar
这个回答显然没有回答问题。当应用程序被杀死时,您无法调用这些方法。 - Pushan Gupta
@VidorVistrom 当应用程序被杀死时,如果在其onMessageReceive()中接收到某些广播消息,则会重新启动它,并且一旦应用程序启动,您可以启动与其相关的任何其他组件。 - Rishabh

3
您可以使用以下代码对通知进行分组。我正在使用 Android Web 视图应用程序,因此将 URL 作为意图内容传递。基于 Android 版本,我使用了 2 种通知分组方式,因为 Android Nougat 和更高版本会根据组 ID 自动对通知进行分组,但 Marshmallow 和更早的版本不会对通知进行分组。请记住一件事,您应该将通知发送为数据通知。因为您可以在 onMessageReceived 中处理数据通知,即使应用程序处于后台或已杀死状态。
我的 Firebase 消息处理服务如下:
import static com.packageName.config.AppConstant.MY_NOTIFICATION;

public class MyFireBaseMessagingService extends FirebaseMessagingService {
    private static final String TAG = "MyFireBaseService";
    private static final int SUMMARY_ID = 999;

    @Override
    public void onNewToken(String refreshedToken) {
        super.onNewToken(refreshedToken);
        //Store fcm token to shared preferences
        SharedPrefManager.getInstance(getApplicationContext()).setFCMToken(refreshedToken);
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    /* Data messages should be in the form of
     * {
     *      type(Required)              : "NotificationDTO type"
     *      title(Required)             : "NotificationDTO title"
     *      message(Required)           : "Message to be displayed in the notification panel"
     *      notificationURL(Required)   : "Url to be loaded into the web view"
     *      groupId(Optional)           : "Based on this group id, system will group the notification"
     *      channelId(optional)         : "This channel id will be used to send notification"
     *      image(optional)             : "This image will be displayed on notification panel"
     *      label(optional)             : "NotificationDTO label"
     *      priority(optional)          : "NotificationDTO priority. If notification priority not mentioned,
     *                                     Then default priority will be assigned to the notification"
     * }
     */
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        boolean isForeGround = false;

        super.onMessageReceived(remoteMessage);
        // Fetching data part from the notification
        Map<String, String> data = remoteMessage.getData();
        String message = data.get("message");
        String id = data.get("notificationId");
        int notificationId;

        // If notification id is empty then no need to show a notification
        if (id == null || id.isEmpty()) {
            return;
        } else {
            notificationId = Integer.parseInt(id);
        }
        if (message == null || message.equals("")) {
            message = getString(R.string.default_notification_message);
        }
        String notificationURL = data.get("notificationURL");
        String title = data.get("title");

        // Group id should be a string
        String groupKey = AppConstant.GROUP_KEY_NOTIFICATION;
        if (data.get("groupKey") != null) {
            groupKey = data.get("groupKey");
        }

        // Current we have only one channel with id `general_notification_id`
        String channelId = data.get("channelId");
        String label = data.get("label");
        String image = data.get("image");

        /*
         *  Notification priority(String Value) should be one of the following
         *  PRIORITY_HIGH/PRIORITY_LOW/PRIORITY_MAX/PRIORITY_MIN
         *  If no priority mentioned, system will automatically assign the default priority
         */
        String priority = data.get("priority");
        int notificationPriority = 0;
        if (priority != null && !priority.isEmpty()) {
            priority = priority.toUpperCase();
            switch (priority) {
                case "PRIORITY_HIGH":
                    notificationPriority = NotificationCompat.PRIORITY_HIGH;
                    break;
                case "PRIORITY_LOW":
                    notificationPriority = NotificationCompat.PRIORITY_LOW;
                    break;
                case "PRIORITY_MAX":
                    notificationPriority = NotificationCompat.PRIORITY_MAX;
                    break;
                case "PRIORITY_MIN":
                    notificationPriority = NotificationCompat.PRIORITY_MIN;
                    break;
                default:
                    notificationPriority = NotificationCompat.PRIORITY_DEFAULT;
                    break;
            }
        }

        /*
         *  Category should be from the following list.
         *  Because system will sort the notification based on the category.
         *
         *  CATEGORY_ALARM,CATEGORY_CALL,CATEGORY_MESSAGE,CATEGORY_EMAIL,CATEGORY_EVENT,
         *  CATEGORY_PROMO,CATEGORY_ALARM,CATEGORY_PROGRESS,CATEGORY_SOCIAL,CATEGORY_ERROR,
         *  CATEGORY_TRANSPORT,CATEGORY_SYSTEM,CATEGORY_SERVICE,CATEGORY_REMINDER,
         *  CATEGORY_RECOMMENDATION,CATEGORY_STATUS
         */
        String category = data.get("category");
        String notificationCategory = "";
        if (category != null && !category.isEmpty()) {
            category = category.toUpperCase();
            switch (category) {
                case "CATEGORY_ALARM":
                    notificationCategory = NotificationCompat.CATEGORY_ALARM;
                    break;
                case "CATEGORY_CALL":
                    notificationCategory = NotificationCompat.CATEGORY_CALL;
                    break;
                case "CATEGORY_MESSAGE":
                    notificationCategory = NotificationCompat.CATEGORY_MESSAGE;
                    break;
                case "CATEGORY_EMAIL":
                    notificationCategory = NotificationCompat.CATEGORY_EMAIL;
                    break;
                case "CATEGORY_EVENT":
                    notificationCategory = NotificationCompat.CATEGORY_EVENT;
                    break;
                case "CATEGORY_PROMO":
                    notificationCategory = NotificationCompat.CATEGORY_PROMO;
                    break;
                case "CATEGORY_PROGRESS":
                    notificationCategory = NotificationCompat.CATEGORY_PROGRESS;
                    break;
                case "CATEGORY_SOCIAL":
                    notificationCategory = NotificationCompat.CATEGORY_SOCIAL;
                    break;
                case "CATEGORY_ERROR":
                    notificationCategory = NotificationCompat.CATEGORY_ERROR;
                    break;
                case "CATEGORY_TRANSPORT":
                    notificationCategory = NotificationCompat.CATEGORY_TRANSPORT;
                    break;
                case "CATEGORY_SYSTEM":
                    notificationCategory = NotificationCompat.CATEGORY_SYSTEM;
                    break;
                case "CATEGORY_SERVICE":
                    notificationCategory = NotificationCompat.CATEGORY_SERVICE;
                    break;
                case "CATEGORY_RECOMMENDATION":
                    notificationCategory = NotificationCompat.CATEGORY_RECOMMENDATION;
                    break;
                case "CATEGORY_REMINDER":
                    notificationCategory = NotificationCompat.CATEGORY_REMINDER;
                    break;
                case "CATEGORY_STATUS":
                    notificationCategory = NotificationCompat.CATEGORY_STATUS;
                    break;
            }
        }

        // Default notification visibility is private
        String visibility = data.get("visibility");
        int notificationVisibility = 0;
        if (visibility != null && !visibility.isEmpty()) {
            visibility = visibility.toUpperCase();
            switch (visibility) {
                case "VISIBILITY_PUBLIC":
                    notificationVisibility = NotificationCompat.VISIBILITY_PUBLIC;
                    break;
                case "VISIBILITY_SECRET":
                    notificationVisibility = NotificationCompat.VISIBILITY_SECRET;
                    break;
                default:
                    notificationVisibility = NotificationCompat.VISIBILITY_PRIVATE;
                    break;
            }
        }
        //creating default notification url for grouped notifications
        // if notification grouped, user cannot go the url corresponding to the each notification therefore assign a common url for the notification 
        String defaultNotificationURL = "https://something.com"

        // Creating notification object
        NotificationDTO notificationDTO = new NotificationDTO(
                notificationId,
                groupKey,
                message,
                notificationURL,
                channelId,
                image,
                label,
                notificationPriority,
                title,
                notificationCategory,
                notificationVisibility,
                defaultNotificationURL);

        // Checking app is in foreground or background
        // if the app in the foreground this message service send a broadcast message
        // else app will create a notification in notification panel
        try {
            isForeGround = new ForegroundCheckTask().execute(this).get();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //Android implement new grouping and channel mechanisms after android API version 24,
        //So we need to implement different notification settings for both above 24 and below 24
        if (android.os.Build.VERSION.SDK_INT >= 24) {
            createNotificationForAPILevelAbove24(notificationDTO, isForeGround);
        } else {
            createNotificationForAPILevelBelow24(notificationDTO, isForeGround);
        }
    }

    /**
     * Creating notification for api level above 24
     *
     * @param notificationDTO NotificationDTO
     * @param isForeGround    Boolean
     */
    private void createNotificationForAPILevelAbove24(NotificationDTO notificationDTO, Boolean isForeGround) {

        Log.d(TAG, String.valueOf(isForeGround));
        if (isForeGround) {
            Intent intent = new Intent(MY_NOTIFICATION);
            intent.putExtra("notificationURL", notificationDTO.getNotificationURL());
            LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
        } else {
            int requestID = (int) System.currentTimeMillis();
            Intent intent = new Intent(this, MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.putExtra("notificationURL", notificationDTO.getNotificationURL());

            PendingIntent resultIntent = PendingIntent.getActivity(this, requestID, intent,
                    PendingIntent.FLAG_ONE_SHOT);
            Uri notificationSoundURI = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            String defaultChannel = getString(R.string.general_notification_id);
            NotificationCompat.Builder mNotificationBuilder = new NotificationCompat.Builder(this, defaultChannel);
            mNotificationBuilder.setSmallIcon(R.drawable.ic_stat_notification);
            mNotificationBuilder.setColor(getResources().getColor(R.color.colorPrimary));
            mNotificationBuilder.setContentTitle(notificationDTO.getTitle());
            mNotificationBuilder.setContentText(notificationDTO.getMessage());
            mNotificationBuilder.setGroup(notificationDTO.getGroupKey());
            mNotificationBuilder.setAutoCancel(true);
            mNotificationBuilder.setSound(notificationSoundURI);
            mNotificationBuilder.setPriority(notificationDTO.getPriority());
            if (notificationDTO.getImage() != null) {
                Bitmap bitmap = getBitmapFromUrl(notificationDTO.getImage());
                mNotificationBuilder.setStyle(new NotificationCompat.BigPictureStyle()
                        .bigPicture(bitmap));
            }
            mNotificationBuilder.setContentIntent(resultIntent);
            if (notificationDTO.getCategory() != null) {
                mNotificationBuilder.setCategory(notificationDTO.getCategory());
            }
            mNotificationBuilder.setVisibility(notificationDTO.getVisibility());
            NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
            boolean areNotificationsEnabled = notificationManager.areNotificationsEnabled();
            String appPushEnabled = String.valueOf(areNotificationsEnabled);
            notificationManager.notify(notificationDTO.getId(), mNotificationBuilder.build());

            // Creating notification summary for grouping notifications
            Notification summaryNotification =
                    new NotificationCompat.Builder(this, defaultChannel)
                            .setContentTitle(getString(R.string.app_name))
                            .setSmallIcon(R.drawable.ic_stat_notification)
                            //specify which group this notification belongs to
                            .setGroup(notificationDTO.getGroupKey())
                            //set this notification as the summary for the group
                            .setGroupSummary(true)
                            //automatically remove the notifications from the notification tray
                            .setAutoCancel(true)
                            .build();
            notificationManager.notify(getString(R.string.app_name), SUMMARY_ID, summaryNotification);
        }
    }

    /**
     * Handling notification for api level below 24
     *
     * @param notificationDTO NotificationDTO
     * @param isForeGround    Boolean
     */
    private void createNotificationForAPILevelBelow24(NotificationDTO notificationDTO, Boolean isForeGround) {
        if (isForeGround) {
            Intent intent = new Intent(MY_NOTIFICATION);
            intent.putExtra("notificationURL", notificationDTO.getNotificationURL());
            LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
        } else {
            //Grouping notifications
            String storedNotifications = SharedPrefManager.getInstance(this).getNotifications();
            JSONArray notificationArray;
            try {
                boolean isDuplicateNotification = false;
                JSONObject notificationObject = new JSONObject();
                notificationObject.put("notificationId", notificationDTO.getId());
                notificationObject.put("description", notificationDTO.getMessage());
                notificationObject.put("title", notificationDTO.getTitle());
                if (storedNotifications != null && !storedNotifications.equals("")) {
                    Log.d(TAG, storedNotifications);
                    notificationArray = new JSONArray(storedNotifications);
                    for (int i = 0; i < notificationArray.length(); i++) {
                        JSONObject json = notificationArray.getJSONObject(i);
                        if (json.getInt("notificationId") == notificationDTO.getId()) {
                            isDuplicateNotification = true;
                            break;
                        }
                    }
                } else {
                    notificationArray = new JSONArray();
                }
                if (isDuplicateNotification) {
                    //Notification already added to the tray
                    return;
                }
                notificationArray.put(notificationObject);
                SharedPrefManager.getInstance(this).setNotificationDetails(notificationArray.toString());
                Uri notificationSoundURI = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
                NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                NotificationCompat.Builder summary = new NotificationCompat.Builder(this);
                summary.setSmallIcon(R.drawable.ic_stat_notification);
                summary.setGroup(notificationDTO.getGroupKey());
                summary.setAutoCancel(true);
                summary.setPriority(notificationDTO.getPriority());
                summary.setColor(ContextCompat.getColor(this, R.color.colorPrimary));
                summary.setSound(notificationSoundURI);
                summary.setContentTitle(notificationDTO.getTitle());
                summary.setContentText(notificationDTO.getMessage());
                summary.setPriority(notificationDTO.getPriority());
                if (notificationDTO.getCategory() != null) {
                    summary.setCategory(notificationDTO.getCategory());
                }
                summary.setVisibility(notificationDTO.getVisibility());
                if (notificationDTO.getImage() != null) {
                    Bitmap bitmap = getBitmapFromUrl(notificationDTO.getImage());
                    summary.setStyle(new NotificationCompat.BigPictureStyle()
                            .bigPicture(bitmap));
                }
                /*
                 *  This is used to pass notification url to the main class of the application.
                 *  Based on this url MainActivity load the corresponding url into the web view
                 */
                Intent intent = new Intent(this, MainActivity.class);

                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

                /*
                 * checking more than 2 notifications received by the system,
                 * then this will create a summary of that notifications.
                 * else create a single notification
                 */
                if (notificationArray.length() > 1) {

                    summary.setGroupSummary(true);

                    NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();

                    inboxStyle.setBigContentTitle(getString(R.string.app_name));

                    summary.setStyle(inboxStyle);
                    int messageCount;
                    for (messageCount = 0; messageCount < notificationArray.length(); messageCount++) {
                        JSONObject json = notificationArray.getJSONObject(messageCount);
                        inboxStyle.addLine(json.getString("title") + " " + json.getString("description"));
                    }
                    inboxStyle.setSummaryText(String.valueOf
                            (messageCount) + " notifications");
                    summary.setNumber(messageCount);
                    summary.setContentText(String.valueOf(messageCount + " notifications"));
                    intent.putExtra("notificationURL", notificationDTO.getDefaultNotificationUrl());
                } else {
                    intent.putExtra("notificationURL", notificationDTO.getNotificationURL());
                }

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

                summary.setContentIntent(resultIntent);

                /*
                 *  One cancel intent is used to clear the notifications stored in
                 *  the shared preferences when user delete the notifications.
                 */
                Intent onCancelIntent = new Intent(this, OnCancelBroadcastReceiver.class);

                PendingIntent onDismissPendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, onCancelIntent, 0);

                summary.setDeleteIntent(onDismissPendingIntent);

                notificationManager.notify(getString(R.string.app_name), SUMMARY_ID, summary.build());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Used to load image from notification
     *
     * @param imageUrl String
     * @return Bitmap
     */
    public Bitmap getBitmapFromUrl(String imageUrl) {
        try {
            URL url = new URL(imageUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream input = connection.getInputStream();
            return BitmapFactory.decodeStream(input);

        } catch (Exception e) {
            return null;
        }
    }
}

通知对象类如下所示:

public class NotificationDTO {
    private String groupKey, message, notificationURL, channelId;
    private String image, label, title, category,defaultNotificationUrl;
    private int priority, id, visibility;

    public NotificationDTO(
            int id,
            String groupKey,
            String message,
            String notificationURL,
            String channelId,
            String image,
            String label,
            int priority,
            String title,
            String category,
            int visibility,
            String defaultNotificationUrl) {
        this.groupKey = groupKey;
        this.message = message;
        this.id = id;
        this.notificationURL = notificationURL;
        this.channelId = channelId;
        this.image = image;
        this.label = label;
        this.priority = priority;
        this.title = title;
        this.category = category;
        this.visibility = visibility;
        this.defaultNotificationUrl = defaultNotificationUrl;
    }

    public String getGroupKey() {
        return groupKey;
    }

    public String getMessage() {
        return message;
    }

    public String getNotificationURL() {
        return notificationURL;
    }

    public String getChannelId() {
        return channelId;
    }

    public String getLabel() {
        return label;
    }

    public String getImage() {
        return image;
    }

    public int getPriority() {
        return priority;
    }

    public String getTitle() {
        return title;
    }

    public String getCategory() {
        return category;
    }

    public int getId() {
        return id;
    }

    public int getVisibility() {
        return visibility;
    }

    public String getDefaultNotificationUrl() {
        return defaultNotificationUrl;
    }
}

像以下这样的SharedPreference管理器:

public class SharedPrefManager {
    private static final String KEY_FCM_TOKEN = "keyFCMToken";
    private static final String KEY_NOTIFICATIONS = "keyNotifications";
    private static SharedPrefManager mInstance;
    private static Context mContext;

    private SharedPrefManager(Context context) {
        mContext = context;
    }

    public static synchronized SharedPrefManager getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new SharedPrefManager(context);
        }
        return mInstance;
    }

    public void setNotificationDetails(String descriptions) {
        SharedPreferences sharedPreferences = mContext.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(KEY_NOTIFICATIONS, descriptions);
        editor.apply();
    }
    public void setFCMToken(String fcmToken) {
        SharedPreferences sharedPreferences = mContext.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(KEY_FCM_TOKEN, fcmToken);
        editor.apply();
    }
    public String getNotifications() {
        SharedPreferences sharedPreferences = mContext.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
        return sharedPreferences.getString(KEY_NOTIFICATIONS, null);
    }

    public String getFCMToken() {
        SharedPreferences sharedPreferences = mContext.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
        return sharedPreferences.getString(KEY_FCM_TOKEN, null);
    }
}

我使用扩展应用程序类的应用程序控制器类来创建通知通道。

public class AppController extends Application {
    public static final String TAG = AppController.class.getSimpleName();
    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
        /*
          Define notification channels here.
         */
        //NotificationDTO channel is necessary
        //create  a notification channel id in res/values/strings.xml
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Create channel to show notifications.
            String defaultChannel = getString(R.string.general_notification_id);
            String channelName = getString(R.string.general_notification_name);
//            String miscellaneousChannel = getString(R.string.miscellaneous_notification_id);
//            String miscellaneousChannelName = getString(R.string.miscellaneous_notification_name);
            NotificationManager notificationManager =
                    getSystemService(NotificationManager.class);
            if (notificationManager != null) {
                notificationManager.createNotificationChannel(new NotificationChannel(defaultChannel,
                        channelName, NotificationManager.IMPORTANCE_DEFAULT));
            }
        }
    }

一个广播接收器的实现方式,用于清除共享参数如下所示。
public class OnCancelBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("ON_CANCEL","Cancelled");
        SharedPrefManager.getInstance(context).setNotificationDetails("");
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接