diff --git a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
index 79188325459bfcc0ae347f82f233eb40e653cacd..6817730efad203890c0345c61437090378dce9bd 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
@@ -3,6 +3,7 @@ package org.briarproject.android.contact;
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.design.widget.FloatingActionButton;
+import android.support.v7.util.SortedList;
 import android.support.v7.widget.LinearLayoutManager;
 import android.view.View;
 
@@ -134,7 +135,21 @@ public class ContactListActivity extends BriarActivity
 		runOnUiThread(new Runnable() {
 			public void run() {
 				if (contacts.size() > 0) {
-					adapter.addAll(contacts);
+					if (adapter.getItemCount() > 0) {
+						// update existing items rather than just adding them,
+						// because different timestamps in added items change
+						// sorting criteria and cause duplicates
+						for (ContactListItem contact : contacts) {
+							int position = adapter.findItemPosition(contact);
+							if (position == SortedList.INVALID_POSITION) {
+								adapter.add(contact);
+							} else {
+								adapter.updateItem(position, contact);
+							}
+						}
+					} else {
+						adapter.addAll(contacts);
+					}
 				} else {
 					// no contacts to display, make sure progress bar is hidden
 					list.showData();
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java b/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java
index 2abe5e6ffcf4d6d40c279c976108060c1e98624e..970461d7088740c284a4e69016f907298bcb35b4 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListAdapter.java
@@ -60,13 +60,25 @@ public class ContactListAdapter
 						@Override
 						public boolean areItemsTheSame(ContactListItem c1,
 								ContactListItem c2) {
-							return c1.getContact().getId().equals(c2.getContact().getId());
+							return c1.getContact().getId()
+									.equals(c2.getContact().getId());
 						}
 
 						@Override
 						public boolean areContentsTheSame(ContactListItem c1,
 								ContactListItem c2) {
-							return c1.equals(c2);
+							// check for all properties that influence visual
+							// representation of contact
+							if (c1.isConnected() != c2.isConnected()) {
+								return false;
+							}
+							if (c1.getUnreadCount() != c2.getUnreadCount()) {
+								return false;
+							}
+							if (c1.getTimestamp() != c2.getTimestamp()) {
+								return false;
+							}
+							return true;
 						}
 					});
 	private Context ctx;
@@ -144,7 +156,8 @@ public class ContactListAdapter
 	}
 
 	public ContactListItem getItem(int position) {
-		if (position == -1 || contacts.size() <= position) {
+		if (position == SortedList.INVALID_POSITION ||
+				contacts.size() <= position) {
 			return null; // Not found
 		}
 		return contacts.get(position);
@@ -163,13 +176,17 @@ public class ContactListAdapter
 		return null; // Not found
 	}
 
+	public int findItemPosition(ContactListItem item) {
+		return contacts.indexOf(item);
+	}
+
 	public int findItemPosition(ContactId c) {
 		int count = getItemCount();
 		for (int i = 0; i < count; i++) {
 			ContactListItem item = getItem(i);
 			if (item.getContact().getId().equals(c)) return i;
 		}
-		return -1; // Not found
+		return SortedList.INVALID_POSITION; // Not found
 	}
 
 	public void addAll(final List<ContactListItem> contacts) {