Я работаю над обменом информацией о дорожном движении между приложениями Android и задаюсь вопросом, что такое хороший транспортный механизм.
Существует два класса приложений: Издатели публикуют сообщения трафика, которые они получили из различных источников (скажем, из службы Интернета или приемного устройства TMC) и преобразовали в стандартный формат. Подписчики слушают сообщения и работают с ними (например, отображают их в списке или направляют водителей в обход пробок). Предполагается, что система будет децентрализованной: будет несколько издателей, несколько подписчиков, и пользователи смогут смешивать и сочетать их по своему усмотрению.
Сообщения идентифицируются уникальным идентификатором, который остается неизменным на протяжении всего их жизненного цикла. У них есть срок годности, по истечении которого они считаются недействительными. До тех пор их можно обновить в любое время. Обновление также может отменить сообщение (заменив его захоронением до истечения срока его действия) или продлить срок его действия.
Подписчики получают новые сообщения по мере их поступления. (Фильтрация может произойти на более позднем этапе.) Им также нужен способ получить все кэшированные в настоящее время сообщения от всех издателей.
Размер сообщения составляет около 1 кбайт. Издатель может легко хранить несколько сотен активных сообщений в любой момент времени.
С точки зрения безопасности сообщения, как правило, являются общедоступной информацией. Единственной конфиденциальной информацией являются геоданные, поскольку они могут позволить сделать вывод о местонахождении устройства или о том, куда его пользователь намеревается отправиться. Точность таких данных низка везде, от города до уровня страны. Поэтому я не вижу необходимости скрывать эту информацию от какого-либо приложения, если оно имеет разрешение на определение местоположения.
Теперь мне интересно, каким будет хороший транспортный механизм:
Первоначально я работал с широковещательными намерениями: всякий раз, когда у издателя есть какие-либо новые сообщения, он отправляет неявную широковещательную рассылку с сообщениями в дополнениях. Подписчики могут зарегистрировать широковещательный приемник во время выполнения для получения сообщений. У них также есть возможность отправить широковещательную рассылку опроса (явная широковещательная рассылка с соответствующим получателем широковещательной рассылки, объявленным в манифесте издателя). Затем издатели ответят лентой всех кэшированных в данный момент сообщений. Для решения проблем безопасности любое приложение, отправляющее широковещательную рассылку с геоданными, требует, чтобы получатель имел одно из разрешений на определение местоположения.
Существует проблема с большими фидами, так как брокер запросов Android поддерживает максимум 1 МБ для всех одновременных транзакций (поэтому максимальный объем данных в фиде может быть даже меньше, если что-то занято). В настоящее время я работаю над этим, разбивая каналы на куски по 100 сообщений или меньше.
Преимущество этой системы в том, что вся центральная инфраструктура обеспечивается ОС. Достаточно установить одно приложение издателя и одно приложение подписчика.
Некоторые люди указали, что широковещательные намерения — не лучший путь, и предложили мне внедрить поставщика контента, территорию, на которую я пока не заходил. Глядя на документацию, неясно, есть ли способ иметь несколько серверных частей (каждая серверная часть является отдельным приложением) для реализации функционально идентичных поставщиков контента и рекламировать их как таковые. Поскольку поставщики содержимого поддерживают как операции чтения, так и записи, я мог бы настроить один центральный компонент в качестве поставщика содержимого и подключить к нему как издателей, так и подписчиков. Однако для этого потребуется предоставить центральный компонент, которого я бы предпочел избежать.
Вопросы:
Другая аналогия с FCM для push-сообщений. Там полезная нагрузка еще более ограничена (в последний раз я проверял 4 КБ). Это означает, что полезная нагрузка часто представляет собой просто URL-адрес или идентификатор, который можно использовать для извлечения остальных данных из веб-службы. Ответ не такой: «О, нет! Наши данные превышают 4 КБ! Мы не можем использовать FCM!» -- ответ состоит в том, чтобы использовать FCM для push-аспекта и разгрузить массовую доставку данных на что-то еще, что не имеет жестких ограничений по размеру.
Веб-адрес @CommonsWare не будет работать, поскольку данные полезной нагрузки не находятся в Интернете, а некоторые источники (например, TMC) даже не требуют подключения для передачи данных. Таким образом, основной вопрос заключается в следующем: как мне передать фактическую полезную нагрузку сообщения из одного приложения в другое?
«веб-URL не будет работать, поскольку данных полезной нагрузки нет в Интернете» — я это понимаю. Я проводил аналогии, чтобы помочь вам понять, в чем заключалась рекомендация. «Как мне передать фактическую полезную нагрузку сообщения из одного приложения в другое?» -- мы рекомендуем вам использовать ContentProvider. Ваша система вещания останется в основном такой же. Вместо того, чтобы удерживать большую полезную нагрузку, дополнительная удерживает от Uri до ContentProvider. Затем получатель будет использовать ContentResolver, чтобы что-то сделать с этим Uri (например, query()).
@CommonsWare, чтобы каждое приложение реализовывало своего собственного поставщика контента (в соответствии с общей спецификацией) и указывало на него в отправляемых им трансляциях? Это действительно звучит как ответ… почему бы не сделать его одним?
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 для работы, а не заставлять их «создавать свои собственные».
Мы с Гейбом предложили в твой предыдущий вопрос заменить дополнения в вашей трансляции
IntentнаUri, указывающую наContentProvider. Вы по-прежнему будете использовать существующий механизм широковещания, только со вторым шагом для получения слишком больших данных. Аналогией может быть электронное письмо, содержащее<img src = "...">с URL-адресом в Интернете вместо слишком большого изображения в качестве вложения.