예제 #1
0
  private void registerPresenceListener() {
    // do not register multiple packet listeners
    if (mPresenceListener != null) mXMPPConnection.removePacketListener(mPresenceListener);

    mPresenceListener =
        new PacketListener() {
          public void processPacket(Packet packet) {
            try {
              Presence p = (Presence) packet;
              switch (p.getType()) {
                case subscribe:
                  handleIncomingSubscribe(p);
                  break;
                case unsubscribe:
                  break;
              }
            } catch (Exception e) {
              // SMACK silently discards exceptions dropped from processPacket :(
              Log.e(TAG, "failed to process presence:");
              e.printStackTrace();
            }
          }
        };

    mXMPPConnection.addPacketListener(mPresenceListener, new PacketTypeFilter(Presence.class));
  }
예제 #2
0
  /**
   * Check the server connection, reconnect if needed.
   *
   * <p>This function will try to ping the server if we are connected, and try to reestablish a
   * connection otherwise.
   */
  public void sendServerPing() {
    if (mXMPPConnection == null || !mXMPPConnection.isAuthenticated()) {
      debugLog("Ping: requested, but not connected to server.");
      requestConnectionState(ConnectionState.ONLINE, false);
      return;
    }
    if (mPingID != null) {
      debugLog("Ping: requested, but still waiting for " + mPingID);
      return; // a ping is still on its way
    }

    if (mStreamHandler.isSmEnabled()) {
      debugLog("Ping: sending SM request");
      mPingID = "" + mStreamHandler.requestAck();
    } else {
      Ping ping = new Ping();
      ping.setType(Type.GET);
      ping.setTo(mConfig.server);
      mPingID = ping.getPacketID();
      debugLog("Ping: sending ping " + mPingID);
      mXMPPConnection.sendPacket(ping);
    }

    // register ping timeout handler: PACKET_TIMEOUT(30s) + 3s
    registerPongTimeout(PACKET_TIMEOUT + 3000, mPingID);
  }
예제 #3
0
  private void registerRosterListener() {
    // flush roster on connecting.
    mRoster = mXMPPConnection.getRoster();
    mRoster.setSubscriptionMode(Roster.SubscriptionMode.manual);

    if (mRosterListener != null) mRoster.removeRosterListener(mRosterListener);

    mRosterListener =
        new RosterListener() {
          private boolean first_roster = true;

          public void entriesAdded(Collection<String> entries) {
            debugLog("entriesAdded(" + entries + ")");

            ContentValues[] cvs = new ContentValues[entries.size()];
            int i = 0;
            for (String entry : entries) {
              RosterEntry rosterEntry = mRoster.getEntry(entry);
              cvs[i++] = getContentValuesForRosterEntry(rosterEntry);
            }
            mContentResolver.bulkInsert(RosterProvider.CONTENT_URI, cvs);
            // when getting the roster in the beginning, remove remains of old one
            if (first_roster) {
              removeOldRosterEntries();
              first_roster = false;
              mServiceCallBack.rosterChanged();
            }
            debugLog("entriesAdded() done");
          }

          public void entriesDeleted(Collection<String> entries) {
            debugLog("entriesDeleted(" + entries + ")");

            for (String entry : entries) {
              deleteRosterEntryFromDB(entry);
            }
            mServiceCallBack.rosterChanged();
          }

          public void entriesUpdated(Collection<String> entries) {
            debugLog("entriesUpdated(" + entries + ")");

            for (String entry : entries) {
              RosterEntry rosterEntry = mRoster.getEntry(entry);
              updateRosterEntryInDB(rosterEntry);
            }
            mServiceCallBack.rosterChanged();
          }

          public void presenceChanged(Presence presence) {
            debugLog("presenceChanged(" + presence.getFrom() + "): " + presence);

            String jabberID = getBareJID(presence.getFrom());
            RosterEntry rosterEntry = mRoster.getEntry(jabberID);
            updateRosterEntryInDB(rosterEntry);
            mServiceCallBack.rosterChanged();
          }
        };
    mRoster.addRosterListener(mRosterListener);
  }
예제 #4
0
 public void sendPresenceRequest(String user, String type) {
   // HACK: remove the fake roster entry added by handleIncomingSubscribe()
   if ("unsubscribed".equals(type)) deleteRosterEntryFromDB(user);
   Presence response = new Presence(Presence.Type.valueOf(type));
   response.setTo(user);
   mXMPPConnection.sendPacket(response);
 }
