AnsweredAssumed Answered

Using SMACK API to do initial load of Buddy List

Question asked by James Beshada on Jan 29, 2015

I have been struggling to get user presence information using the SMACK API. I am able to receive presence changes via the RosterListener, but iterating thru the roster entries after my application starts (and checking presence information) doesn't yield accurate results. For example, if a user was on-line prior to my application starting, using the roster to access the presence information shows the user to be off-line when they are in fact on-line (using Spark client). In addition, I do not receive any Roster Listener updates for users that were already on-line (prior to my application starting up) unless they change their presence information. Therefore, I don't know how to do the initial load of my buddy list.

 

I have searched IgniteRealtime and StackOverflow for the last two days. It seems that I am not alone in seeking an answer to this issue.

 

Here's my code for anyone that wants to take a look:

 

import java.io.File;

import java.io.IOException;

import java.util.Collection;

import java.util.Date;

 

import org.apache.log4j.Logger;

import org.apache.log4j.PropertyConfigurator;

import org.jivesoftware.smack.ConnectionConfiguration;

import org.jivesoftware.smack.PacketListener;

import org.jivesoftware.smack.Roster;

import org.jivesoftware.smack.RosterEntry;

import org.jivesoftware.smack.RosterListener;

import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;

import org.jivesoftware.smack.SmackException.NotConnectedException;

import org.jivesoftware.smack.filter.MessageTypeFilter;

import org.jivesoftware.smack.filter.PacketFilter;

import org.jivesoftware.smack.packet.Message;

import org.jivesoftware.smack.packet.Packet;

import org.jivesoftware.smack.packet.Presence;

import org.jivesoftware.smack.tcp.XMPPTCPConnection;

import org.jivesoftware.smackx.delay.packet.DelayInformation;

import org.jivesoftware.smackx.filetransfer.FileTransfer.Status;

import org.jivesoftware.smackx.filetransfer.FileTransferListener;

import org.jivesoftware.smackx.filetransfer.FileTransferManager;

import org.jivesoftware.smackx.filetransfer.FileTransferRequest;

import org.jivesoftware.smackx.filetransfer.IncomingFileTransfer;

import org.jivesoftware.smackx.receipts.DeliveryReceiptManager;

 

 

public class XmppReceiver extends Thread {

  private XMPPTCPConnection connection;

  FileTransferManager manager;

  private static final String USERID = "valariebeshada";

  private static final String PASSWORD = "becky11";

  private static final String RESOURCE = "CAD";

  private Logger log;

 

  public static void main(String[] args) {

       new XmppReceiver();

  }

 

  public XmppReceiver() {

 

       // Set up logging through log4j.

       log = Logger.getLogger(XmppReceiver.class);

       PropertyConfigurator.configure("log4j.properties");

 

       this.start();

  }

 

  public void run() {

       this.connectionSetup();

 

       this.admitFriendsRequest();

       this.setPresence();

       this.setPresenceSubscription("jimbeshada@jamess-macbook-air.local", true);

       this.startRosterListener();

       this.showRoster();

       this.startFileTransferManager();

       this.listenForChatMessages();

       this.listenForNormalMessages();

 

       this.pause(30000);

 

       log.info("XmppReceiver has stopped");

  }

 

 

  public boolean connectionSetup() {

 

       try {

          ConnectionConfiguration config = new ConnectionConfiguration("localhost", 5222);

          config.setSecurityMode(SecurityMode.disabled);

          connection = new XMPPTCPConnection(config);

          DeliveryReceiptManager.getInstanceFor(connection).enableAutoReceipts();

          connection.connect();

          log.info("Connected");

       } catch (Exception e) {

            log.error("Error connecting: " + e.toString());

            return false;

       }

 

       try {

            connection.login(USERID, PASSWORD, RESOURCE);

            return true;

       } catch (Exception e) {

            log.error("Login error: " + e.toString());

            return false;

       }

  }

 

