I am working on sharing road traffic information between Android applications, and wondering what is a good transport mechanism.
There are two classes of applications: Publishers post traffic messages they have obtained from various sources (say, an Internet service or a TMC receiver device) and converted to a standard format. Subscribers listen for messages and work with them (e.g. displaying them in a list or guiding drivers around congestions). The system is intended to be decentral: there will be multiple publishers, multiple subscribers and users can mix and match them as they like.
Messages are identified by a unique ID, which remains stable over their entire life cycle. They have an expiration time, after which they are considered invalid. Until then, they can be updated at any time. An update can also cancel the message (replacing it with a tombstone until it expires), or extend its expiration time.
Subscribers get new messages as they arrive. (Filtering may happen in a later phase.) They also need a way to retrieve all currently cached messages from all publishers.
A message is around 1 kByte in size. A publisher can easily hold several hundred active messages at any given time.
In terms of security, the messages are generally public information. The only sensitive information is geodata, as it may allow for conclusions on the location of the device or where its user intends to travel. The precision of such data is low, anywhere from city to country level. Therefore I don’t see a need to hide this information from any app, as long as it has location permission.
Now I am wondering what a good transport mechanism would be:
Option 1: Broadcast intents
Initially I have been working with broadcast intents: whenever a publisher has any new messages, it sends an implicit broadcast with the messages in the extras. Subscribers can register a broadcast receiver at run time to receive messages. They also have the option to send a poll broadcast (an explicit broadcast, with the corresponding broadcast receiver declared in the publisher’s Manifest). Publishers will then respond with a feed of all currently cached messages. To address security concerns, any app sending a broadcast with geodata requires that the receiver hold one of the location permissions.
There is an issue with large feeds, as the Android request broker supports a maximum of 1 MByte for all concurrent transactions (so the maximum amount of data in a feed can be even less if things are busy). I am currently working around that by breaking down feeds into chunks of 100 messages or less.
An advantage of this system is that all central infrastructure is provided by the OS. Having one publisher and one subscriber app installed is sufficient.
Option 2: Content Providers
Some people have pointed out that broadcast intents are not the best way to go, and have suggested I implement a content provider, a territory into which I have not ventured so far. Looking at the documentation, it is not clear if there is a way to have multiple backends (each backend being a separate app) implement functionally identical content providers and advertise them as such. Since content providers support both read and write operations, I could set up one central component as the content provider, and have both publishers and subscribers connect to it. However, that would require providing a central component in order to work, which I would rather avoid.
Questions:
Is there a way to implement the above multi-publisher, multi-subscriber model with content providers, and without having to supply a central component not already provided by the OS?
Specifically, can a single content provider have multiple backends? Alternatively, can multiple, functionally identical content providers advertise themselves as a group?
How would I implement the above using content providers?
What are advantages and drawbacks of broadcast intents or content providers that I may have missed?
Is there a way to implement the above multi-publisher, multi-subscriber model with content providers
Keep the broadcasts. Replace the payload.
Publishers would implement a ContentProvider that serve up the current roster of messages. You can think of a ContentProvider as being a quirky sort of REST-style Web service, where Uri values get mapped to responses by the provider.
Publishers would then send broadcasts as they are today, but perhaps with only two extras:
One that identifies the protocol version that the broadcast is using, since you have lots of independently-updated parties. Rceivers need to know how to interpret the broadcast, as you might change the rules over time.
One that contains a Uri pointing to the publisher's ContentProvider.
If there are other extras that you are using today that you know will remain small, and you want to still put those in the broadcast, that's cool. Just keep the indeterminate-sized ones out of the broadcast.
Receivers would then:
Look at the protocol version extra and branch to the code to handle that version (today, just one branch, but, hey, future-proofing)
Use that Uri and a ContentResolver to get the messages (and other stuff if needed) from the publisher
You might consider developing this communications infrastructure as an SDK. Even if you are the only one developing apps, you'll want to avoid duplicating all this logic across the apps. And, if third parties will develop apps, you're better off giving them an SDK to work from, rather than forcing them "roll their own".
I'm an Android newbie. I'm trying to send and receive messages between process. One thing which I'm aware of is communicating via binder calls by implementing a Service. The other message transferring mechanism which I've seen so far is
Broadcast (Not reliable though) - which can be missed
Event bus (Not sure IPC is possible with greenrobot's event bus - this SO link says it's not possible and suggested for alternatives
Registering a ContentObserver so that I can update my content at one process and the other process can get notified of the content change (Not sure this is reliable)
All I mean by reliable is that it can be missed at rare cases. Is there any alternative reliable and ordered (delivered in the same order in which it's published) - message exchanging mechanism between processes in Android?
EDIT: Though there are many ways discussed in this SO Link I would like to maintain the message order and guaranteed delivery of message.
I am developing a simple library project which have a broadcast for Battery stats.
I implemented this simple library project in 3 of the my projects. As the result of this, suppose at 30% battery I need to send something to the server, I received the broadcast and send data to server. What is happening is as I have implemented the same broadcast in 3 of my applications, I receives 3 same files at the server.
I need to restrict this, such that only one time the file will be send to the server, that means if from 3 projects if any one received the broadcast other two will not receive it or don't perform the broadcast.
As there are 3 separate broadcast senders so i think the only way to stop this behaviour is make a shared object that the first sender (or receiver) will create with some sort of timestamp and the other will check and if the object is present - stop sending anything to server.
That can be achieved with:
world readable/writable preference (i think it marked as deprecated since api 17..)
or
some sort of file on sdcard
I have to develop an application where i have to continuously collect the GPS, accelerometer data [esp. when user is in motion i.e traveling, else it can be relaxed). Also I have to communicate with web server and handle the response from the sever. So for this(handling response ) part application should continuously poll.
Based on response from server I have show UI to the user.
I am not very clear about the design.
Do I have to create activity from where I start service. Should service be ran as a separate thread(this always runs in background).
I am planning to create two services. One service to continuously collect GPS data.
Other service for communicating with the web server[start timer/alarm manager] for polling.
ALso can these two services communicate with each other.
Also after processing the response frm server the service should be able to start user interface to show some form. I am not clear how to handle this.
Also is acquiring wakelock required if I have to collect GPS data continuously.
Please clarify.
Thanks
You can use an AlarmManager for polling. You just need to set the interval. You will notice that most components Application, Service, Activity all are Contexts. So they all can get Application Context. The way to think about communication is that the android message/event is essentially the Intent. So you define your custom Intents. You just need to give them a custom name for the action. Then you use Intent filters. You can do point to point messaging by doing startService, startActivity or you can broadcast the intent. I would recommend that you communicate via broadcasted intents. Message routing is handled using Intent filters. Starting form etc would just be a startActivity(Intent) and the Intent itself could contain using intent.getExtras(). Just so long as you can put it in the Bundle you can pass it and display. So to answer your question, just use Intents for everything. Use broadcasting and filtering for communication and Intents again to start your activity for display.
The May 10th Google I/O had an afternoon session called Android Pro Tips. The first section covered several different approaches to making your app more continuously location aware.
So I'm working on a service that will handle requests to send data to a socket.
I've done socket programming in a service before, but only within the same application. I'd like this to just sit and do nothing until any application wants to give it data to send. That's all well and good.
I have register an intent filter and the usual stuff and can process the data. But I want to process the data coming from different activities in different threads (subsequent calls from the same application will be computed on the same thread).
Is there a way to get the calling package or app or whatever? I'd prefer not to require passing in an identifier as an extra to prevent spoofing. (It's not a serious security concern, it's just each application needs its data processed in the order that it's received.)
I had run to the same issue in the past. I couldn't find a way to know how send the intent and I ended up adding an extra.
If you don't want to use an extra perhaps you might want to set an Action but it's almost the same thing.