2010-04-27 126 views
3

我想創建一個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

回答

2

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

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

2

的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