I am currently working on an architecture to pass traffic messages (“stationary traffic on A9 between Como-Monte Olimpino and Brogeda”) between applications.
Sources of these messages are dedicated apps: one picks up messages via TMC, others might pull them from various services on the Internet.
Consumers are navigation apps in the typical use case, though other use cases are possible as well.
Multiple sources and consumers can be active at the same time.
When a source receives a new message, it sends a broadcast Intent with the message as an extra. Consumers register a BroadcastReceiver
to pick up these messages. (Payload for a message typically being a few hundred bytes.)
When a consumer starts up, I need to provide a way for it to poll every source for messages which the source might have in its cache (while bearing in mind that the consumer has no way of knowing which sources are available).
My initial idea was to do that via broadcasts as well: on startup, the consumer would send an implicit broadcast and each source would respond with a broadcast feed of its currently active messages.
Some sources might not be running at the time a consumer starts up, but may still have messages in their cache that need to be delivered to the consumer. As a context-registered BroadcastReceiver
would not be able to catch the poll broadcast if the app is not running, it would seem logical to declare te receiver in the manifest.
However, as of Android 8.0, manifest-declared receivers can no longer be used to receive implicit broadcasts. Furthermore, this comment suggests that even on earlier versions and with some flavors of Android, waking up an app via an implicit broadcast does not work as expected (and the device on which I am developing sems to have that restriction as well).
What would be a good mechanism to let a consumer retrieve all currently active messages from all sources, even if they are not running? Implementing a content provider looks a bit like overkill, so what other options are available?
Your consumer app will need to know:
What sources are installed
What subset of those sources the user wants the consumer app to use (as the user might not want all of them)
Possible ways to know what sources are installed include:
PackageManager
to see which are installedPackageManager
to see which installed apps adhere to that conventionPackageManager
and queryBroadcastReceivers()
to see which apps implement a receiver for some known action stringPackageManager
to iterate over all installed apps and see which have a certain <meta-data>
entryYou can use SharedPreference
and a MultiSelectListPreference
, or some similar UI, to allow the user to uncheck particular sources that they do not want the consumer app to use.
Given that you are planning on the sources sending broadcasts to consumers, you will also need the same basic flow in the source apps, to see:
Given that the sources know the eligible consumers, and vice versa, you have a variety of IPC options.
It feels like that most of the communications is source -> consumer. In that case, having sources use broadcasts is reasonable. Bear in mind that those will need to be explicit broadcasts:
Intent
with the desired action stringsetPackage()
on a copy of the Intent
to associate it with a particular consumerIf I am correct that most of the communications is source -> consumer, then using a broadcast from consumer -> source to "wake up" the sources and get cached data is reasonable, if this will simplify the implementation of the sources. It may be that a regular update broadcast is very similar to the "send the cached events" broadcast.
If there will be substantial differences between those two broadcasts, such that not a lot of code would be shared either on the source or the consumer, you might eliminate the asynchronous nature of that approach and use a ContentProvider
, where the source has a provider that the consumer can query.
IMHO, your #1 problem with all of this is privacy and security. N-party communications like this gets tricky to make sure that it is not accidentally N+1-party communications, where the +1 is a piece of spyware.