  private boolean setPresence() {

 

       Presence presence = new Presence(Presence.Type.available);

       presence.setStatus("Ready to chat");

       presence.setPriority(42);

       presence.setMode(Presence.Mode.available);

 

       try {

            connection.sendPacket(presence);

            log.info("Presence set");

            return true;

       } catch (NotConnectedException e) {

            log.error("Error setting Presence: " + e.toString());

            return false;

       }

 

  }

 

  private boolean setPresenceSubscription(String user, boolean subscriptionEnabled) {

       Presence presence;

       if (subscriptionEnabled) {

            presence = new Presence(Presence.Type.subscribe);

            log.info("Subscribed to " + user);

       } else {

            presence = new Presence(Presence.Type.unsubscribe);

            log.info("Unsubscribed from " + user);

       }

 

       presence.setFrom(USERID);

       presence.setTo(user);

 

       try {

            connection.sendPacket(presence);

            return true;

       } catch (NotConnectedException e) {

            log.error("Error subscribing to user presence: " + e.toString());

            return false;

       }

 

  }

 

  private void startRosterListener() {

 

      connection.getRoster().addRosterListener(new RosterListener() {

      

          public void presenceChanged(Presence presence) {

 

               log.info("Presence change detected for:" + presence.getFrom()

                    + "\tType: " + presence.getType()

                    + "\tStatus: " + presence.getStatus());

          }

 

          public void entriesUpdated(Collection<String> presence) {

              log.info("entriesUpdated");

 

          }

 

          public void entriesDeleted(Collection<String> presence) {

              log.info("entriesDeleted");

 

          }

 

          public void entriesAdded(Collection<String> presence) {

              log.info("entriesAdded");

          }

      });

    

      log.info("Listening to roster changes");

  }

 

 

 

  public void showRoster() {

 

  Roster roster = connection.getRoster();

        Collection<RosterEntry> entries = roster.getEntries();

       

        for (RosterEntry entry : entries) {

 

        log.info("RosterEntry " + entry);

            log.info("User: [" + entry.getUser() + "]");

            log.info("Name: " + entry.getName());

             

            Presence presence = roster.getPresence(entry.getUser());

            if (presence == null) {

            log.info("User is off-line");

            } else {

            log.info("User is on-line");

            }

 

            log.info("Present Type: " + presence.getType());

           log.info("Present Status: " + presence.getStatus());

 

        }

  }

 

  public void listenForChatMessages() {

 

      if (connection != null) {

        

          PacketFilter filter = new MessageTypeFilter(Message.Type.chat);

          connection.addPacketListener(new PacketListener() {

        

              @Override

              public void processPacket(Packet packet) {

                  Message message = (Message) packet;

                  if (message.getBody() != null) {

                      log.info("Received chat message [" + message.getBody() + "] from [" +  message.getFrom() + "]");

                  }

              }

          }, filter);

      }

 

      log.info("Listening for Chat Messages");

  }

 

  public void listenForNormalMessages() {

 

      if (connection != null) {

        

          PacketFilter filter = new MessageTypeFilter(Message.Type.normal);

          connection.addPacketListener(new PacketListener() {

        

              @Override

              public void processPacket(Packet packet) {

                  Message message = (Message) packet;

                  if (message.getBody() != null) {

                      log.info("Received normal message [" + message.getBody() + "] from [" +  message.getFrom() + "]");

                      DelayInformation inf = null;

                      try {

                          inf = (DelayInformation)packet.getExtension("x","jabber:x:delay");

                      } catch (Exception e) {

                          System.out.println("Error retrieving delay information: " + e.toString());

                      }

                      // get offline message timestamp

                      if(inf!=null){

                          Date date = inf.getStamp();

                          log.info("Packet Date: " + date);

                      }

                  }

              }

          }, filter);

      }

 

      log.info("Listening for Normal Messages");

  }

 

