
Комментарии 9
Я не погромист, но считаю себя умеющим писать ТЗ. С помощью антигравити создал рабочий проект по передачи пушей с одного устройства на другое. Суть проекта в том, что если у человека много телефонов, собирать пуши с них на основной, где, например, часы привязаны. Или как вариант прямо на часы.
Разумеется, нужно было обходиться без всякого кривого gms, который и работает не понятно как, и не везде есть, а на часах и нет. Поэтому было выбрано решение использовать отдельный сервер (оно написало его на go) и mttq протокол. Приложения успешно объединяются в группу, есть фильтры и прочее. Сама передача пушей работает отлично даже при проблемах с gms. В качестве идентификатора группы устройств используются guid, регистрация не нужна.
Что думаете о таком концепте?
Концепт рабочий, и вы, по сути, независимо пришли к той же архитектуре, что и UnifiedPush: приложение получает у дистрибьютора адрес, сервер шлёт туда, дистрибьютор будит устройство. Разница в транспорте (у вас MQTT, у нас HTTP плюс WebSocket) и в том, что у вас адресом служит GUID группы, а у нас топик.
MQTT тут выбран удачнее, чем кажется на первый взгляд. У него дешёвый keepalive и нативный fan-out на нескольких подписчиков, а «раздать одно уведомление на телефон, планшет и часы» это ровно pub/sub. Мы остались на WebSocket только потому, что переиспользовали готовый ntfy, а если бы писали с нуля именно под несколько устройств одного человека, MQTT был бы честным кандидатом.
Три вещи, о которых стоит подумать, если проект выйдет за пределы личного пользования.
Первое. GUID у вас одновременно и адрес, и пароль: кто его узнал, тот и читает ваши уведомления, и подсовывает свои. У нас та же модель для топика, и это осознанный размен, но содержимое до сервера уже зашифровано, сервер видит шифротекст. У вас, если я правильно понял, текст уведомления идёт через сервер как есть, и это единственное место, где стоит навести порядок в первую очередь.
Второе. Дедупликация. Когда на одну группу подписаны телефон и часы, полезно, чтобы прочтение на одном гасило уведомление на другом, иначе часы будут вибрировать тем, что вы уже посмотрели.
Третье. Doze и вендорские «оптимизаторы» убивают долгоживущее соединение с большим удовольствием, и MQTT тут не защищён ничем по сравнению с WebSocket. Держите соединение foreground-сервисом и смотрите на интервал keepalive: слишком короткий ест батарею, слишком длинный даёт минуты задержки после выхода из сна.
Встречный вопрос, самому интересно: как вы снимаете уведомления с исходных телефонов, через NotificationListenerService? И что делаете с пачками, когда мессенджер присылает десяток уведомлений подряд, схлопываете или льёте как есть?
Как вы помните мы делаем мессенджер.
Нет, мы не помним. Нас тут десятки тысяч и все не следят за вашими статьями. А вам трудно дать в каждой статье хотя бы ссылку на сайт или репо вашего мессенджера? Или вам не нужны клиенты? Я понимаю политику “кому надо, тот сам всё разроет и сам разберётся”, но нужна ли вам именно эта политика?
Кстати, зашёл на репо. В главной папке нет readme. Почему?
При установке на Андроид, на одном из начальных экранов написано: работает через Bluetooth и Wi-Fi direct. А через стандартный инет работает? Непонятно.
По всем трём пунктам справедливо, спасибо. По порядку.
Про «как вы помните»: вы правы, так писать нельзя, читатель видит нас впервые. Поправили начало статьи, ссылка на сайт и на репозитории теперь в первом абзаце, а не в футере.
Про README: полез проверять и нашёл кое-что похуже. В репозиториях клиентов README есть, но у Android он был написан задолго до текущего состояния и сообщал, что это pre-alpha, в Play не выкладывается и кросс-платформенная совместимость ещё допиливается. Всё это давно неправда. Устаревший README хуже отсутствующего, потому что он отвечает на вопрос, и отвечает неверно. Переписали: что это, где скачать, что где лежит в коде, как собрать. Заодно нашли публичный репозиторий со спекой, у которого README действительно не было, добавили. Если вы заходили в какой-то третий репозиторий, скажите в какой, посмотрим и его.
Про Bluetooth и Wi-Fi Direct: это целиком наш косяк в тексте, а не ваше невнимание. Обычная переписка идёт через интернет, как в любом мессенджере. Bluetooth и Wi-Fi Direct это отдельный режим (Радиочат) на случай, когда сети нет совсем: устройства рядом находят друг друга и передают сообщения напрямую. Слайд онбординга был написан так, что читался как описание всего продукта. Текст переписали, в следующей сборке он начинается со слов о том, что обычная переписка идёт через интернет.
Спасибо за оперативный ответ и даже фиксы.
Про readme, имелась ввиду папка выше Андроида, то есть, главная папка проекта. Там нет readme.
Что пофиксили и обновили описания, это хорошо.
Точно, и это оказалось хуже, чем я сначала подумал. У организации действительно не было страницы: GitHub рисует её из специального репозитория .github, а его у нас просто не существовало. Человек приходил на организацию и видел список из восьми репозиториев без единого слова о том, что это и с чего начинать.
Сделали: github.com/rcq-messenger теперь открывается описанием проекта, таблицей «хочу сделать это, идти сюда» по всем репозиториям, ссылками на спеку, приватность и условия.
Спасибо, что дожали, сами бы мы на это ещё долго не посмотрели: когда живёшь внутри проекта, точка входа для постороннего человека это последнее, что замечаешь. Приносим изменения и еще раз благодарим за внимательность.
Как же знакомо все) Да, firebase - единственная возможность получить пуш, если приложение смахнуто. Тоже прошли через все эти костыли и остановились на таком варианте: по умолчанию сообщение дублируется на почту пользователя если не прочитано в течении 10 минут. клиенты обычно в фоне норм работают и доставка у них более стабильна
Но с «firebase единственная возможность, если приложение смахнуто» я поспорю, тут важная разница, на которую мы сами не сразу посмотрели внимательно.
Смахивание из недавних и force stop это разные вещи. Force stop убивает всё, включая доставку через FCM: система перестаёт будить приложение, пока пользователь сам его не откроет. А обычное смахивание из списка недавних на стоковом Android не убивает foreground-сервис, и постоянное соединение переживает его спокойно. Именно так живёт ntfy, и именно так теперь живём мы: свой сокет в foreground-сервисе, ценой постоянного уведомления в шторке. Firebase выигрывает не в том, что он один умеет пережить смахивание, а в том, что при нём вашему приложению вообще не надо держать соединение и тратить батарею. Отдельная история это вендорские «оптимизаторы», вот они убивают и то, и другое, и с ними не воюет никто.
Дублирование на почту через 10 минут это честное инженерное решение, и оно закрывает ровно ту дыру, которая остаётся: сигнал не дошёл, но информация всё равно доехала. Нам этот путь закрыт по построению, у нас нет почты пользователя, её отсутствие это и есть продукт. Плюс для сквозного шифрования второй канал в открытом виде это шаг назад: содержимое уходит из системы к почтовому провайдеру.
Мы решили ту же задачу иначе: пуш-сервер держит сигнал в кэше 12 часов, а клиент при переподключении просит всё, что пришло после последнего доставленного, и догоняет пропущенное. Уведомление в этом случае приходит поздно, но не теряется. По сути та же гарантия, что у вас, только вторым каналом служит не почта, а само переподключение.
Интересно, как люди реагируют на дубли. Со стороны кажется, что это ровно та функция, которую часть пользователей попросит выключить, а часть не заметит вовсе. У вас есть переключатель?
Именно поэтому предыдущий пункт про туннель не косметика.
Во-первых, непонятно, что за туннель из предыдущего пункта.
Во-вторых, от этого фрагмента и всей статьи ужасно сквозит текстом, написанным ИИ.
Уведомления на Android без Google: почему UnifiedPush через публичный ntfy у вас не работает