Хорошая практика для обмена данными между несколькими издателями и несколькими подписчиками на Android

Я работаю над обменом информацией о дорожном движении между приложениями Android и задаюсь вопросом, что такое хороший транспортный механизм.

Существует два класса приложений: Издатели публикуют сообщения трафика, которые они получили из различных источников (скажем, из службы Интернета или приемного устройства TMC) и преобразовали в стандартный формат. Подписчики слушают сообщения и работают с ними (например, отображают их в списке или направляют водителей в обход пробок). Предполагается, что система будет децентрализованной: будет несколько издателей, несколько подписчиков, и пользователи смогут смешивать и сочетать их по своему усмотрению.

Сообщения идентифицируются уникальным идентификатором, который остается неизменным на протяжении всего их жизненного цикла. У них есть срок годности, по истечении которого они считаются недействительными. До тех пор их можно обновить в любое время. Обновление также может отменить сообщение (заменив его захоронением до истечения срока его действия) или продлить срок его действия.

Подписчики получают новые сообщения по мере их поступления. (Фильтрация может произойти на более позднем этапе.) Им также нужен способ получить все кэшированные в настоящее время сообщения от всех издателей.

Размер сообщения составляет около 1 кбайт. Издатель может легко хранить несколько сотен активных сообщений в любой момент времени.

С точки зрения безопасности сообщения, как правило, являются общедоступной информацией. Единственной конфиденциальной информацией являются геоданные, поскольку они могут позволить сделать вывод о местонахождении устройства или о том, куда его пользователь намеревается отправиться. Точность таких данных низка везде, от города до уровня страны. Поэтому я не вижу необходимости скрывать эту информацию от какого-либо приложения, если оно имеет разрешение на определение местоположения.

Теперь мне интересно, каким будет хороший транспортный механизм:

Вариант 1. Широковещательные намерения

Первоначально я работал с широковещательными намерениями: всякий раз, когда у издателя есть какие-либо новые сообщения, он отправляет неявную широковещательную рассылку с сообщениями в дополнениях. Подписчики могут зарегистрировать широковещательный приемник во время выполнения для получения сообщений. У них также есть возможность отправить широковещательную рассылку опроса (явная широковещательная рассылка с соответствующим получателем широковещательной рассылки, объявленным в манифесте издателя). Затем издатели ответят лентой всех кэшированных в данный момент сообщений. Для решения проблем безопасности любое приложение, отправляющее широковещательную рассылку с геоданными, требует, чтобы получатель имел одно из разрешений на определение местоположения.

Существует проблема с большими фидами, так как брокер запросов Android поддерживает максимум 1 МБ для всех одновременных транзакций (поэтому максимальный объем данных в фиде может быть даже меньше, если что-то занято). В настоящее время я работаю над этим, разбивая каналы на куски по 100 сообщений или меньше.

Преимущество этой системы в том, что вся центральная инфраструктура обеспечивается ОС. Достаточно установить одно приложение издателя и одно приложение подписчика.

Вариант 2. Поставщики содержимого

Некоторые люди указали, что широковещательные намерения — не лучший путь, и предложили мне внедрить поставщика контента, территорию, на которую я пока не заходил. Глядя на документацию, неясно, есть ли способ иметь несколько серверных частей (каждая серверная часть является отдельным приложением) для реализации функционально идентичных поставщиков контента и рекламировать их как таковые. Поскольку поставщики содержимого поддерживают как операции чтения, так и записи, я мог бы настроить один центральный компонент в качестве поставщика содержимого и подключить к нему как издателей, так и подписчиков. Однако для этого потребуется предоставить центральный компонент, которого я бы предпочел избежать.

Вопросы:

  • Есть ли способ реализовать описанную выше модель с несколькими издателями и несколькими подписчиками с поставщиками контента и без необходимости предоставления центрального компонента, еще не предоставленного ОС?
  • В частности, может ли один поставщик контента иметь несколько серверных частей? В качестве альтернативы, могут ли несколько функционально идентичных поставщиков контента рекламировать себя как группу?
  • Как бы я реализовал вышеизложенное с помощью поставщиков контента?
  • Каковы преимущества и недостатки широковещательных намерений или поставщиков контента, которые я мог упустить?

