Merge remote-tracking branch 'upstream/development' into fix_typo
This commit is contained in:
		
						commit
						969cba5ee6
					
				| @ -1,8 +1,8 @@ | |||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|     package="eu.siacs.conversations" |     package="eu.siacs.conversations" | ||||||
|     android:versionCode="24" |     android:versionCode="26" | ||||||
|     android:versionName="0.6-alpha" > |     android:versionName="0.7-alpha" > | ||||||
| 
 | 
 | ||||||
|     <uses-sdk |     <uses-sdk | ||||||
|         android:minSdkVersion="14" |         android:minSdkVersion="14" | ||||||
|  | |||||||
| @ -1,5 +1,12 @@ | |||||||
| ###Changelog | ###Changelog | ||||||
| 
 | 
 | ||||||
|  | ####Version 0.6 | ||||||
|  | * Support for server side avatars | ||||||
|  | * save images in gallery | ||||||
|  | * show contact name and picture in non-anonymous conferences | ||||||
|  | * reworked account creation | ||||||
|  | * various bug fixes | ||||||
|  | 
 | ||||||
| ####Version 0.5.2 | ####Version 0.5.2 | ||||||
| * minor bug fixes | * minor bug fixes | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -12,23 +12,13 @@ public abstract class AbstractGenerator { | |||||||
| 	public final String[] FEATURES = { "urn:xmpp:jingle:1", | 	public final String[] FEATURES = { "urn:xmpp:jingle:1", | ||||||
| 			"urn:xmpp:jingle:apps:file-transfer:3", | 			"urn:xmpp:jingle:apps:file-transfer:3", | ||||||
| 			"urn:xmpp:jingle:transports:s5b:1", | 			"urn:xmpp:jingle:transports:s5b:1", | ||||||
| 			"urn:xmpp:jingle:transports:ibb:1", | 			"urn:xmpp:jingle:transports:ibb:1", "urn:xmpp:receipts", | ||||||
| 			"urn:xmpp:receipts", | 			"urn:xmpp:chat-markers:0", "http://jabber.org/protocol/muc", | ||||||
| 			"urn:xmpp:chat-markers:0", | 			"jabber:x:conference", "http://jabber.org/protocol/caps", | ||||||
| 			"http://jabber.org/protocol/muc", |  | ||||||
| 			"jabber:x:conference", |  | ||||||
| 			"http://jabber.org/protocol/caps", |  | ||||||
| 			"http://jabber.org/protocol/disco#info", | 			"http://jabber.org/protocol/disco#info", | ||||||
| 			"urn:xmpp:avatar:metadata+notify" }; | 			"urn:xmpp:avatar:metadata+notify" }; | ||||||
| 	public final String IDENTITY_NAME = "Conversations 0.5"; | 	public final String IDENTITY_NAME = "Conversations 0.6"; | ||||||
| 	public final String IDENTITY_TYPE = "phone"; | 	public final String IDENTITY_TYPE = "phone"; | ||||||
| 	/*public final String[] FEATURES = { "http://jabber.org/protocol/muc","http://jabber.org/protocol/disco#info", "http://jabber.org/protocol/disco#items", "http://jabber.org/protocol/caps" }; |  | ||||||
| 	 |  | ||||||
| 	public final String IDENTITY_NAME = "Exodus 0.9.1"; |  | ||||||
| 	public final String IDENTITY_TYPE = "pc";*/ |  | ||||||
| 	 |  | ||||||
| 	 |  | ||||||
| 	 |  | ||||||
| 
 | 
 | ||||||
| 	public String getCapHash() { | 	public String getCapHash() { | ||||||
| 		StringBuilder s = new StringBuilder(); | 		StringBuilder s = new StringBuilder(); | ||||||
| @ -36,8 +26,7 @@ public abstract class AbstractGenerator { | |||||||
| 		MessageDigest md = null; | 		MessageDigest md = null; | ||||||
| 		try { | 		try { | ||||||
| 			md = MessageDigest.getInstance("SHA-1"); | 			md = MessageDigest.getInstance("SHA-1"); | ||||||
| 	    } | 		} catch (NoSuchAlgorithmException e) { | ||||||
| 	    catch(NoSuchAlgorithmException e) { |  | ||||||
| 			return null; | 			return null; | ||||||
| 		} | 		} | ||||||
| 		List<String> features = Arrays.asList(FEATURES); | 		List<String> features = Arrays.asList(FEATURES); | ||||||
|  | |||||||
| @ -49,6 +49,7 @@ import eu.siacs.conversations.xml.Element; | |||||||
| import eu.siacs.conversations.xmpp.OnBindListener; | import eu.siacs.conversations.xmpp.OnBindListener; | ||||||
| import eu.siacs.conversations.xmpp.OnContactStatusChanged; | import eu.siacs.conversations.xmpp.OnContactStatusChanged; | ||||||
| import eu.siacs.conversations.xmpp.OnIqPacketReceived; | import eu.siacs.conversations.xmpp.OnIqPacketReceived; | ||||||
|  | import eu.siacs.conversations.xmpp.OnMessageAcknowledged; | ||||||
| import eu.siacs.conversations.xmpp.OnStatusChanged; | import eu.siacs.conversations.xmpp.OnStatusChanged; | ||||||
| import eu.siacs.conversations.xmpp.XmppConnection; | import eu.siacs.conversations.xmpp.XmppConnection; | ||||||
| import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager; | import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager; | ||||||
| @ -146,8 +147,10 @@ public class XmppConnectionService extends Service { | |||||||
| 
 | 
 | ||||||
| 		@Override | 		@Override | ||||||
| 		public void onStatusChanged(Account account) { | 		public void onStatusChanged(Account account) { | ||||||
|  | 			XmppConnection connection = account.getXmppConnection(); | ||||||
| 			if (mOnAccountUpdate != null) { | 			if (mOnAccountUpdate != null) { | ||||||
| 				mOnAccountUpdate.onAccountUpdate();; | 				mOnAccountUpdate.onAccountUpdate(); | ||||||
|  | 				; | ||||||
| 			} | 			} | ||||||
| 			if (account.getStatus() == Account.STATUS_ONLINE) { | 			if (account.getStatus() == Account.STATUS_ONLINE) { | ||||||
| 				for (Conversation conversation : account.pendingConferenceLeaves) { | 				for (Conversation conversation : account.pendingConferenceLeaves) { | ||||||
| @ -164,27 +167,35 @@ public class XmppConnectionService extends Service { | |||||||
| 						sendUnsendMessages(conversations.get(i)); | 						sendUnsendMessages(conversations.get(i)); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  | 				if (connection != null && connection.getFeatures().csi()) { | ||||||
|  | 					if (checkListeners()) { | ||||||
|  | 						Log.d(LOGTAG, account.getJid() | ||||||
|  | 								+ " sending csi//inactive"); | ||||||
|  | 						connection.sendInactive(); | ||||||
|  | 					} else { | ||||||
|  | 						Log.d(LOGTAG, account.getJid() + " sending csi//active"); | ||||||
|  | 						connection.sendActive(); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
| 				syncDirtyContacts(account); | 				syncDirtyContacts(account); | ||||||
| 				scheduleWakeupCall(PING_MAX_INTERVAL, true); | 				scheduleWakeupCall(PING_MAX_INTERVAL, true); | ||||||
| 			} else if (account.getStatus() == Account.STATUS_OFFLINE) { | 			} else if (account.getStatus() == Account.STATUS_OFFLINE) { | ||||||
|  | 				resetSendingToWaiting(account); | ||||||
| 				if (!account.isOptionSet(Account.OPTION_DISABLED)) { | 				if (!account.isOptionSet(Account.OPTION_DISABLED)) { | ||||||
| 					int timeToReconnect = mRandom.nextInt(50) + 10; | 					int timeToReconnect = mRandom.nextInt(50) + 10; | ||||||
| 					scheduleWakeupCall(timeToReconnect, false); | 					scheduleWakeupCall(timeToReconnect, false); | ||||||
| 				} | 				} | ||||||
| 
 |  | ||||||
| 			} else if (account.getStatus() == Account.STATUS_REGISTRATION_SUCCESSFULL) { | 			} else if (account.getStatus() == Account.STATUS_REGISTRATION_SUCCESSFULL) { | ||||||
| 				databaseBackend.updateAccount(account); | 				databaseBackend.updateAccount(account); | ||||||
| 				reconnectAccount(account, true); | 				reconnectAccount(account, true); | ||||||
| 			} else if ((account.getStatus() != Account.STATUS_CONNECTING) | 			} else if ((account.getStatus() != Account.STATUS_CONNECTING) | ||||||
| 					&& (account.getStatus() != Account.STATUS_NO_INTERNET)) { | 					&& (account.getStatus() != Account.STATUS_NO_INTERNET)) { | ||||||
| 				XmppConnection connection = account.getXmppConnection(); |  | ||||||
| 				if (connection != null) { | 				if (connection != null) { | ||||||
| 					int next = connection.getTimeToNextAttempt(); | 					int next = connection.getTimeToNextAttempt(); | ||||||
| 					Log.d(LOGTAG, account.getJid() | 					Log.d(LOGTAG, account.getJid() | ||||||
| 							+ ": error connecting account. try again in " + next | 							+ ": error connecting account. try again in " | ||||||
| 							+ "s for the " | 							+ next + "s for the " | ||||||
| 							+ (connection.getAttempt() + 1) | 							+ (connection.getAttempt() + 1) + " time"); | ||||||
| 							+ " time"); |  | ||||||
| 					scheduleWakeupCall((int) (next * 1.2), false); | 					scheduleWakeupCall((int) (next * 1.2), false); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| @ -217,12 +228,32 @@ public class XmppConnectionService extends Service { | |||||||
| 			account.pendingConferenceLeaves.clear(); | 			account.pendingConferenceLeaves.clear(); | ||||||
| 			fetchRosterFromServer(account); | 			fetchRosterFromServer(account); | ||||||
| 			fetchBookmarks(account); | 			fetchBookmarks(account); | ||||||
| 				sendPresencePacket(account, mPresenceGenerator.sendPresence(account)); | 			sendPresencePacket(account, | ||||||
|  | 					mPresenceGenerator.sendPresence(account)); | ||||||
| 			connectMultiModeConversations(account); | 			connectMultiModeConversations(account); | ||||||
| 			updateConversationUi(); | 			updateConversationUi(); | ||||||
| 		} | 		} | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | 	private OnMessageAcknowledged mOnMessageAcknowledgedListener = new OnMessageAcknowledged() { | ||||||
|  | 
 | ||||||
|  | 		@Override | ||||||
|  | 		public void onMessageAcknowledged(Account account, String uuid) { | ||||||
|  | 			for (Conversation conversation : getConversations()) { | ||||||
|  | 				if (conversation.getAccount() == account) { | ||||||
|  | 					for (Message message : conversation.getMessages()) { | ||||||
|  | 						if ((message.getStatus() == Message.STATUS_UNSEND || message | ||||||
|  | 								.getStatus() == Message.STATUS_WAITING) | ||||||
|  | 								&& message.getUuid().equals(uuid)) { | ||||||
|  | 							markMessage(message, Message.STATUS_SEND); | ||||||
|  | 							return; | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
| 	public PgpEngine getPgpEngine() { | 	public PgpEngine getPgpEngine() { | ||||||
| 		if (pgpServiceConnection.isBound()) { | 		if (pgpServiceConnection.isBound()) { | ||||||
| 			if (this.mPgpEngine == null) { | 			if (this.mPgpEngine == null) { | ||||||
| @ -320,8 +351,10 @@ public class XmppConnectionService extends Service { | |||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 					if (account.getStatus() == Account.STATUS_ONLINE) { | 					if (account.getStatus() == Account.STATUS_ONLINE) { | ||||||
| 						long lastReceived = account.getXmppConnection().getLastPacketReceived(); | 						long lastReceived = account.getXmppConnection() | ||||||
| 						long lastSent = account.getXmppConnection().getLastPingSent(); | 								.getLastPacketReceived(); | ||||||
|  | 						long lastSent = account.getXmppConnection() | ||||||
|  | 								.getLastPingSent(); | ||||||
| 						if (lastSent - lastReceived >= PING_TIMEOUT * 1000) { | 						if (lastSent - lastReceived >= PING_TIMEOUT * 1000) { | ||||||
| 							Log.d(LOGTAG, account.getJid() + ": ping timeout"); | 							Log.d(LOGTAG, account.getJid() + ": ping timeout"); | ||||||
| 							this.reconnectAccount(account, true); | 							this.reconnectAccount(account, true); | ||||||
| @ -369,7 +402,8 @@ public class XmppConnectionService extends Service { | |||||||
| 		ExceptionHelper.init(getApplicationContext()); | 		ExceptionHelper.init(getApplicationContext()); | ||||||
| 		PRNGFixes.apply(); | 		PRNGFixes.apply(); | ||||||
| 		this.mRandom = new SecureRandom(); | 		this.mRandom = new SecureRandom(); | ||||||
| 		this.mMemorizingTrustManager = new MemorizingTrustManager(getApplicationContext()); | 		this.mMemorizingTrustManager = new MemorizingTrustManager( | ||||||
|  | 				getApplicationContext()); | ||||||
| 		this.databaseBackend = DatabaseBackend | 		this.databaseBackend = DatabaseBackend | ||||||
| 				.getInstance(getApplicationContext()); | 				.getInstance(getApplicationContext()); | ||||||
| 		this.fileBackend = new FileBackend(getApplicationContext()); | 		this.fileBackend = new FileBackend(getApplicationContext()); | ||||||
| @ -466,10 +500,11 @@ public class XmppConnectionService extends Service { | |||||||
| 		connection.setOnMessagePacketReceivedListener(this.mMessageParser); | 		connection.setOnMessagePacketReceivedListener(this.mMessageParser); | ||||||
| 		connection.setOnStatusChangedListener(this.statusListener); | 		connection.setOnStatusChangedListener(this.statusListener); | ||||||
| 		connection.setOnPresencePacketReceivedListener(this.mPresenceParser); | 		connection.setOnPresencePacketReceivedListener(this.mPresenceParser); | ||||||
| 		connection | 		connection.setOnUnregisteredIqPacketReceivedListener(this.mIqParser); | ||||||
| 				.setOnUnregisteredIqPacketReceivedListener(this.mIqParser); |  | ||||||
| 		connection.setOnJinglePacketReceivedListener(this.jingleListener); | 		connection.setOnJinglePacketReceivedListener(this.jingleListener); | ||||||
| 		connection.setOnBindListener(this.mOnBindListener); | 		connection.setOnBindListener(this.mOnBindListener); | ||||||
|  | 		connection | ||||||
|  | 				.setOnMessageAcknowledgeListener(this.mOnMessageAcknowledgedListener); | ||||||
| 		return connection; | 		return connection; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -514,7 +549,6 @@ public class XmppConnectionService extends Service { | |||||||
| 								.getUserID()); | 								.getUserID()); | ||||||
| 						packet = mMessageGenerator.generateOtrChat(message); | 						packet = mMessageGenerator.generateOtrChat(message); | ||||||
| 						send = true; | 						send = true; | ||||||
| 						message.setStatus(Message.STATUS_SEND); |  | ||||||
| 
 | 
 | ||||||
| 					} else if (message.getPresence() == null) { | 					} else if (message.getPresence() == null) { | ||||||
| 						message.setStatus(Message.STATUS_WAITING); | 						message.setStatus(Message.STATUS_WAITING); | ||||||
| @ -523,14 +557,10 @@ public class XmppConnectionService extends Service { | |||||||
| 					message.getConversation().endOtrIfNeeded(); | 					message.getConversation().endOtrIfNeeded(); | ||||||
| 					failWaitingOtrMessages(message.getConversation()); | 					failWaitingOtrMessages(message.getConversation()); | ||||||
| 					packet = mMessageGenerator.generatePgpChat(message); | 					packet = mMessageGenerator.generatePgpChat(message); | ||||||
| 					message.setStatus(Message.STATUS_SEND); |  | ||||||
| 					send = true; | 					send = true; | ||||||
| 				} else { | 				} else { | ||||||
| 					message.getConversation().endOtrIfNeeded(); | 					message.getConversation().endOtrIfNeeded(); | ||||||
| 					failWaitingOtrMessages(message.getConversation()); | 					failWaitingOtrMessages(message.getConversation()); | ||||||
| 					if (message.getConversation().getMode() == Conversation.MODE_SINGLE || message.getType() == Message.TYPE_PRIVATE) { |  | ||||||
| 						message.setStatus(Message.STATUS_SEND); |  | ||||||
| 					} |  | ||||||
| 					packet = mMessageGenerator.generateChat(message); | 					packet = mMessageGenerator.generateChat(message); | ||||||
| 					send = true; | 					send = true; | ||||||
| 				} | 				} | ||||||
| @ -562,11 +592,14 @@ public class XmppConnectionService extends Service { | |||||||
| 			databaseBackend.createMessage(message); | 			databaseBackend.createMessage(message); | ||||||
| 		} | 		} | ||||||
| 		conv.getMessages().add(message); | 		conv.getMessages().add(message); | ||||||
| 		updateConversationUi(); |  | ||||||
| 		if ((send) && (packet != null)) { | 		if ((send) && (packet != null)) { | ||||||
|  | 			if (!account.getXmppConnection().getFeatures().sm() | ||||||
|  | 					&& conv.getMode() != Conversation.MODE_MULTI) { | ||||||
|  | 				message.setStatus(Message.STATUS_SEND); | ||||||
|  | 			} | ||||||
| 			sendMessagePacket(account, packet); | 			sendMessagePacket(account, packet); | ||||||
| 		} | 		} | ||||||
| 
 | 		updateConversationUi(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private void sendUnsendMessages(Conversation conversation) { | 	private void sendUnsendMessages(Conversation conversation) { | ||||||
| @ -672,7 +705,8 @@ public class XmppConnectionService extends Service { | |||||||
| 			public void onIqPacketReceived(Account account, IqPacket packet) { | 			public void onIqPacketReceived(Account account, IqPacket packet) { | ||||||
| 				Element query = packet.query(); | 				Element query = packet.query(); | ||||||
| 				List<Bookmark> bookmarks = new CopyOnWriteArrayList<Bookmark>(); | 				List<Bookmark> bookmarks = new CopyOnWriteArrayList<Bookmark>(); | ||||||
| 				Element storage = query.findChild("storage", "storage:bookmarks"); | 				Element storage = query.findChild("storage", | ||||||
|  | 						"storage:bookmarks"); | ||||||
| 				if (storage != null) { | 				if (storage != null) { | ||||||
| 					for (Element item : storage.getChildren()) { | 					for (Element item : storage.getChildren()) { | ||||||
| 						if (item.getName().equals("conference")) { | 						if (item.getName().equals("conference")) { | ||||||
| @ -683,7 +717,8 @@ public class XmppConnectionService extends Service { | |||||||
| 								conversation.setBookmark(bookmark); | 								conversation.setBookmark(bookmark); | ||||||
| 							} else { | 							} else { | ||||||
| 								if (bookmark.autojoin()) { | 								if (bookmark.autojoin()) { | ||||||
| 									conversation = findOrCreateConversation(account, bookmark.getJid(), true); | 									conversation = findOrCreateConversation( | ||||||
|  | 											account, bookmark.getJid(), true); | ||||||
| 									conversation.setBookmark(bookmark); | 									conversation.setBookmark(bookmark); | ||||||
| 									joinMuc(conversation); | 									joinMuc(conversation); | ||||||
| 								} | 								} | ||||||
| @ -796,7 +831,8 @@ public class XmppConnectionService extends Service { | |||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public Conversation find(List<Conversation> haystack, Account account, String jid) { | 	public Conversation find(List<Conversation> haystack, Account account, | ||||||
|  | 			String jid) { | ||||||
| 		for (Conversation conversation : haystack) { | 		for (Conversation conversation : haystack) { | ||||||
| 			if ((conversation.getAccount().equals(account)) | 			if ((conversation.getAccount().equals(account)) | ||||||
| 					&& (conversation.getContactJid().split("/")[0].equals(jid))) { | 					&& (conversation.getContactJid().split("/")[0].equals(jid))) { | ||||||
| @ -806,7 +842,6 @@ public class XmppConnectionService extends Service { | |||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	 |  | ||||||
| 	public Conversation findOrCreateConversation(Account account, String jid, | 	public Conversation findOrCreateConversation(Account account, String jid, | ||||||
| 			boolean muc) { | 			boolean muc) { | ||||||
| 		Conversation conversation = find(account, jid); | 		Conversation conversation = find(account, jid); | ||||||
| @ -911,6 +946,9 @@ public class XmppConnectionService extends Service { | |||||||
| 
 | 
 | ||||||
| 	public void setOnConversationListChangedListener( | 	public void setOnConversationListChangedListener( | ||||||
| 			OnConversationUpdate listener) { | 			OnConversationUpdate listener) { | ||||||
|  | 		if (checkListeners()) { | ||||||
|  | 			switchToForeground(); | ||||||
|  | 		} | ||||||
| 		this.mOnConversationUpdate = listener; | 		this.mOnConversationUpdate = listener; | ||||||
| 		this.convChangedListenerCount++; | 		this.convChangedListenerCount++; | ||||||
| 	} | 	} | ||||||
| @ -919,10 +957,16 @@ public class XmppConnectionService extends Service { | |||||||
| 		this.convChangedListenerCount--; | 		this.convChangedListenerCount--; | ||||||
| 		if (this.convChangedListenerCount == 0) { | 		if (this.convChangedListenerCount == 0) { | ||||||
| 			this.mOnConversationUpdate = null; | 			this.mOnConversationUpdate = null; | ||||||
|  | 			if (checkListeners()) { | ||||||
|  | 				switchToBackground(); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void setOnAccountListChangedListener(OnAccountUpdate listener) { | 	public void setOnAccountListChangedListener(OnAccountUpdate listener) { | ||||||
|  | 		if (checkListeners()) { | ||||||
|  | 			switchToForeground(); | ||||||
|  | 		} | ||||||
| 		this.mOnAccountUpdate = listener; | 		this.mOnAccountUpdate = listener; | ||||||
| 		this.accountChangedListenerCount++; | 		this.accountChangedListenerCount++; | ||||||
| 	} | 	} | ||||||
| @ -931,15 +975,53 @@ public class XmppConnectionService extends Service { | |||||||
| 		this.accountChangedListenerCount--; | 		this.accountChangedListenerCount--; | ||||||
| 		if (this.accountChangedListenerCount == 0) { | 		if (this.accountChangedListenerCount == 0) { | ||||||
| 			this.mOnAccountUpdate = null; | 			this.mOnAccountUpdate = null; | ||||||
|  | 			if (checkListeners()) { | ||||||
|  | 				switchToBackground(); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void setOnRosterUpdateListener(OnRosterUpdate listener) { | 	public void setOnRosterUpdateListener(OnRosterUpdate listener) { | ||||||
|  | 		if (checkListeners()) { | ||||||
|  | 			switchToForeground(); | ||||||
|  | 		} | ||||||
| 		this.mOnRosterUpdate = listener; | 		this.mOnRosterUpdate = listener; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void removeOnRosterUpdateListener() { | 	public void removeOnRosterUpdateListener() { | ||||||
| 		this.mOnRosterUpdate = null; | 		this.mOnRosterUpdate = null; | ||||||
|  | 		if (checkListeners()) { | ||||||
|  | 			switchToBackground(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private boolean checkListeners() { | ||||||
|  | 		return (this.mOnAccountUpdate == null | ||||||
|  | 				&& this.mOnConversationUpdate == null && this.mOnRosterUpdate == null); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private void switchToForeground() { | ||||||
|  | 		for (Account account : getAccounts()) { | ||||||
|  | 			if (account.getStatus() == Account.STATUS_ONLINE) { | ||||||
|  | 				XmppConnection connection = account.getXmppConnection(); | ||||||
|  | 				if (connection != null && connection.getFeatures().csi()) { | ||||||
|  | 					connection.sendActive(); | ||||||
|  | 					Log.d(LOGTAG, account.getJid() + " sending csi//active"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	private void switchToBackground() { | ||||||
|  | 		for (Account account : getAccounts()) { | ||||||
|  | 			if (account.getStatus() == Account.STATUS_ONLINE) { | ||||||
|  | 				XmppConnection connection = account.getXmppConnection(); | ||||||
|  | 				if (connection != null && connection.getFeatures().csi()) { | ||||||
|  | 					connection.sendInactive(); | ||||||
|  | 					Log.d(LOGTAG, account.getJid() + " sending csi//inactive"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void connectMultiModeConversations(Account account) { | 	public void connectMultiModeConversations(Account account) { | ||||||
| @ -958,7 +1040,8 @@ public class XmppConnectionService extends Service { | |||||||
| 		account.pendingConferenceJoins.remove(conversation); | 		account.pendingConferenceJoins.remove(conversation); | ||||||
| 		account.pendingConferenceLeaves.remove(conversation); | 		account.pendingConferenceLeaves.remove(conversation); | ||||||
| 		if (account.getStatus() == Account.STATUS_ONLINE) { | 		if (account.getStatus() == Account.STATUS_ONLINE) { | ||||||
| 			Log.d(LOGTAG,"joining conversation "+conversation.getContactJid()); | 			Log.d(LOGTAG, | ||||||
|  | 					"joining conversation " + conversation.getContactJid()); | ||||||
| 			String nick = conversation.getMucOptions().getProposedNick(); | 			String nick = conversation.getMucOptions().getProposedNick(); | ||||||
| 			conversation.getMucOptions().setJoinNick(nick); | 			conversation.getMucOptions().setJoinNick(nick); | ||||||
| 			PresencePacket packet = new PresencePacket(); | 			PresencePacket packet = new PresencePacket(); | ||||||
| @ -975,8 +1058,8 @@ public class XmppConnectionService extends Service { | |||||||
| 				final SimpleDateFormat mDateFormat = new SimpleDateFormat( | 				final SimpleDateFormat mDateFormat = new SimpleDateFormat( | ||||||
| 						"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); | 						"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); | ||||||
| 				mDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); | 				mDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); | ||||||
| 				Date date = new Date( | 				Date date = new Date(conversation.getLatestMessage() | ||||||
| 						conversation.getLatestMessage().getTimeSent() + 1000); | 						.getTimeSent() + 1000); | ||||||
| 				x.addChild("history").setAttribute("since", | 				x.addChild("history").setAttribute("since", | ||||||
| 						mDateFormat.format(date)); | 						mDateFormat.format(date)); | ||||||
| 			} | 			} | ||||||
| @ -1011,7 +1094,8 @@ public class XmppConnectionService extends Service { | |||||||
| 						renameListener.onRename(success); | 						renameListener.onRename(success); | ||||||
| 					} | 					} | ||||||
| 					if (success) { | 					if (success) { | ||||||
| 						conversation.setContactJid(conversation.getMucOptions().getJoinJid()); | 						conversation.setContactJid(conversation.getMucOptions() | ||||||
|  | 								.getJoinJid()); | ||||||
| 						databaseBackend.updateConversation(conversation); | 						databaseBackend.updateConversation(conversation); | ||||||
| 						Bookmark bookmark = conversation.getBookmark(); | 						Bookmark bookmark = conversation.getBookmark(); | ||||||
| 						if (bookmark != null) { | 						if (bookmark != null) { | ||||||
| @ -1058,7 +1142,8 @@ public class XmppConnectionService extends Service { | |||||||
| 			sendPresencePacket(conversation.getAccount(), packet); | 			sendPresencePacket(conversation.getAccount(), packet); | ||||||
| 			conversation.getMucOptions().setOffline(); | 			conversation.getMucOptions().setOffline(); | ||||||
| 			conversation.deregisterWithBookmark(); | 			conversation.deregisterWithBookmark(); | ||||||
| 			Log.d(LOGTAG,conversation.getAccount().getJid()+" leaving muc "+conversation.getContactJid()); | 			Log.d(LOGTAG, conversation.getAccount().getJid() + " leaving muc " | ||||||
|  | 					+ conversation.getContactJid()); | ||||||
| 		} else { | 		} else { | ||||||
| 			account.pendingConferenceLeaves.add(conversation); | 			account.pendingConferenceLeaves.add(conversation); | ||||||
| 		} | 		} | ||||||
| @ -1176,25 +1261,29 @@ public class XmppConnectionService extends Service { | |||||||
| 		Account account = contact.getAccount(); | 		Account account = contact.getAccount(); | ||||||
| 		if (account.getStatus() == Account.STATUS_ONLINE) { | 		if (account.getStatus() == Account.STATUS_ONLINE) { | ||||||
| 			boolean ask = contact.getOption(Contact.Options.ASKING); | 			boolean ask = contact.getOption(Contact.Options.ASKING); | ||||||
| 			boolean sendUpdates = contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST) | 			boolean sendUpdates = contact | ||||||
|  | 					.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST) | ||||||
| 					&& contact.getOption(Contact.Options.PREEMPTIVE_GRANT); | 					&& contact.getOption(Contact.Options.PREEMPTIVE_GRANT); | ||||||
| 			IqPacket iq = new IqPacket(IqPacket.TYPE_SET); | 			IqPacket iq = new IqPacket(IqPacket.TYPE_SET); | ||||||
| 			iq.query("jabber:iq:roster").addChild(contact.asElement()); | 			iq.query("jabber:iq:roster").addChild(contact.asElement()); | ||||||
| 			account.getXmppConnection().sendIqPacket(iq, null); | 			account.getXmppConnection().sendIqPacket(iq, null); | ||||||
| 			if (sendUpdates) { | 			if (sendUpdates) { | ||||||
| 				sendPresencePacket(account, mPresenceGenerator.sendPresenceUpdatesTo(contact)); | 				sendPresencePacket(account, | ||||||
|  | 						mPresenceGenerator.sendPresenceUpdatesTo(contact)); | ||||||
| 			} | 			} | ||||||
| 			if (ask) { | 			if (ask) { | ||||||
| 				sendPresencePacket(account, mPresenceGenerator.requestPresenceUpdatesFrom(contact)); | 				sendPresencePacket(account, | ||||||
|  | 						mPresenceGenerator.requestPresenceUpdatesFrom(contact)); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	 | 	public void publishAvatar(Account account, Uri image, | ||||||
| 	public void publishAvatar(Account account, Uri image, final UiCallback<Avatar> callback) { | 			final UiCallback<Avatar> callback) { | ||||||
| 		final Bitmap.CompressFormat format = Defaults.AVATAR_FORMAT; | 		final Bitmap.CompressFormat format = Defaults.AVATAR_FORMAT; | ||||||
| 		final int size = Defaults.AVATAR_SIZE; | 		final int size = Defaults.AVATAR_SIZE; | ||||||
| 		final Avatar avatar = getFileBackend().getPepAvatar(image, size, format); | 		final Avatar avatar = getFileBackend() | ||||||
|  | 				.getPepAvatar(image, size, format); | ||||||
| 		if (avatar != null) { | 		if (avatar != null) { | ||||||
| 			avatar.height = size; | 			avatar.height = size; | ||||||
| 			avatar.width = size; | 			avatar.width = size; | ||||||
| @ -1215,23 +1304,29 @@ public class XmppConnectionService extends Service { | |||||||
| 				@Override | 				@Override | ||||||
| 				public void onIqPacketReceived(Account account, IqPacket result) { | 				public void onIqPacketReceived(Account account, IqPacket result) { | ||||||
| 					if (result.getType() == IqPacket.TYPE_RESULT) { | 					if (result.getType() == IqPacket.TYPE_RESULT) { | ||||||
| 						IqPacket packet = XmppConnectionService.this.mIqGenerator.publishAvatarMetadata(avatar); | 						IqPacket packet = XmppConnectionService.this.mIqGenerator | ||||||
|  | 								.publishAvatarMetadata(avatar); | ||||||
| 						sendIqPacket(account, packet, new OnIqPacketReceived() { | 						sendIqPacket(account, packet, new OnIqPacketReceived() { | ||||||
| 
 | 
 | ||||||
| 							@Override | 							@Override | ||||||
| 							public void onIqPacketReceived(Account account, IqPacket result) { | 							public void onIqPacketReceived(Account account, | ||||||
|  | 									IqPacket result) { | ||||||
| 								if (result.getType() == IqPacket.TYPE_RESULT) { | 								if (result.getType() == IqPacket.TYPE_RESULT) { | ||||||
| 									if (account.setAvatar(avatar.getFilename())) { | 									if (account.setAvatar(avatar.getFilename())) { | ||||||
| 										databaseBackend.updateAccount(account); | 										databaseBackend.updateAccount(account); | ||||||
| 									} | 									} | ||||||
| 									callback.success(avatar); | 									callback.success(avatar); | ||||||
| 								} else { | 								} else { | ||||||
| 									callback.error(R.string.error_publish_avatar_server_reject, avatar); | 									callback.error( | ||||||
|  | 											R.string.error_publish_avatar_server_reject, | ||||||
|  | 											avatar); | ||||||
| 								} | 								} | ||||||
| 							} | 							} | ||||||
| 						}); | 						}); | ||||||
| 					} else { | 					} else { | ||||||
| 						callback.error(R.string.error_publish_avatar_server_reject, avatar); | 						callback.error( | ||||||
|  | 								R.string.error_publish_avatar_server_reject, | ||||||
|  | 								avatar); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			}); | 			}); | ||||||
| @ -1244,8 +1339,10 @@ public class XmppConnectionService extends Service { | |||||||
| 		fetchAvatar(account, avatar, null); | 		fetchAvatar(account, avatar, null); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void fetchAvatar(Account account, final Avatar avatar, final UiCallback<Avatar> callback) { | 	public void fetchAvatar(Account account, final Avatar avatar, | ||||||
| 		Log.d(LOGTAG,account.getJid()+": retrieving avatar for "+avatar.owner); | 			final UiCallback<Avatar> callback) { | ||||||
|  | 		Log.d(LOGTAG, account.getJid() + ": retrieving avatar for " | ||||||
|  | 				+ avatar.owner); | ||||||
| 		IqPacket packet = this.mIqGenerator.retrieveAvatar(avatar); | 		IqPacket packet = this.mIqGenerator.retrieveAvatar(avatar); | ||||||
| 		sendIqPacket(account, packet, new OnIqPacketReceived() { | 		sendIqPacket(account, packet, new OnIqPacketReceived() { | ||||||
| 
 | 
 | ||||||
| @ -1259,7 +1356,8 @@ public class XmppConnectionService extends Service { | |||||||
| 								databaseBackend.updateAccount(account); | 								databaseBackend.updateAccount(account); | ||||||
| 							} | 							} | ||||||
| 						} else { | 						} else { | ||||||
| 							Contact contact = account.getRoster().getContact(avatar.owner); | 							Contact contact = account.getRoster().getContact( | ||||||
|  | 									avatar.owner); | ||||||
| 							contact.setAvatar(avatar.getFilename()); | 							contact.setAvatar(avatar.getFilename()); | ||||||
| 						} | 						} | ||||||
| 						if (callback != null) { | 						if (callback != null) { | ||||||
| @ -1275,14 +1373,16 @@ public class XmppConnectionService extends Service { | |||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void checkForAvatar(Account account, final UiCallback<Avatar> callback) { | 	public void checkForAvatar(Account account, | ||||||
|  | 			final UiCallback<Avatar> callback) { | ||||||
| 		IqPacket packet = this.mIqGenerator.retrieveAvatarMetaData(null); | 		IqPacket packet = this.mIqGenerator.retrieveAvatarMetaData(null); | ||||||
| 		this.sendIqPacket(account, packet, new OnIqPacketReceived() { | 		this.sendIqPacket(account, packet, new OnIqPacketReceived() { | ||||||
| 
 | 
 | ||||||
| 			@Override | 			@Override | ||||||
| 			public void onIqPacketReceived(Account account, IqPacket packet) { | 			public void onIqPacketReceived(Account account, IqPacket packet) { | ||||||
| 				if (packet.getType() == IqPacket.TYPE_RESULT) { | 				if (packet.getType() == IqPacket.TYPE_RESULT) { | ||||||
| 					Element pubsub = packet.findChild("pubsub", "http://jabber.org/protocol/pubsub"); | 					Element pubsub = packet.findChild("pubsub", | ||||||
|  | 							"http://jabber.org/protocol/pubsub"); | ||||||
| 					if (pubsub != null) { | 					if (pubsub != null) { | ||||||
| 						Element items = pubsub.findChild("items"); | 						Element items = pubsub.findChild("items"); | ||||||
| 						if (items != null) { | 						if (items != null) { | ||||||
| @ -1350,6 +1450,18 @@ public class XmppConnectionService extends Service { | |||||||
| 		sendMessagePacket(conversation.getAccount(), packet); | 		sendMessagePacket(conversation.getAccount(), packet); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	public void resetSendingToWaiting(Account account) { | ||||||
|  | 		for (Conversation conversation : getConversations()) { | ||||||
|  | 			if (conversation.getAccount() == account) { | ||||||
|  | 				for (Message message : conversation.getMessages()) { | ||||||
|  | 					if (message.getStatus() == Message.STATUS_UNSEND) { | ||||||
|  | 						markMessage(message, Message.STATUS_WAITING); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public boolean markMessage(Account account, String recipient, String uuid, | 	public boolean markMessage(Account account, String recipient, String uuid, | ||||||
| 			int status) { | 			int status) { | ||||||
| 		for (Conversation conversation : getConversations()) { | 		for (Conversation conversation : getConversations()) { | ||||||
| @ -1438,7 +1550,8 @@ public class XmppConnectionService extends Service { | |||||||
| 		if (confirmMessages() && id != null) { | 		if (confirmMessages() && id != null) { | ||||||
| 			Account account = conversation.getAccount(); | 			Account account = conversation.getAccount(); | ||||||
| 			String to = conversation.getContactJid(); | 			String to = conversation.getContactJid(); | ||||||
| 			this.sendMessagePacket(conversation.getAccount(), mMessageGenerator.confirm(account, to, id)); | 			this.sendMessagePacket(conversation.getAccount(), | ||||||
|  | 					mMessageGenerator.confirm(account, to, id)); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -1521,7 +1634,8 @@ public class XmppConnectionService extends Service { | |||||||
| 		account.getXmppConnection().sendPresencePacket(packet); | 		account.getXmppConnection().sendPresencePacket(packet); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public void sendIqPacket(Account account, IqPacket packet, OnIqPacketReceived callback) { | 	public void sendIqPacket(Account account, IqPacket packet, | ||||||
|  | 			OnIqPacketReceived callback) { | ||||||
| 		account.getXmppConnection().sendIqPacket(packet, callback); | 		account.getXmppConnection().sendIqPacket(packet, callback); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -90,6 +90,10 @@ public class XmlReader { | |||||||
| 			throw new IOException("xml parser mishandled ArrayIndexOufOfBounds", e); | 			throw new IOException("xml parser mishandled ArrayIndexOufOfBounds", e); | ||||||
| 		} catch (StringIndexOutOfBoundsException e) { | 		} catch (StringIndexOutOfBoundsException e) { | ||||||
| 			throw new IOException("xml parser mishandled StringIndexOufOfBounds", e); | 			throw new IOException("xml parser mishandled StringIndexOufOfBounds", e); | ||||||
|  | 		} catch (NullPointerException e) { | ||||||
|  | 			throw new IOException("xml parser mishandled NullPointerException", e); | ||||||
|  | 		} catch (IndexOutOfBoundsException e) { | ||||||
|  | 			throw new IOException("xml parser mishandled IndexOutOfBound", e); | ||||||
| 		} | 		} | ||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -0,0 +1,7 @@ | |||||||
|  | package eu.siacs.conversations.xmpp; | ||||||
|  | 
 | ||||||
|  | import eu.siacs.conversations.entities.Account; | ||||||
|  | 
 | ||||||
|  | public interface OnMessageAcknowledged { | ||||||
|  | 	public void onMessageAcknowledged(Account account, String id); | ||||||
|  | } | ||||||
| @ -31,6 +31,7 @@ import android.os.PowerManager; | |||||||
| import android.os.PowerManager.WakeLock; | import android.os.PowerManager.WakeLock; | ||||||
| import android.os.SystemClock; | import android.os.SystemClock; | ||||||
| import android.util.Log; | import android.util.Log; | ||||||
|  | import android.util.SparseArray; | ||||||
| import eu.siacs.conversations.entities.Account; | import eu.siacs.conversations.entities.Account; | ||||||
| import eu.siacs.conversations.services.XmppConnectionService; | import eu.siacs.conversations.services.XmppConnectionService; | ||||||
| import eu.siacs.conversations.utils.CryptoHelper; | import eu.siacs.conversations.utils.CryptoHelper; | ||||||
| @ -47,6 +48,8 @@ import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; | |||||||
| import eu.siacs.conversations.xmpp.stanzas.IqPacket; | import eu.siacs.conversations.xmpp.stanzas.IqPacket; | ||||||
| import eu.siacs.conversations.xmpp.stanzas.MessagePacket; | import eu.siacs.conversations.xmpp.stanzas.MessagePacket; | ||||||
| import eu.siacs.conversations.xmpp.stanzas.PresencePacket; | import eu.siacs.conversations.xmpp.stanzas.PresencePacket; | ||||||
|  | import eu.siacs.conversations.xmpp.stanzas.csi.ActivePacket; | ||||||
|  | import eu.siacs.conversations.xmpp.stanzas.csi.InactivePacket; | ||||||
| import eu.siacs.conversations.xmpp.stanzas.streammgmt.AckPacket; | import eu.siacs.conversations.xmpp.stanzas.streammgmt.AckPacket; | ||||||
| import eu.siacs.conversations.xmpp.stanzas.streammgmt.EnablePacket; | import eu.siacs.conversations.xmpp.stanzas.streammgmt.EnablePacket; | ||||||
| import eu.siacs.conversations.xmpp.stanzas.streammgmt.RequestPacket; | import eu.siacs.conversations.xmpp.stanzas.streammgmt.RequestPacket; | ||||||
| @ -74,6 +77,7 @@ public class XmppConnection implements Runnable { | |||||||
| 
 | 
 | ||||||
| 	private String streamId = null; | 	private String streamId = null; | ||||||
| 	private int smVersion = 3; | 	private int smVersion = 3; | ||||||
|  | 	private SparseArray<String> messageReceipts = new SparseArray<String>(); | ||||||
| 	 | 	 | ||||||
| 	private boolean usingCompression = false; | 	private boolean usingCompression = false; | ||||||
| 
 | 
 | ||||||
| @ -98,6 +102,7 @@ public class XmppConnection implements Runnable { | |||||||
| 	private OnMessagePacketReceived messageListener = null; | 	private OnMessagePacketReceived messageListener = null; | ||||||
| 	private OnStatusChanged statusListener = null; | 	private OnStatusChanged statusListener = null; | ||||||
| 	private OnBindListener bindListener = null; | 	private OnBindListener bindListener = null; | ||||||
|  | 	private OnMessageAcknowledged acknowledgedListener = null; | ||||||
| 	private MemorizingTrustManager mMemorizingTrustManager; | 	private MemorizingTrustManager mMemorizingTrustManager; | ||||||
| 
 | 
 | ||||||
| 	public XmppConnection(Account account, XmppConnectionService service) { | 	public XmppConnection(Account account, XmppConnectionService service) { | ||||||
| @ -248,7 +253,6 @@ public class XmppConnection implements Runnable { | |||||||
| 						challange,mRandom)); | 						challange,mRandom)); | ||||||
| 				tagWriter.writeElement(response); | 				tagWriter.writeElement(response); | ||||||
| 			} else if (nextTag.isStart("enabled")) { | 			} else if (nextTag.isStart("enabled")) { | ||||||
| 				this.stanzasSent = 0; |  | ||||||
| 				Element enabled = tagReader.readElement(nextTag); | 				Element enabled = tagReader.readElement(nextTag); | ||||||
| 				if ("true".equals(enabled.getAttribute("resume"))) { | 				if ("true".equals(enabled.getAttribute("resume"))) { | ||||||
| 					this.streamId = enabled.getAttribute("id"); | 					this.streamId = enabled.getAttribute("id"); | ||||||
| @ -264,9 +268,27 @@ public class XmppConnection implements Runnable { | |||||||
| 				tagWriter.writeStanzaAsync(r); | 				tagWriter.writeStanzaAsync(r); | ||||||
| 			} else if (nextTag.isStart("resumed")) { | 			} else if (nextTag.isStart("resumed")) { | ||||||
| 				lastPaketReceived = SystemClock.elapsedRealtime(); | 				lastPaketReceived = SystemClock.elapsedRealtime(); | ||||||
|  | 				Element resumed = tagReader.readElement(nextTag); | ||||||
|  | 				String h = resumed.getAttribute("h"); | ||||||
|  | 				try { | ||||||
|  | 					int serverCount = Integer.parseInt(h); | ||||||
|  | 					if (serverCount!=stanzasSent) { | ||||||
|  | 						Log.d(LOGTAG,account.getJid() + ": session resumed with lost packages"); | ||||||
|  | 						stanzasSent = serverCount; | ||||||
|  | 					} else { | ||||||
| 						Log.d(LOGTAG, account.getJid() + ": session resumed"); | 						Log.d(LOGTAG, account.getJid() + ": session resumed"); | ||||||
| 				tagReader.readElement(nextTag); | 					} | ||||||
| 				sendPing(); | 					if (acknowledgedListener!=null) { | ||||||
|  | 						for(int i = 0; i < messageReceipts.size(); ++i) { | ||||||
|  | 							if (serverCount>=messageReceipts.keyAt(i)) { | ||||||
|  | 								acknowledgedListener.onMessageAcknowledged(account, messageReceipts.valueAt(i)); | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					messageReceipts.clear(); | ||||||
|  | 				} catch (NumberFormatException e) { | ||||||
|  | 					 | ||||||
|  | 				} | ||||||
| 				changeStatus(Account.STATUS_ONLINE); | 				changeStatus(Account.STATUS_ONLINE); | ||||||
| 			} else if (nextTag.isStart("r")) { | 			} else if (nextTag.isStart("r")) { | ||||||
| 				tagReader.readElement(nextTag); | 				tagReader.readElement(nextTag); | ||||||
| @ -276,8 +298,12 @@ public class XmppConnection implements Runnable { | |||||||
| 				Element ack = tagReader.readElement(nextTag); | 				Element ack = tagReader.readElement(nextTag); | ||||||
| 				lastPaketReceived = SystemClock.elapsedRealtime(); | 				lastPaketReceived = SystemClock.elapsedRealtime(); | ||||||
| 				int serverSequence = Integer.parseInt(ack.getAttribute("h")); | 				int serverSequence = Integer.parseInt(ack.getAttribute("h")); | ||||||
| 				if (serverSequence > this.stanzasSent) { | 				String msgId = this.messageReceipts.get(serverSequence); | ||||||
| 					this.stanzasSent = serverSequence; | 				if (msgId != null) { | ||||||
|  | 					if (this.acknowledgedListener != null) { | ||||||
|  | 						this.acknowledgedListener.onMessageAcknowledged(account, msgId); | ||||||
|  | 					} | ||||||
|  | 					this.messageReceipts.remove(serverSequence); | ||||||
| 				} | 				} | ||||||
| 			} else if (nextTag.isStart("failed")) { | 			} else if (nextTag.isStart("failed")) { | ||||||
| 				tagReader.readElement(nextTag); | 				tagReader.readElement(nextTag); | ||||||
| @ -610,10 +636,14 @@ public class XmppConnection implements Runnable { | |||||||
| 							smVersion = 3; | 							smVersion = 3; | ||||||
| 							EnablePacket enable = new EnablePacket(smVersion); | 							EnablePacket enable = new EnablePacket(smVersion); | ||||||
| 							tagWriter.writeStanzaAsync(enable); | 							tagWriter.writeStanzaAsync(enable); | ||||||
|  | 							stanzasSent = 0; | ||||||
|  | 							messageReceipts.clear(); | ||||||
| 						} else if (streamFeatures.hasChild("sm", "urn:xmpp:sm:2")) { | 						} else if (streamFeatures.hasChild("sm", "urn:xmpp:sm:2")) { | ||||||
| 							smVersion = 2; | 							smVersion = 2; | ||||||
| 							EnablePacket enable = new EnablePacket(smVersion); | 							EnablePacket enable = new EnablePacket(smVersion); | ||||||
| 							tagWriter.writeStanzaAsync(enable); | 							tagWriter.writeStanzaAsync(enable); | ||||||
|  | 							stanzasSent = 0; | ||||||
|  | 							messageReceipts.clear(); | ||||||
| 						} | 						} | ||||||
| 						sendServiceDiscoveryInfo(account.getServer()); | 						sendServiceDiscoveryInfo(account.getServer()); | ||||||
| 						sendServiceDiscoveryItems(account.getServer()); | 						sendServiceDiscoveryItems(account.getServer()); | ||||||
| @ -751,9 +781,15 @@ public class XmppConnection implements Runnable { | |||||||
| 	 | 	 | ||||||
| 	private synchronized void sendPacket(final AbstractStanza packet, | 	private synchronized void sendPacket(final AbstractStanza packet, | ||||||
| 			PacketReceived callback) { | 			PacketReceived callback) { | ||||||
| 		// TODO dont increment stanza count if packet = request packet or ack; | 		if (packet.getName().equals("iq") || packet.getName().equals("message") || packet.getName().equals("presence")) { | ||||||
| 			++stanzasSent; | 			++stanzasSent; | ||||||
|  | 		} | ||||||
| 		tagWriter.writeStanzaAsync(packet); | 		tagWriter.writeStanzaAsync(packet); | ||||||
|  | 		if (packet instanceof MessagePacket && packet.getId() != null && this.streamId != null) { | ||||||
|  | 			Log.d(LOGTAG,"request delivery report for stanza "+stanzasSent); | ||||||
|  | 			this.messageReceipts.put(stanzasSent, packet.getId()); | ||||||
|  | 			tagWriter.writeStanzaAsync(new RequestPacket(this.smVersion)); | ||||||
|  | 		} | ||||||
| 		if (callback != null) { | 		if (callback != null) { | ||||||
| 			if (packet.getId() == null) { | 			if (packet.getId() == null) { | ||||||
| 				packet.setId(nextRandomId()); | 				packet.setId(nextRandomId()); | ||||||
| @ -802,6 +838,10 @@ public class XmppConnection implements Runnable { | |||||||
| 		this.bindListener = listener; | 		this.bindListener = listener; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
|  | 	public void setOnMessageAcknowledgeListener(OnMessageAcknowledged listener) { | ||||||
|  | 		this.acknowledgedListener = listener; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public void disconnect(boolean force) { | 	public void disconnect(boolean force) { | ||||||
| 		changeStatus(Account.STATUS_OFFLINE); | 		changeStatus(Account.STATUS_OFFLINE); | ||||||
| 		Log.d(LOGTAG, "disconnecting"); | 		Log.d(LOGTAG, "disconnecting"); | ||||||
| @ -900,6 +940,14 @@ public class XmppConnection implements Runnable { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
|  | 		public boolean csi() { | ||||||
|  | 			if (connection.streamFeatures == null) { | ||||||
|  | 				return false; | ||||||
|  | 			} else { | ||||||
|  | 				return connection.streamFeatures.hasChild("csi","urn:xmpp:csi:0"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
| 		public boolean pubsub() { | 		public boolean pubsub() { | ||||||
| 			return hasDiscoFeature(account.getServer(), "http://jabber.org/protocol/pubsub#publish"); | 			return hasDiscoFeature(account.getServer(), "http://jabber.org/protocol/pubsub#publish"); | ||||||
| 		} | 		} | ||||||
| @ -942,4 +990,12 @@ public class XmppConnection implements Runnable { | |||||||
| 	public long getLastPacketReceived() { | 	public long getLastPacketReceived() { | ||||||
| 		return this.lastPaketReceived; | 		return this.lastPaketReceived; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	public void sendActive() { | ||||||
|  | 		this.sendPacket(new ActivePacket(), null); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	public void sendInactive() { | ||||||
|  | 		this.sendPacket(new InactivePacket(), null); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,10 @@ | |||||||
|  | package eu.siacs.conversations.xmpp.stanzas.csi; | ||||||
|  | 
 | ||||||
|  | import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; | ||||||
|  | 
 | ||||||
|  | public class ActivePacket extends AbstractStanza { | ||||||
|  | 	public ActivePacket() { | ||||||
|  | 		super("active"); | ||||||
|  | 		setAttribute("xmlns", "urn:xmpp:csi:0"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -0,0 +1,10 @@ | |||||||
|  | package eu.siacs.conversations.xmpp.stanzas.csi; | ||||||
|  | 
 | ||||||
|  | import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; | ||||||
|  | 
 | ||||||
|  | public class InactivePacket extends AbstractStanza { | ||||||
|  | 	public InactivePacket() { | ||||||
|  | 		super("inactive"); | ||||||
|  | 		setAttribute("xmlns", "urn:xmpp:csi:0"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Michael
						Michael