  private void startFileTransferManager() {

 

       manager = new FileTransferManager(connection);

       manager.addFileTransferListener(new FileTransferListener() {

 

            public void fileTransferRequest(final FileTransferRequest request) {

                 log.info("File transfer request received");

                 new Thread() {

      

                      @Override

                      public void run() {

                           log.info("Received request from: " + request.getRequestor() + " to transfer file: " + request.getFileName());

                           //FileTransferNegotiator.IBB_ONLY = true;

                           IncomingFileTransfer transfer = request.accept();

                           log.info("File transfer request accepted");

                           String path = getRunDirectory() + File.separator + System.currentTimeMillis() + ".jpg";

                           File file = new File(path);

                           try {

                                transfer.recieveFile(file);

                                while (!transfer.isDone()) {

                                     pause(1000);

                                     if (transfer.getStatus().equals(Status.error)) {

                                          log.error("File transfer error: " + transfer.getError());

                                          if (transfer.getException() != null) {

                                               log.error("Transfer exception: " + transfer.getException().getMessage());

                                          }                        

                                          break;

                                     }

                                }    

                           } catch (Exception e) {

                                log.error("File transfer exception caught: " + e.getMessage());

                           }

 

                           if (transfer.getStatus().equals(Status.complete)) {

                                log.info("File transfer complete");

                           }

                      };         

                  }.start();

          }

       });

 

       log.info("File Transfer Manager is listening for requests");

  }

 

  public void admitFriendsRequest() {

 

       connection.getRoster().setSubscriptionMode(Roster.SubscriptionMode.manual);

       connection.addPacketListener(new PacketListener() {

 

           public void processPacket(Packet paramPacket) {

 

               if (paramPacket instanceof Presence) {

                   Presence presence = (Presence) paramPacket;

                   String email = presence.getFrom();

                   log.info("chat invite status changed by user: : "

                           + email + " calling listner");

                   log.info("presence: " + presence.getFrom()

                           + "; type: " + presence.getType() + "; to: "

                           + presence.getTo() + "; " + presence.toXML());

                   Roster roster = connection.getRoster();

                   for (RosterEntry rosterEntry : roster.getEntries()) {

                       log.info("jid: " + rosterEntry.getUser()

                               + "; type: " + rosterEntry.getType()

                               + "; status: " + rosterEntry.getStatus());

                   }

 

                   if (presence.getType().equals(Presence.Type.subscribe)) {

                  

                       Presence newp = new Presence(Presence.Type.subscribed);

                       newp.setMode(Presence.Mode.available);

                       newp.setPriority(24);

                       newp.setTo(presence.getFrom());

                       try {

                           connection.sendPacket(newp);

                       } catch (Exception e) {

                      

                       }

 

                       Presence subscription = new Presence(

                               Presence.Type.subscribe);

                       subscription.setTo(presence.getFrom());

                      

                      

                       try {

                       connection.sendPacket(subscription);

                       } catch (Exception e) {

                      

                       }

 

                   } else if (presence.getType().equals(Presence.Type.unsubscribe)) {

                  

                       Presence newp = new Presence(Presence.Type.unsubscribed);

                       newp.setMode(Presence.Mode.available);

                       newp.setPriority(24);

                       newp.setTo(presence.getFrom());

                      

                       try {

                       connection.sendPacket(newp);

                       } catch (Exception e) {

                      

                       }

                   } else {

                   log.info("Other type of presence packet received");

                   }

               }

 

           }

       }, new PacketFilter() {

           public boolean accept(Packet packet) {

               if (packet instanceof Presence) {

                   Presence presence = (Presence) packet;

                   if (presence.getType().equals(Presence.Type.subscribed)

                           || presence.getType().equals(

                                   Presence.Type.subscribe)

                           || presence.getType().equals(

                                   Presence.Type.unsubscribed)

                           || presence.getType().equals(

                                   Presence.Type.unsubscribe)) {

                       return true;

                   }

               }

               return false;

           }

       });

 

   }

 

  private String getRunDirectory() {

 

       try {

            File cur_dir = new File(".");

       return cur_dir.getCanonicalPath();

       } catch (IOException e) {

            return null;

       }

  }

 

  private void pause(int delay){

       try {

            Thread.sleep(delay);

       } catch (Exception e) {

            // ignore

       }

  }

 

}

Outcomes