예제 #5
0
  public void unRegisterCallback() {
    debugLog("unRegisterCallback()");
    // remove callbacks _before_ tossing old connection
    try {
      mXMPPConnection.getRoster().removeRosterListener(mRosterListener);
      mXMPPConnection.removePacketListener(mPacketListener);
      mXMPPConnection.removePacketListener(mPresenceListener);

      mXMPPConnection.removePacketListener(mPongListener);
      unregisterPongListener();
    } catch (Exception e) {
      // ignore it!
      e.printStackTrace();
    }
    requestConnectionState(ConnectionState.OFFLINE);
    setStatusOffline();
    mService.unregisterReceiver(mPingAlarmReceiver);
    mService.unregisterReceiver(mPongTimeoutAlarmReceiver);
    this.mServiceCallBack = null;
  }
예제 #6
0
  public void setStatusFromConfig() {
    // TODO: only call this when carbons changed, not on every presence change
    CarbonManager.getInstanceFor(mXMPPConnection).sendCarbonsEnabled(mConfig.messageCarbons);

    Presence presence = new Presence(Presence.Type.available);
    Mode mode = Mode.valueOf(mConfig.statusMode);
    presence.setMode(mode);
    presence.setStatus(mConfig.statusMessage);
    presence.setPriority(mConfig.priority);
    mXMPPConnection.sendPacket(presence);
    mConfig.presence_required = false;
  }
예제 #7
0
  /**
   * Registers a smack packet listener for IQ packets, intended to recognize "pongs" with a packet
   * id matching the last "ping" sent to the server.
   *
   * <p>Also sets up the AlarmManager Timer plus necessary intents.
   */
  private void registerPongListener() {
    // reset ping expectation on new connection
    mPingID = null;

    if (mPongListener != null) mXMPPConnection.removePacketListener(mPongListener);

    mPongListener =
        new PacketListener() {

          @Override
          public void processPacket(Packet packet) {
            if (packet == null) return;

            gotServerPong(packet.getPacketID());
          }
        };

    mXMPPConnection.addPacketListener(mPongListener, new PacketTypeFilter(IQ.class));
    mPingAlarmPendIntent =
        PendingIntent.getBroadcast(
            mService.getApplicationContext(),
            0,
            mPingAlarmIntent,
            PendingIntent.FLAG_UPDATE_CURRENT);
    mPongTimeoutAlarmPendIntent =
        PendingIntent.getBroadcast(
            mService.getApplicationContext(),
            0,
            mPongTimeoutAlarmIntent,
            PendingIntent.FLAG_UPDATE_CURRENT);
    mAlarmManager.setInexactRepeating(
        AlarmManager.RTC_WAKEUP,
        System.currentTimeMillis() + AlarmManager.INTERVAL_FIFTEEN_MINUTES,
        AlarmManager.INTERVAL_FIFTEEN_MINUTES,
        mPingAlarmPendIntent);
  }
예제 #8
0
  private void tryToRemoveRosterEntry(String user) throws YaximXMPPException {
    try {
      RosterEntry rosterEntry = mRoster.getEntry(user);

      if (rosterEntry != null) {
        // first, unsubscribe the user
        Presence unsub = new Presence(Presence.Type.unsubscribed);
        unsub.setTo(rosterEntry.getUser());
        mXMPPConnection.sendPacket(unsub);
        // then, remove from roster
        mRoster.removeEntry(rosterEntry);
      }
    } catch (XMPPException e) {
      throw new YaximXMPPException("tryToRemoveRosterEntry", e);
    }
  }
예제 #9
0
 public void sendOfflineMessages() {
   Cursor cursor =
       mContentResolver.query(
           ChatProvider.CONTENT_URI, SEND_OFFLINE_PROJECTION, SEND_OFFLINE_SELECTION, null, null);
   final int _ID_COL = cursor.getColumnIndexOrThrow(ChatConstants._ID);
   final int JID_COL = cursor.getColumnIndexOrThrow(ChatConstants.JID);
   final int MSG_COL = cursor.getColumnIndexOrThrow(ChatConstants.MESSAGE);
   final int TS_COL = cursor.getColumnIndexOrThrow(ChatConstants.DATE);
   final int PACKETID_COL = cursor.getColumnIndexOrThrow(ChatConstants.PACKET_ID);
   ContentValues mark_sent = new ContentValues();
   mark_sent.put(ChatConstants.DELIVERY_STATUS, ChatConstants.DS_SENT_OR_READ);
   while (cursor.moveToNext()) {
     int _id = cursor.getInt(_ID_COL);
     String toJID = cursor.getString(JID_COL);
     String message = cursor.getString(MSG_COL);
     String packetID = cursor.getString(PACKETID_COL);
     long ts = cursor.getLong(TS_COL);
     Log.d(TAG, "sendOfflineMessages: " + toJID + " > " + message);
     final Message newMessage = new Message(toJID, Message.Type.chat);
     newMessage.setBody(message);
     DelayInformation delay = new DelayInformation(new Date(ts));
     newMessage.addExtension(delay);
     newMessage.addExtension(new DelayInfo(delay));
     newMessage.addExtension(new DeliveryReceiptRequest());
     if ((packetID != null) && (packetID.length() > 0)) {
       newMessage.setPacketID(packetID);
     } else {
       packetID = newMessage.getPacketID();
       mark_sent.put(ChatConstants.PACKET_ID, packetID);
     }
     Uri rowuri =
         Uri.parse(
             "content://" + ChatProvider.AUTHORITY + "/" + ChatProvider.TABLE_NAME + "/" + _id);
     mContentResolver.update(rowuri, mark_sent, null, null);
     mXMPPConnection.sendPacket(
         newMessage); // must be after marking delivered, otherwise it may override the
     // SendFailListener
   }
   cursor.close();
 }
예제 #10
0
 public void sendMessage(String toJID, String message) {
   final Message newMessage = new Message(toJID, Message.Type.chat);
   newMessage.setBody(message);
   newMessage.addExtension(new DeliveryReceiptRequest());
   if (isAuthenticated()) {
     addChatMessageToDB(
         ChatConstants.OUTGOING,
         toJID,
         message,
         ChatConstants.DS_SENT_OR_READ,
         System.currentTimeMillis(),
         newMessage.getPacketID());
     mXMPPConnection.sendPacket(newMessage);
   } else {
     // send offline -> store to DB
     addChatMessageToDB(
         ChatConstants.OUTGOING,
         toJID,
         message,
         ChatConstants.DS_NEW,
         System.currentTimeMillis(),
         newMessage.getPacketID());
   }
 }
예제 #11
0
 public boolean isAuthenticated() {
   if (mXMPPConnection != null) {
     return (mXMPPConnection.isConnected() && mXMPPConnection.isAuthenticated());
   }
   return false;
 }
예제 #12
0
 public void sendReceipt(String toJID, String id) {
   Log.d(TAG, "sending XEP-0184 ack to " + toJID + " id=" + id);
   final Message ack = new Message(toJID, Message.Type.normal);
   ack.addExtension(new DeliveryReceipt(id));
   mXMPPConnection.sendPacket(ack);
 }
예제 #13
0
  private void tryToConnect(boolean create_account) throws YaximXMPPException {
    try {
      if (mXMPPConnection.isConnected()) {
        try {
          mStreamHandler.quickShutdown(); // blocking shutdown prior to re-connection
        } catch (Exception e) {
          debugLog("conn.shutdown() failed: " + e);
        }
      }
      registerRosterListener();
      boolean need_bind = !mStreamHandler.isResumePossible();

      mXMPPConnection.connect(need_bind);
      // the following should not happen as of smack 3.3.1
      if (!mXMPPConnection.isConnected()) {
        throw new YaximXMPPException("SMACK connect failed without exception!");
      }
      if (mConnectionListener != null)
        mXMPPConnection.removeConnectionListener(mConnectionListener);
      mConnectionListener =
          new ConnectionListener() {
            public void connectionClosedOnError(Exception e) {
              onDisconnected(e);
            }

            public void connectionClosed() {
              // TODO: fix reconnect when we got kicked by the server or SM failed!
              // onDisconnected(null);
              updateConnectionState(ConnectionState.OFFLINE);
            }

            public void reconnectingIn(int seconds) {}

            public void reconnectionFailed(Exception e) {}

            public void reconnectionSuccessful() {}
          };
      mXMPPConnection.addConnectionListener(mConnectionListener);

      // SMACK auto-logins if we were authenticated before
      if (!mXMPPConnection.isAuthenticated()) {
        if (create_account) {
          Log.d(TAG, "creating new server account...");
          AccountManager am = new AccountManager(mXMPPConnection);
          am.createAccount(mConfig.userName, mConfig.password);
        }
        mXMPPConnection.login(mConfig.userName, mConfig.password, mConfig.ressource);
      }
      Log.d(
          TAG, "SM: can resume = " + mStreamHandler.isResumePossible() + " needbind=" + need_bind);
      if (need_bind) {
        mStreamHandler.notifyInitialLogin();
        setStatusFromConfig();
      }

    } catch (YaximXMPPException e) {
      throw e;
    } catch (Exception e) {
      // actually we just care for IllegalState or NullPointer or XMPPEx.
      throw new YaximXMPPException("tryToConnect failed", e);
    }
  }
예제 #14
0
  private void registerMessageListener() {
    // do not register multiple packet listeners
    if (mPacketListener != null) mXMPPConnection.removePacketListener(mPacketListener);

    PacketTypeFilter filter = new PacketTypeFilter(Message.class);

    mPacketListener =
        new PacketListener() {
          public void processPacket(Packet packet) {
            try {
              if (packet instanceof Message) {
                Message msg = (Message) packet;

                String fromJID = getBareJID(msg.getFrom());
                int direction = ChatConstants.INCOMING;
                Carbon cc = CarbonManager.getCarbon(msg);

                // extract timestamp
                long ts;
                DelayInfo timestamp = (DelayInfo) msg.getExtension("delay", "urn:xmpp:delay");
                if (timestamp == null)
                  timestamp = (DelayInfo) msg.getExtension("x", "jabber:x:delay");
                if (cc != null) // Carbon timestamp overrides packet timestamp
                timestamp = cc.getForwarded().getDelayInfo();
                if (timestamp != null) ts = timestamp.getStamp().getTime();
                else ts = System.currentTimeMillis();

                // try to extract a carbon
                if (cc != null) {
                  Log.d(TAG, "carbon: " + cc.toXML());
                  msg = (Message) cc.getForwarded().getForwardedPacket();

                  // outgoing carbon: fromJID is actually chat peer's JID
                  if (cc.getDirection() == Carbon.Direction.sent) {
                    fromJID = getBareJID(msg.getTo());
                    direction = ChatConstants.OUTGOING;
                  } else {
                    fromJID = getBareJID(msg.getFrom());

                    // hook off carbonated delivery receipts
                    DeliveryReceipt dr =
                        (DeliveryReceipt)
                            msg.getExtension(DeliveryReceipt.ELEMENT, DeliveryReceipt.NAMESPACE);
                    if (dr != null) {
                      Log.d(TAG, "got CC'ed delivery receipt for " + dr.getId());
                      changeMessageDeliveryStatus(dr.getId(), ChatConstants.DS_ACKED);
                    }
                  }
                }

                String chatMessage = msg.getBody();

                // display error inline
                if (msg.getType() == Message.Type.error) {
                  if (changeMessageDeliveryStatus(msg.getPacketID(), ChatConstants.DS_FAILED))
                    mServiceCallBack.messageError(fromJID, msg.getError().toString(), (cc != null));
                  return; // we do not want to add errors as "incoming messages"
                }

                // ignore empty messages
                if (chatMessage == null) {
                  Log.d(TAG, "empty message.");
                  return;
                }

                // carbons are old. all others are new
                int is_new = (cc == null) ? ChatConstants.DS_NEW : ChatConstants.DS_SENT_OR_READ;
                if (msg.getType() == Message.Type.error) is_new = ChatConstants.DS_FAILED;

                addChatMessageToDB(direction, fromJID, chatMessage, is_new, ts, msg.getPacketID());
                if (direction == ChatConstants.INCOMING)
                  mServiceCallBack.newMessage(fromJID, chatMessage, (cc != null));
              }
            } catch (Exception e) {
              // SMACK silently discards exceptions dropped from processPacket :(
              Log.e(TAG, "failed to process packet:");
              e.printStackTrace();
            }
          }
        };

    mXMPPConnection.addPacketListener(mPacketListener, filter);
  }