XEP-0080: User Location on Android using PEP with aSmack
Deon Botha• Nov 2, 2014A project I’m currently working on requires periodically publishing a user’s location to their XMPP roster friends on Android.
My initial feeling given the relative simplicity of the problem and readily available XEP-0080: User Location specification was that I’d have something up and running in a matter of hours. How wrong I was. I ended up spending several days in a state of perpetual frustration just trying to get PEP to play nicely with aSmack.
Given the lack of documented Android examples surrounding PEP and aSmack at the time of writing, arriving upon solution was more luck than anything. Frustratingly it came down to some careful (and not entirely intuitive) ordering of a few key statements.
So that others might not have to go through the same trouble I thought I’d document my approach now that I have something working.
I made the decision to loosely follow the XEP-0080 specification as I’m relatively new to XMPP and figured it would lead me down a “best practice” path. It also seemed to cover my requirements nicely:
This specification defines an XMPP protocol extension for communicating information about the current geographical or physical location of an entity.
As aSmack does not support XEP-0080 out the box we’ll need to write:
- A custom
PEPItem
(effectively aPacketExtension
) to hold the user location data - A custom
PEPEvent
to store thePEPItem
- A custom
PacketExtensionProvider
to parse the custom user locationPEPEvent
’s from incoming packets - Some boilerplate to tie the above together
- A function to publish a user’s location to the XMPP server
In the interest of brevity the only XML child elements from the specification that I’ll cover in this post are those relating to latitude and longitude. Adding support for the remainder of the specification should be a trivial exercise once we’ve got the foundations in place.
We’re going to be making use of the Smack provider architecture to handle parsing parsing of our custom user location packet extensions. I’ll assume that you’re familiar with this architecture and won’t be covering it any any detail.
A PEPItem to store user location
To start we need to define a PEPItem
to hold the user location data that we’ll publish and receive. A PEPItem
is
responsible for transforming the location data into a representative XML element.
A PEPEvent to hold the PEPItem
Next we’ll need a custom PEPEvent
class to hold our UserLocation
item. This one’s mostly boilerplate but is required to play nice with the PEPManager
subsystem.
A PacketExtensionProvider to parse incoming friend locations
Whenever a friend on our roster publishes their location it will find it’s way to us nested as an extension deep within an XMPP packet.
Out of the box aSmack will not know what to do with our custom extension that it finds within these packets and will effectively ignore it.
To have them parsed and reported back in a sensible form we need to create and register a custom PacketExtensionProvider
.
Tying it all together
And now for the magic that eluded me for so long… and as I found out the hard way – the ordering of the code snippets in this section is crucial.
In the above code we create a connection and indicate to the ServiceDiscoveryManager
that we support XEP-0080.
The +notify
suffix indicates our additional interest in receiving notifications related to this protocol too, rather than just publishing them.
Reporting of entity capabilities is also enabled. This means publishing and subscribing XEP-0080 capabilities will be reported within presence updates sent by the Android client.
In the code snippet below we register our custom UserLocationProvider
with the ProviderManager
as per the
Smack provider architecture.
aSmack will now know what to do when it finds a user location extension nested within an XMPP packet i.e. a
UserLocationEvent
will ultimately get parsed out of the packet which will then find its way to the PEPManager
and
finally reported to our own listener.
And after all that setup we provide a listener to be notified when a friend publishes a UserLocationEvent
Publishing a users location with PEP
Finally publishing a user’s location is pretty straightforward in comparison to receiving them and can be accomplished as follows