Flutter звонки на ios

5a5586ab3727333c9817b0bf9aac47f4

ОООООО, кто проживает на дне стабильности приема пушей для инициализации звонка?

Ну из названия стало понятно, что со звонками на ios не все так просто, и далее расскажу почему. Но для начала чутка справки: callkit — это интерфейс телефона, когда поступает звонок, неважно откуда, мобильная связь, телеграмм, viber — если ты старообрядец.

Есть для Flutter’a интересная либа, чтобы вызывать нативный callkit, называется flutter_callkit_incoming, вот ссыль, чтобы ознакомиться детально. Для ленивых или тех, кто еще не сталкивался — суть ее работы в том, чтобы инициализировать callkit и показать на твоей любимой звонилке уведомление, что кто‑то хочет наполнить твои уши звучанием своего голоса, невзирая на то, что ты воробушек‑социофобушек.

Теперь к проблеме. Так как Flutter — кроссплатформенная штука, то нам (это я и разработчик, отвечающий за проект) хотелось написать единую логику для всего сервиса звонков. Схема такая:

  1. Человек набирает на домофоне номер;

  2. ВАТС отправляет в наш бэкенд хук с информацией, в какую квартиру звонок;

  3. бэк находит всех пользователей квартиры, используя push‑токены из базы данных отправляет silent push‑уведомления на устройства;

  4. приложение пробуждается и вызывает нативный callkit.

И нашей целью было использовать Firebase пуши для этого. Звучит просто на самом деле каждый этап вызвал разработческую боль, но ios оказался не прост.

Мы пытались выпилить нативную логику и оставить только FCM пуши для нашего приложения, но почему‑то звонки работали нестабильно, мы начали копать и наткнулись, что сообщения, которые отправляются через сервис User Notifications непригодны, так как их доставка не гарантируется, вот пруф с доки эпла:

The system makes every attempt to deliver local and remote notifications in a timely manner, but delivery isn«t guaranteed. The PushKit framework offers a more timely delivery mechanism for specific types of notifications, such as those VoIP and watchOS complications use.

Тут же подсказка, что для стабильной работы, стоит использовать PushKit вместо User Notifications. Но FCM не умеют в PushKit, что ж, не беда, написал нативную логику для использования VoIP пушей (именно они предназначены для инициализации callkit’a), бэк написал методы отправки пушей отдельно на андроид, отдельно на ios и мы столкнулись с новой проблемой! Оказывается, что обязательным результатом обработки VoIP пуша должна стать инициализация callkit. Иначе что? Правильно, иначе ОС просто банит следующие пуши. К тебе пришел курьер? «П + П», — ответит ios. Ждешь девушку? — Смотри в экран камеры домофона, а лучше спустить и жди ее такси у подъезда, ios подталкивает в джентельменству. «А в чем проблема», ‑ резонно спросишь ты, мой дорогой читатель. «А ну, да», — почесав репу отвечу я. Проблема в том, что нужно отменять звонок в случае, когда он принят на другом устройстве, отменен звонящим или произошла ошибка.

Вот что пишут эплы:

If your app repeatedly fails to report VoIP notifications to CallKit, the system stops launching your app for VoIP push notifications.

Хоть они и пишут repeatedly, но в рамках теста нам не удалось выявить систематичность бана звонков со стороны ОС, и мы сделали то, от чего старались избавиться. Написали отмену звонка для IOS через FCM и User Notifications, потому что наш бэк не нашел способа использовать два разных сервиса от эпладля отправки пуша звонка и пуши отмены звонка.

Общий вывод, зачем эта статья. Если вы пытаетесь интегрировать звонки в приложение на flutter, то для ios единственный выход использовать сервис PushKit и VoIP пуши. Не тратьте время на поиск других решений, все пруфы есть в статье. Готовый код, как прокинуть евенты во Flutter есть в самой либе flutter_callkit_incoming. Для андроида идеально работает FCM (кроме Huawei, конечно, но это другая история).

© Habrahabr.ru