我想为 Android 创建一个应用程序,使我能够获取用户的地理位置。这必须作为客户端-服务器应用程序制作,而对于服务器端,我使用的是 OpenFire。为了获取用户的位置,我必须使用 XEP-0080,对吗?还有 SmackAPI 吗?我对 XMPP 和 Smack 完全陌生,所以如果有人能给我一些指示或示例或任何类型的文档,我将非常感激。
提前感谢您的帮助。
我目前正在处理的一个 Android 项目需要使用 aSmack 和 XEP-0080 定期将用户的位置发布给他们的 XMPP 名册朋友。
结果比我想要的更棘手,所以我在这里记录了我的解决方案:http ://www.dbotha.com/2014/11/02/xep-0080-user-location-on-android-using-pep-with-咂嘴/
为了完整起见,我将在这里介绍重要部分。为简洁起见,我将介绍的 XEP-0080 规范中的唯一 XML 子元素是与纬度和经度相关的那些。
用于保存用户位置并将其转换为适当 XML 的 PEPItem:
public class UserLocation extends PEPItem {
public static final String NODE =
"http://jabber.org/protocol/geoloc";
public final double latitude, longitude;
public UserLocation(double latitude, double longitude) {
this(StringUtils.randomString(16), latitude, longitude);
}
public UserLocation(double latitude, double longitude,
String id) {
super(id);
this.latitude = latitude;
this.longitude = longitude;
}
@Override
java.lang.String getNode() {
return NODE;
}
// return an XML element approximately inline
// with the XEP-0080 spec
@Override
java.lang.String getItemDetailsXML() {
return String.format(
"<geoloc xmlns='%s'><lat>%f</lat>" +
"<lon>%f</lon></geoloc>",
NODE, latitude, longitude);
}
}
用于保存 UserLocation PEPItem 的大部分样板 PEPEvent:
public class UserLocationEvent extends PEPEvent {
private final UserLocation location;
public UserLocationEvent(UserLocation location) {
this.location = location;
}
public UserLocation getLocation() {
return location;
}
@Override
public String getNamespace() {
return "http://jabber.org/protocol/pubsub#event";
}
@Override
public String toXML() {
return String.format("<event xmlns=" +
"'http://jabber.org/protocol/pubsub#event' >" +
"<items node='%s' >%s</items></event>",
UserLocation.NODE, location.toXML());
}
}
一个自定义的 PacketExtensionProvider,用于从存在的传入数据包中解析出 UserLocationEvent。
public class UserLocationProvider
implements PacketExtensionProvider {
// This method will get called whenever aSmack discovers a
// packet extension containing a publish element with the
// attribute node='http://jabber.org/protocol/geoloc'
@Override
public PacketExtension parseExtension(XmlPullParser parser)
throws Exception {
boolean stop = false;
String id = null;
double latitude = 0;
double longitude = 0;
String openTag = null;
while (!stop) {
int eventType = parser.next();
switch (eventType) {
case XmlPullParser.START_TAG:
openTag = parser.getName();
if ("item".equals(openTag)) {
id = parser.getAttributeValue("", "id");
}
break;
case XmlPullParser.TEXT:
if ("lat".equals(openTag)) {
try {
latitude = Double.parseDouble(
parser.getText());
} catch (NumberFormatException ex) {
/* ignore */
}
} else if ("lon".equals(openTag)) {
try {
longitude = Double.parseDouble(
parser.getText());
} catch (NumberFormatException ex) {
/* ignore */
}
}
break;
case XmlPullParser.END_TAG:
// Stop parsing when we hit </item>
stop = "item".equals(parser.getName());
openTag = null;
break;
}
}
return new UserLocationEvent(
new UserLocation(id, latitude, longitude));
}
}
现在把它们绑在一起:
XMPPTCPConnection connection = new XMPPTCPConnection();
ServiceDiscoveryManager sdm = ServiceDiscoveryManager
.getInstanceFor(connection);
sdm.addFeature("http://jabber.org/protocol/geoloc");
sdm.addFeature("http://jabber.org/protocol/geoloc+notify");
EntityCapsManager capsManager = EntityCapsManager
.getInstanceFor(connection);
capsManager.enableEntityCaps();
PEPProvider pepProvider = new PEPProvider();
pepProvider.registerPEPParserExtension(
"http://jabber.org/protocol/geoloc",
new UserLocationProvider());
ProviderManager.addExtensionProvider("event",
"http://jabber.org/protocol/pubsub#event", pepProvider);
PEPManager pepManager = new PEPManager(connection);
pepManager.addPEPListener(PEP_LISTENER);
connection.connect();
connection.login(username, password);
最后是传入 LocationEvent 的侦听器:
PEPListener PEP_LISTENER = new PEPListener() {
@Override
public void eventReceived(String from, PEPEvent event) {
if (event instanceof UserLocationEvent) {
// do something interesting
}
}
};
我相信这与您要完成的工作很接近。