Альтернативы неявному BroadcastReceiver? - PullRequest
0 голосов
/ 24 июня 2018

В настоящее время я работаю над архитектурой для передачи сообщений о трафике («стационарный трафик на A9 между Como-Monte Olimpino и Brogeda») между приложениями.

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

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

Несколько источников и потребителей могут быть активны одновременно.

Когда источник получает новое сообщение, он отправляет широковещательный Намерение с сообщением в качестве дополнительного. Потребители регистрируют BroadcastReceiver, чтобы получить эти сообщения. (Полезная нагрузка для сообщения обычно составляет несколько сотен байтов.)

Когда потребитель запускается, мне нужно предоставить ему способ опрашивать каждый источник на наличие сообщений, которые источник может иметь в своем кэше (учитывая, что потребитель не может знать, какие источники доступны).

Моя первоначальная идея заключалась в том, чтобы сделать это также с помощью широковещательных рассылок: при запуске потребитель отправлял неявную широковещательную рассылку, а каждый источник отвечал с помощью широковещательной передачи своих текущих активных сообщений.

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

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

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

1 Ответ

0 голосов
/ 24 июня 2018

Ваше потребительское приложение должно знать:

  • Какие источники установлены

  • Какое подмножество этих источников пользователь хочет использовать в потребительском приложении (поскольку пользователь может не хотеть их всех)

Возможные способы узнать, какие источники установлены:

  • Итерация по списку известных возможных идентификаторов исходного приложения и использование PackageManager для просмотра установленных
  • Использование некоторого соглашения об именовании идентификаторов приложений (если вы будете разработчиком всех исходных приложений) и использование PackageManager, чтобы увидеть, какие установленные приложения придерживаются этого соглашения
  • Использование PackageManager и queryBroadcastReceivers(), чтобы увидеть, какие приложения реализуют приемник для некоторой известной строки действия
  • Использование PackageManager для перебора всех установленных приложений и просмотра, у которых есть определенная <meta-data> запись

Вы можете использовать SharedPreference и MultiSelectListPreference, или какой-либо подобный пользовательский интерфейс, чтобы позволить пользователю снимать флажки с определенных источников, которые он не хочет использовать в потребительском приложении.

Учитывая, что вы планируете источники, отправляющие широковещательные сообщения потребителям, вам также понадобится тот же базовый поток в исходных приложениях, чтобы увидеть:

  • Какие потребители установлены
  • С каким подмножеством этих потребителей пользователь хочет, чтобы исходное приложение работало с

Учитывая, что источники знают приемлемых потребителей, и наоборот, у вас есть различные варианты IPC.

Такое ощущение, что большая часть сообщений является источником -> потребителем. В этом случае разумно использовать источники, использующие трансляции. Имейте в виду, что это должны быть прямые трансляции:

  • Создайте Intent с желаемой строкой действия
  • Перебирать идентификаторы приложений соответствующих потребителей
    • Используйте setPackage() на копии Intent, чтобы связать ее с конкретным потребителем
    • Отправить "трансляцию" этой копии

Если я прав, что большая часть сообщений является источником -> потребителем, то целесообразно использовать широковещательную передачу от потребителя -> источника для «пробуждения» источников и получения кэшированных данных, если это упростит реализацию источников , Может случиться так, что обычная трансляция обновлений очень похожа на трансляцию «отправить кэшированные события».

Если между этими двумя широковещательными сообщениями будут существенные различия, такие, что не много кода будет совместно использоваться ни источником, ни потребителем, вы можете устранить асинхронный характер этого подхода и использовать ContentProvider, где В источнике есть поставщик, к которому может обратиться потребитель.


ИМХО, ваша проблема № 1 во всем этом - это конфиденциальность и безопасность. N-партийное общение, подобное этому, становится сложным, чтобы убедиться, что это не случайное N + 1-стороннее общение, где +1 - это часть шпионского ПО.

...