Битва за уведомления в React Native
Во время теста нового мобильного приложения для Такси 42 нашел неприятную особенность. Иногда не приходят оповещения о том, что автомобиль подъехал и ожидает. Это случается на слабых устройствах с небольшим количеством памяти. Если одновременно запустить что-то тяжелое, то из-за нехватки ресурсов Андроид «убивает» сервис, следящий за статусом заказа.
В моих тестах этим «тяжёлым» было Яндекс Go. Не секрет, что многие часто запускают несколько приложений такси стремясь уехать подешевле или побыстрее. Я повторял это поведение на стареньком телефоне всего с двумя гигабайтами оперативки. Он не выдерживал нагрузки и принудительно закрывал работающие в фоне приложения. Включая и наше.

Я стал дебажить библиотеку Notifee, которую использую для фоновой работы с оповещениями. Пришлось залезть к ней «под капот» в нативный Java-код, хоть я и не особо силён в нём. Напомню, что я пишу на React Native.
Так вот, есть два режима, в которых можно стартовать сервис: START_STICKY и START_NOT_STICKY. В первом Андроид будет пытаться заново запустить его после принудительного завершения. А во втором — нет. Так вот, библиотека Notifee использует именно второй режим. И нет никакого способа повлиять на это через параметры или настройки.
Я встал перед дилеммой: форкать и модифицировать Notifee, либо вовсе от неё отказаться и переписать сервис на нативном модуле. Выбор пал на нативный модуль. Править чужой код не зная нюансов — такое себе занятие. Тем более, я за любой способ сделать приложение легче. А тут такая возможность избавиться от целой библиотеки. Заодно попрактикуюсь в написании кода на Java.
Я выкинул Notifee, переписал сервис и вернулся к тестам. START_STICKY помог, но не совсем. В особенно тяжелых случаях Андроид после рестарта сервиса тут же снова его «прибивал». На этот раз окончательно.
Исправить ситуацию могла бы только отмена экономии заряда. По умолчанию Андроид старается оптимизировать работу приложений, чтобы те поменьше тратили батарею. И в фоне закрывает их при первой возможности. Однако, для некоторых приложений оптимизацию можно отключить через настройки. Тогда Андроид не будет их трогать.
Беда в том, что приложение не может само себе отключить оптимизацию. Для этого оно должно запросить разрешение у пользователя. Так устроен Андроид. А просить человека отключить экономию батареи — это несколько нескромно. Лучше так не делать чтобы не оставить негативных эмоций.
Словом, на сегодня проблема решена на половину. Приложение старается перезапустить сервис оповещений после «убийства». Это получается не всегда, поэтому по прежнему сохраняется опасность пропустить оповещение о подъехавшей машине. Хорошо, что оно дублируется звонком от робота.
Хорошим решением было бы использовать push-уведомления вместо сервиса. Возможно, мы перейдём на них. Хотя, сейчас, в условиях ограничений мобильного интернета, всё равно не обойтись от дублирования оповещений звонком. Поэтому пока работаем в этом режиме и копим статистику.