我想为Android创建一个应用程序,使我能够获得用户的地理位置。这必须作为客户端 - 服务器应用程序,而对于服务器端我使用的是OpenFire。 为了获得用户的位置,我将不得不使用XEP-0080,对吗?还有SmackAPI吗? 我对XMPP和Smack完全不熟悉,所以如果有人能给我一些指示或示例或任何类型的文档,我将非常感激。
提前感谢您的帮助。
答案 0 :(得分:3)
我目前正在处理的Android项目需要使用aSmack& amp ;;定期将用户的位置发布给他们的XMPP名单朋友。 XEP-0080。
结果比我想象的要复杂,所以我在这里记录了我的解决方案:http://www.dbotha.com/2014/11/02/xep-0080-user-location-on-android-using-pep-with-smack/
为了完整起见,我将在此处介绍重要部分。为了简洁起见,我将介绍的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
}
}
};
答案 1 :(得分:2)
我相信这与你想要完成的事情很接近。