使用XMPP用户位置

问题描述:

我想创建一个Android应用程序,使我能够获取用户的地理位置。这必须作为一个客户端服务器应用程序,并为服务器端我使用OpenFire。 为了获得用户的位置,我将不得不使用XEP-0080,对吧?还有SmackAPI? 我完全不熟悉XMPP和Smack,所以如果任何人能够得到我几个指针或者可能的例子或任何类型的文档,我会非常感激。使用XMPP用户位置

在此先感谢您的帮助。

+0

你是不是也使用IM的Openfire的服务器?或者你只是使用它进行地理定位? – hannson 2010-04-27 22:08:11

+0

我只是为了地理位置而使用它。 – Robert 2010-04-27 22:15:59

我相信这与您正在努力完成的工作很接近。

XEP-0080 User Location in Smack Library

+0

thnx这个链接,我已经看到它并计划使用它,但是你有没有在Java程序中使用XMPP扩展的完整示例,因为就像我所说的,我对这个领域完全陌生。 thnx再次寻求帮助 – Robert 2010-04-27 22:37:45

+0

我只需要一些关于首先做什么的线索。就像我说的,我是这个领域的一个完全的noob。我是否必须首先配置我的Openfire服务器(创建新的插件),或者默认支持它,还是只需开发Android应用程序即可完成它的工作。这是为了我的论文,所以它很重要。在此先感谢 – Robert 2010-04-27 23:53:53

+0

Openfire是否支持XEP-0800 – 2010-04-28 13:58:21

的Android项目我目前工作的要求定期发布用户的位置使用aSmack & XEP-0080的XMPP名册的朋友。

原来棘手的比我所希望的,所以我记录我的解决方案在这里:http://www.dbotha.com/2014/11/02/xep-0080-user-location-on-android-using-pep-with-smack/

为了完整,我会在这里介绍的重要组成部分。为了简洁起见,我将介绍的XEP-0080规范中唯一的XML子元素是与纬度和经度有关的。

一个PEPItem保存用户位置并将其转换为相应的XML:

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); 
    } 
} 

,一个最样板PEPEvent保持用户位置PEPItem:

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 
     } 
    } 
}; 
+0

如果您愿意向上游发送代码,那就太棒了:https://github.com/igniterealtime/Smack/wiki/Smack-Jobs#implement-xep-0080-user-location和https:// igniterealtime。组织/问题/浏览/ SMACK-610 – Flow 2014-11-03 17:44:38

+0

将尝试它,谢谢 – tomm 2015-03-15 19:33:42

+0

扩展PEPItem有一个小问题。它的抽象方法没有访问修饰符,但是你需要使用公共修饰符来覆盖它们(因为没有访问修饰符,它们只对其包 - 导入的库JAR可见,而当你使用自己的包时 - 将PEPItem扩展到你自己的包中时,它们将不可访问)。我通过在PEPItem类中添加公共修饰符来重建aSmack库jar来解决它。 – tomm 2015-03-16 14:21:38