Создание локального уведомления в ответ на push-уведомление (из firebase) в кордовой/ионной

Я создаю приложение с использованием Ionic Framework, которое реализует функцию чата, похожую на добрый старый facebook messenger, в котором я хочу уведомить пользователей о сообщении чата, но если они просмотрят его в другом месте, я хочу удалить уведомление с их главного экрана.

Я использую firebase в качестве back-end для push-уведомлений (хотя это может быть изменено, я полагаю).

Я знаю, что вы не можете истечь удаленного уведомления, но мне сказали, что вы можете истечь + удалить локальное уведомление, поэтому мой вопрос - может надежно получить удаленное уведомление, создать локальный, и отобразите это, а затем в ответ на уведомление с областью действия "expire" или "remove" удалите локальное уведомление, чтобы мои пользователи не видели дублирование информации?

Большинство плагинов имеют тенденцию обнаруживать статус приложения и добавлять удаленное уведомление на рабочий стол с информацией, которую вы нажали по умолчанию, есть ли способ избежать этого?

Спасибо, ребята.

EDIT: - Локальные уведомления: http://ionicframework.com/docs/native/local-notifications/ - Firebase cloud messaging: https://github.com/fechanique/cordova-plugin-fcm

Ответ 1

Насколько я могу судить, нет плагинов, которые выполняют все, что вам нужно. Однако..

можно надежно получить удаленное уведомление, создать локальный и отобразить это, а затем в ответ на уведомление с областью действия "expire" или "remove" удалить локальное уведомление, чтобы мои пользователи не см. дублирование информации?

Большинство плагинов имеют тенденцию обнаруживать статус приложения и добавлять удаленное уведомление на рабочий стол с информацией, которую вы нажали по умолчанию, есть ли способ избежать этого?

Да, используя тихие уведомления и самостоятельно создав локальное уведомление.

Для проекта, над которым я работаю, я модифицировал плагин cordova-plugin-fcm, чтобы добавить поддержку (локальный по требованию) уведомлений об увольнении/отображении, отправке нескольких уведомлений в приложение cordova и некоторых PR, которые еще не включены. Также я самостоятельно создаю уведомление, чтобы иметь полный контроль над тем, что отображается. Вы можете взглянуть на код, чтобы получить некоторые идеи.

Вкратце он работает следующим образом:

Во-первых, я посылаю "тихий" push-приложение, которое не отображается Android:

{
    "content_available": true, // IMPORTANT: For Apple -> content-available: 1, for firebase -> content_available: true
    "priority": "high",
    "to": "/topics/all", // or to a fcm token
    "data"{
        "title": "My title", // this implies that you display the notification by yourself
        "body": "My body", // this implies that you display the notification by yourself
        "type": "NEW_USER_MESSAGE", // only relevant to this project
        "userId": "1", // only relevant to this project
        "timestamp", "150000000"
    }
}

Примечание. Если полезная нагрузка имеет элемент "notification": {}, Android отобразит ее на панели задач (если приложение находится в фоновом режиме). https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages

Во-вторых, когда push прибывает в приложение (в onMessageReceived(), я создаю локальное уведомление, назначая ему TAG и Я БЫ. Так вы можете использовать, чтобы уволить его позже. Например, вы можете создать локальное уведомление с помощью TAG "NEW_USER_MESSAGE" и ID 1 (константа, указывающая состояние сообщения или идентификатор пользователя, например). Кроме того, Android заменит уведомления на те же теги и идентификаторы, так что это еще один способ автоматической замены уведомлений (например, если вы отправляете общее сообщение, например "Новое обновление доступно" ).

    public static String TYPE_NEW_USER_MESSAGE = "NEW_USER_MESSAGE";
    public static String TYPE_USER_LEFT_ROOM = "USER_LEFT_ROOM";

    NotificationManager notificationManager =
            (NotificationManager) _ctx.getSystemService(Context.NOTIFICATION_SERVICE);

    // based in the type of the message you've received, you can stylize the notification
    if (type.equals( TYPE_USER_LEFT_ROOM )){
        notificationBuilder.setColor(Color.RED);
        notificationBuilder.setLights(Color.RED, 1000, 500);
    }
    else if (type.equals( TYPE_NEW_USER_MESSAGE )){
        notificationBuilder.setColor(Color.BLUE);
        notificationBuilder.setLights(Color.BLUE, 1000, 1000);
    }

    Notification n = notificationBuilder.build();
    notificationManager.notify(type, userId, n);

Одно из преимуществ этого способа состоит в том, что вы полностью контролируете отображаемое уведомление, поэтому можете стилизовать его так, как хотите.

Если вы хотите отменить истекшие сообщения, вы можете проверить прошедшее время между отправленной меткой времени и текущей меткой времени:

java.util.Date now = new java.util.Date();
java.util.Date sent_timestamp = new java.util.Date( Long.valueOf(timestamp.toString()) );
            final Long elapsed_time = ((now.getTime() - sent_timestamp.getTime()) / 1000);
Log.d(TAG, "New message. sent " + elapsed_time + "s ago");

В-третьих, когда пользователь нажимает на уведомление, Android запустит ваше приложение, и плагин отправит полезную нагрузку push-сообщения в представление cordova (onNotificationReceived()).

Как только ваше приложение будет открыто и вы получите push-сообщение, вы можете отклонить его, добавив новое действие в плагин:

onNotificationReceived(data){
    if (data.wasTapped === true){
        if (data.type === 'NEW_USER_MESSAGE'){
            FCMPlugin.dismissNotification(NEW_USER_MESSAGE, 1);
        }
    }
}

Действие Android:

else if (action.equals( ACTION_DISMISS_NOTIFICATION )) {
    cordova.getThreadPool().execute(new Runnable() {
        public void run() {
            try{
                Log.d(TAG, "FCMPlugin dismissNotificaton: " + args.getString(0)); //tag
                NotificationManager nManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
                        nManager.cancel(args.getString(0)/*NEW_USER_MESSAGE*/, args.getInt(1) /*1*/);
                Log.d(TAG, "FCMPlugin dismissNotificaton() to remove: " + id); //tag
                callbackContext.success();
            }catch(Exception e){
                callbackContext.error(e.getMessage());
            }
       }
 });

https://github.com/TrustedCircles/cordova-plugin-fcm/blob/master/src/android/FCMPlugin.java#L286

И метод, открытый для приложения cordova:

// dismisses a notification by tag+id
FCMPlugin.prototype.dismissNotification = function( tag, userId, success, error ){
    exec(success, error, "FCMPlugin", 'dismissNotification', [tag, userId]);
}

https://github.com/TrustedCircles/cordova-plugin-fcm/blob/master/www/FCMPlugin.js#L65

Ответ 2

Единственный сложный бит с уведомлениями в cordova/ionic - это часть JS, которая получает уведомление и запускает код Android.

Я использовал https://github.com/phonegap/phonegap-plugin-push библиотеку и ее довольно прямолинейную.

Существует обратный вызов, когда уведомления принимаются в JS (Cordova/Ionic), используйте это для визуализации уведомлений локально на Android.

P.S: Базельский ответ подсказывает, как очистить ваши уведомления, поэтому я решил оставить это.