Мы с Гейбом предложили в твой предыдущий вопрос заменить дополнения в вашей трансляции Intent на Uri, указывающую на ContentProvider. Вы по-прежнему будете использовать существующий механизм широковещания, только со вторым шагом для получения слишком больших данных. Аналогией может быть электронное письмо, содержащее <img src = "..."> с URL-адресом в Интернете вместо слишком большого изображения в качестве вложения.

CommonsWare 20.07.2019 19:52

Другая аналогия с FCM для push-сообщений. Там полезная нагрузка еще более ограничена (в последний раз я проверял 4 КБ). Это означает, что полезная нагрузка часто представляет собой просто URL-адрес или идентификатор, который можно использовать для извлечения остальных данных из веб-службы. Ответ не такой: «О, нет! Наши данные превышают 4 КБ! Мы не можем использовать FCM!» -- ответ состоит в том, чтобы использовать FCM для push-аспекта и разгрузить массовую доставку данных на что-то еще, что не имеет жестких ограничений по размеру.

CommonsWare 20.07.2019 19:54

Веб-адрес @CommonsWare не будет работать, поскольку данные полезной нагрузки не находятся в Интернете, а некоторые источники (например, TMC) даже не требуют подключения для передачи данных. Таким образом, основной вопрос заключается в следующем: как мне передать фактическую полезную нагрузку сообщения из одного приложения в другое?

user149408 20.07.2019 20:09

«веб-URL не будет работать, поскольку данных полезной нагрузки нет в Интернете» — я это понимаю. Я проводил аналогии, чтобы помочь вам понять, в чем заключалась рекомендация. «Как мне передать фактическую полезную нагрузку сообщения из одного приложения в другое?» -- мы рекомендуем вам использовать ContentProvider. Ваша система вещания останется в основном такой же. Вместо того, чтобы удерживать большую полезную нагрузку, дополнительная удерживает от Uri до ContentProvider. Затем получатель будет использовать ContentResolver, чтобы что-то сделать с этим Uri (например, query()).

CommonsWare 20.07.2019 20:11

@CommonsWare, чтобы каждое приложение реализовывало своего собственного поставщика контента (в соответствии с общей спецификацией) и указывало на него в отправляемых им трансляциях? Это действительно звучит как ответ… почему бы не сделать его одним?

user149408 20.07.2019 20:21
0
5
143
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Is there a way to implement the above multi-publisher, multi-subscriber model with content providers

Держите трансляции. Замените полезную нагрузку.

Издатели будут реализовывать ContentProvider, который будет обслуживать текущий список сообщений. Вы можете думать о ContentProvider как о причудливой веб-службе в стиле REST, где значения Uri сопоставляются с ответами поставщика.

Издатели тогда будут отправлять трансляции, как сегодня, но, возможно, только с двумя дополнениями:

  • Тот, который идентифицирует версию протокола, которую использует широковещательная передача, поскольку у вас есть много независимо обновляемых сторон. Получатели должны знать, как интерпретировать трансляцию, так как со временем вы можете изменить правила.

  • Тот, который содержит Uri, указывающий на ContentProvider издателя.

Если есть другие дополнения, которые вы используете сегодня и которые, как вы знаете, останутся маленькими, и вы хотите по-прежнему размещать их в трансляции, это круто. Просто держите неопределенного размера вне трансляции.

Тогда получатели:

  • Посмотрите на дополнительную версию протокола и перейдите к коду для обработки этой версии (сегодня только одна ветвь, но, эй, на будущее)

  • Используйте эти Uri и ContentResolver, чтобы получать сообщения (и другие вещи, если необходимо) от издателя.

Вы можете рассмотреть возможность разработки этой коммуникационной инфраструктуры в качестве SDK. Даже если вы единственный, кто разрабатывает приложения, вам следует избегать дублирования всей этой логики в приложениях. И, если третьи стороны будут разрабатывать приложения, вам лучше предоставить им SDK для работы, а не заставлять их «создавать свои собственные».

Другие вопросы по теме