mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2025-12-08 14:11:07 +01:00
Add Support for XEP-80: User Location
SMACK-610
This commit is contained in:
parent
e126469003
commit
0d8f3185e5
8 changed files with 1021 additions and 0 deletions
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2016 Ishan Khanna
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.geoloc;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPConnectionRegistry;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smackx.geoloc.packet.GeoLocation;
|
||||
import org.jxmpp.jid.Jid;
|
||||
|
||||
public class GeoLocationManager extends Manager {
|
||||
|
||||
private static final Map<XMPPConnection, GeoLocationManager> INSTANCES = new WeakHashMap<XMPPConnection, GeoLocationManager>();
|
||||
|
||||
static {
|
||||
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
|
||||
public void connectionCreated(XMPPConnection connection) {
|
||||
getInstanceFor(connection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public GeoLocationManager(XMPPConnection connection) {
|
||||
super(connection);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a {@link GeoLocationManager} for the specified {@link XMPPConnection}, creating one if it doesn't
|
||||
* already exist.
|
||||
*
|
||||
* @param connection The connection the manager is attached to.
|
||||
* @return The new or existing manager.
|
||||
*/
|
||||
public synchronized static GeoLocationManager getInstanceFor(XMPPConnection connection) {
|
||||
GeoLocationManager geoLocationManager = INSTANCES.get(connection);
|
||||
if (geoLocationManager == null) {
|
||||
geoLocationManager = new GeoLocationManager(connection);
|
||||
INSTANCES.put(connection, geoLocationManager);
|
||||
}
|
||||
return geoLocationManager;
|
||||
}
|
||||
|
||||
public void sendGeoLocationToJid(GeoLocation geoLocation, Jid jid) throws InterruptedException,
|
||||
NotConnectedException {
|
||||
|
||||
final XMPPConnection connection = connection();
|
||||
|
||||
Message geoLocationMessage = new Message(jid);
|
||||
geoLocationMessage.addExtension(geoLocation);
|
||||
|
||||
connection.sendStanza(geoLocationMessage);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the message contains a GeoLocation extension.
|
||||
*
|
||||
* @param message the message to check if contains a GeoLocation extension or not
|
||||
* @return a boolean indicating whether the message is a GeoLocation message
|
||||
*/
|
||||
public static boolean isGeoLocationMessage(Message message) {
|
||||
return GeoLocation.from(message) != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,404 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2016 Ishan Khanna
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.geoloc.packet;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
/**
|
||||
* A GeoLocation Extension packet, which is used by the XMPP clients to exchange their respective geographic locations.
|
||||
*
|
||||
* @see <a href="http://www.xmpp.org/extensions/xep-0080.html">XEP-0080</a>
|
||||
* @author Ishan Khanna
|
||||
*/
|
||||
public class GeoLocation implements Serializable, ExtensionElement {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
public static final String NAMESPACE = "http://jabber.org/protocol/geoloc";
|
||||
public static final String ELEMENT = "geoloc";
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(GeoLocation.class.getName());
|
||||
|
||||
private final Double accuracy;
|
||||
private final Double alt;
|
||||
private final String area;
|
||||
private final Double bearing;
|
||||
private final String building;
|
||||
private final String country;
|
||||
private final String countryCode;
|
||||
private final String datum;
|
||||
private final String description;
|
||||
private final Double error;
|
||||
private final String floor;
|
||||
private final Double lat;
|
||||
private final String locality;
|
||||
private final Double lon;
|
||||
private final String postalcode;
|
||||
private final String region;
|
||||
private final String room;
|
||||
private final Double speed;
|
||||
private final String street;
|
||||
private final String text;
|
||||
private final Date timestamp;
|
||||
private final String tzo;
|
||||
private final URI uri;
|
||||
|
||||
private GeoLocation(Double accuracy, Double alt, String area, Double bearing, String building, String country,
|
||||
String countryCode, String datum, String description, Double error, String floor, Double lat,
|
||||
String locality, Double lon, String postalcode, String region, String room, Double speed,
|
||||
String street, String text, Date timestamp, String tzo, URI uri) {
|
||||
this.accuracy = accuracy;
|
||||
this.alt = alt;
|
||||
this.area = area;
|
||||
this.bearing = bearing;
|
||||
this.building = building;
|
||||
this.country = country;
|
||||
this.countryCode = countryCode;
|
||||
|
||||
// If datum is not included, receiver MUST assume WGS84; receivers MUST implement WGS84; senders MAY use another
|
||||
// datum, but it is not recommended.
|
||||
|
||||
if (StringUtils.isNullOrEmpty(datum)) {
|
||||
datum = "WGS84";
|
||||
}
|
||||
|
||||
this.datum = datum;
|
||||
this.description = description;
|
||||
|
||||
// error element is deprecated in favor of accuracy
|
||||
if (accuracy != null) {
|
||||
error = null;
|
||||
LOGGER.log(Level.WARNING,
|
||||
"Error and accurracy set. Ignoring error as it is deprecated in favor of accuracy");
|
||||
}
|
||||
|
||||
this.error = error;
|
||||
this.floor = floor;
|
||||
this.lat = lat;
|
||||
this.locality = locality;
|
||||
this.lon = lon;
|
||||
this.postalcode = postalcode;
|
||||
this.region = region;
|
||||
this.room = room;
|
||||
this.speed = speed;
|
||||
this.street = street;
|
||||
this.text = text;
|
||||
this.timestamp = timestamp;
|
||||
this.tzo = tzo;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public Double getAccuracy() {
|
||||
return accuracy;
|
||||
}
|
||||
|
||||
public Double getAlt() {
|
||||
return alt;
|
||||
}
|
||||
|
||||
public String getArea() {
|
||||
return area;
|
||||
}
|
||||
|
||||
public Double getBearing() {
|
||||
return bearing;
|
||||
}
|
||||
|
||||
public String getBuilding() {
|
||||
return building;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public String getCountryCode() {
|
||||
return countryCode;
|
||||
}
|
||||
|
||||
public String getDatum() {
|
||||
return datum;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Double getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public String getFloor() {
|
||||
return floor;
|
||||
}
|
||||
|
||||
public Double getLat() {
|
||||
return lat;
|
||||
}
|
||||
|
||||
public String getLocality() {
|
||||
return locality;
|
||||
}
|
||||
|
||||
public Double getLon() {
|
||||
return lon;
|
||||
}
|
||||
|
||||
public String getPostalcode() {
|
||||
return postalcode;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public String getRoom() {
|
||||
return room;
|
||||
}
|
||||
|
||||
public Double getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public Date getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public String getTzo() {
|
||||
return tzo;
|
||||
}
|
||||
|
||||
public URI getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getElementName() {
|
||||
return ELEMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence toXML() {
|
||||
XmlStringBuilder xml = new XmlStringBuilder(this);
|
||||
xml.rightAngleBracket();
|
||||
xml.optElement("accuracy", String.valueOf(accuracy));
|
||||
xml.optElement("alt", String.valueOf(alt));
|
||||
xml.optElement("area", area);
|
||||
xml.optElement("bearing", String.valueOf(bearing));
|
||||
xml.optElement("building", building);
|
||||
xml.optElement("country", country);
|
||||
xml.optElement("countrycode", countryCode);
|
||||
xml.optElement("datum", datum);
|
||||
xml.optElement("description", description);
|
||||
xml.optElement("error", String.valueOf(error));
|
||||
xml.optElement("floor", floor);
|
||||
xml.optElement("lat", String.valueOf(lat));
|
||||
xml.optElement("locality", locality);
|
||||
xml.optElement("lon", String.valueOf(lon));
|
||||
xml.optElement("postalcode", postalcode);
|
||||
xml.optElement("region", region);
|
||||
xml.optElement("room", room);
|
||||
xml.optElement("speed", String.valueOf(speed));
|
||||
xml.optElement("street", street);
|
||||
xml.optElement("text", text);
|
||||
xml.optElement("timestamp", timestamp);
|
||||
xml.optElement("tzo", tzo);
|
||||
xml.optElement("uri", uri);
|
||||
xml.closeElement(this);
|
||||
return xml;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return NAMESPACE;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new GeoLocation.Builder();
|
||||
}
|
||||
|
||||
public static GeoLocation from(Message message) {
|
||||
return message.getExtension(ELEMENT, NAMESPACE);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private Double accuracy;
|
||||
private Double alt;
|
||||
private String area;
|
||||
private Double bearing;
|
||||
private String building;
|
||||
private String country;
|
||||
private String countryCode;
|
||||
private String datum;
|
||||
private String description;
|
||||
private Double error;
|
||||
private String floor;
|
||||
private Double lat;
|
||||
private String locality;
|
||||
private Double lon;
|
||||
private String postalcode;
|
||||
private String region;
|
||||
private String room;
|
||||
private Double speed;
|
||||
private String street;
|
||||
private String text;
|
||||
private Date timestamp;
|
||||
private String tzo;
|
||||
private URI uri;
|
||||
|
||||
public Builder setAccuracy(Double accuracy) {
|
||||
this.accuracy = accuracy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAlt(Double alt) {
|
||||
this.alt = alt;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setArea(String area) {
|
||||
this.area = area;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setBearing(Double bearing) {
|
||||
this.bearing = bearing;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setBuilding(String building) {
|
||||
this.building = building;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCountry(String country) {
|
||||
this.country = country;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setCountryCode(String countryCode) {
|
||||
this.countryCode = countryCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDatum(String datum) {
|
||||
this.datum = datum;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setDescription(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setError(Double error) {
|
||||
this.error = error;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setFloor(String floor) {
|
||||
this.floor = floor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setLat(Double lat) {
|
||||
this.lat = lat;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setLocality(String locality) {
|
||||
this.locality = locality;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setLon(Double lon) {
|
||||
this.lon = lon;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPostalcode(String postalcode) {
|
||||
this.postalcode = postalcode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRegion(String region) {
|
||||
this.region = region;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRoom(String room) {
|
||||
this.room = room;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSpeed(Double speed) {
|
||||
this.speed = speed;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setStreet(String street) {
|
||||
this.street = street;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setText(String text) {
|
||||
this.text = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTimestamp(Date timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTzo(String tzo) {
|
||||
this.tzo = tzo;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUri(URI uri) {
|
||||
this.uri = uri;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GeoLocation build() {
|
||||
|
||||
return new GeoLocation(accuracy, alt, area, bearing, building, country, countryCode, datum, description,
|
||||
error, floor, lat, locality, lon, postalcode, region, room, speed, street, text, timestamp,
|
||||
tzo, uri);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2015-2016 Ishan Khanna
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.geoloc.provider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import org.jivesoftware.smack.provider.ExtensionElementProvider;
|
||||
import org.jivesoftware.smack.util.ParserUtils;
|
||||
import org.jivesoftware.smackx.geoloc.packet.GeoLocation;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
public class GeoLocationProvider extends ExtensionElementProvider<GeoLocation> {
|
||||
|
||||
@Override
|
||||
public GeoLocation parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException,
|
||||
ParseException, URISyntaxException {
|
||||
|
||||
GeoLocation.Builder builder = GeoLocation.builder();
|
||||
|
||||
outerloop: while (true) {
|
||||
int event = parser.next();
|
||||
switch (event) {
|
||||
case XmlPullParser.START_TAG:
|
||||
String name = parser.getName();
|
||||
switch (name) {
|
||||
case "accuracy":
|
||||
builder.setAccuracy(ParserUtils.getDoubleFromNextText(parser));
|
||||
break;
|
||||
case "alt":
|
||||
builder.setAlt(ParserUtils.getDoubleFromNextText(parser));
|
||||
break;
|
||||
case "area":
|
||||
builder.setArea(parser.nextText());
|
||||
break;
|
||||
case "bearing":
|
||||
builder.setBearing(ParserUtils.getDoubleFromNextText(parser));
|
||||
break;
|
||||
case "building":
|
||||
builder.setBuilding(parser.nextText());
|
||||
break;
|
||||
case "country":
|
||||
builder.setCountry(parser.nextText());
|
||||
break;
|
||||
case "countrycode":
|
||||
builder.setCountryCode(parser.nextText());
|
||||
break;
|
||||
case "datum":
|
||||
builder.setDatum(parser.nextText());
|
||||
break;
|
||||
case "description":
|
||||
builder.setDescription(parser.nextText());
|
||||
break;
|
||||
case "error":
|
||||
builder.setError(ParserUtils.getDoubleFromNextText(parser));
|
||||
break;
|
||||
case "floor":
|
||||
builder.setFloor(parser.nextText());
|
||||
break;
|
||||
case "lat":
|
||||
builder.setLat(ParserUtils.getDoubleFromNextText(parser));
|
||||
break;
|
||||
case "locality":
|
||||
builder.setLocality(parser.nextText());
|
||||
break;
|
||||
case "lon":
|
||||
builder.setLon(ParserUtils.getDoubleFromNextText(parser));
|
||||
break;
|
||||
case "postalcode":
|
||||
builder.setPostalcode(parser.nextText());
|
||||
break;
|
||||
case "region":
|
||||
builder.setRegion(parser.nextText());
|
||||
break;
|
||||
case "room":
|
||||
builder.setRoom(parser.nextText());
|
||||
break;
|
||||
case "speed":
|
||||
builder.setSpeed(ParserUtils.getDoubleFromNextText(parser));
|
||||
break;
|
||||
case "street":
|
||||
builder.setStreet(parser.nextText());
|
||||
break;
|
||||
case "text":
|
||||
builder.setText(parser.nextText());
|
||||
break;
|
||||
case "timestamp":
|
||||
builder.setTimestamp(ParserUtils.getDateFromNextText(parser));
|
||||
break;
|
||||
case "tzo":
|
||||
builder.setTzo(parser.nextText());
|
||||
break;
|
||||
case "uri":
|
||||
builder.setUri(ParserUtils.getUriFromNextText(parser));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case XmlPullParser.END_TAG:
|
||||
if (parser.getDepth() == initialDepth) {
|
||||
break outerloop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -493,4 +493,11 @@
|
|||
<namespace>http://jabber.org/protocol/rsm</namespace>
|
||||
<className>org.jivesoftware.smackx.rsm.provider.RSMSetProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- XEP-0080: User Location -->
|
||||
<extensionProvider>
|
||||
<elementName>geoloc</elementName>
|
||||
<namespace>http://jabber.org/protocol/geoloc</namespace>
|
||||
<className>org.jivesoftware.smackx.geoloc.provider.GeoLocationProvider</className>
|
||||
</extensionProvider>
|
||||
</smackProviders>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue