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)); }
/** * 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); }
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); }
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); }
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; }
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; }
/** * 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); }
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); } }
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(); }
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()); } }
public boolean isAuthenticated() { if (mXMPPConnection != null) { return (mXMPPConnection.isConnected() && mXMPPConnection.isAuthenticated()); } return false; }
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); }
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); } }
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); }