diff --git a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
index b72a0276b3766204fe8518159fcddf55b17d26cb..9e46afac57f2f8d3a691549d71f4a41215bba8f5 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
@@ -31,6 +31,8 @@ import org.briarproject.api.db.DbException;
 import org.briarproject.api.db.MessageHeader;
 import org.briarproject.api.db.NoSuchContactException;
 import org.briarproject.api.event.ContactAddedEvent;
+import org.briarproject.api.event.ContactConnectedEvent;
+import org.briarproject.api.event.ContactDisconnectedEvent;
 import org.briarproject.api.event.ContactRemovedEvent;
 import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
@@ -38,7 +40,6 @@ import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.MessageAddedEvent;
 import org.briarproject.api.event.MessageExpiredEvent;
 import org.briarproject.api.messaging.GroupId;
-import org.briarproject.api.transport.ConnectionListener;
 import org.briarproject.api.transport.ConnectionRegistry;
 
 import android.content.Intent;
@@ -61,7 +62,7 @@ import android.widget.Toast;
 
 public class ContactListActivity extends BriarActivity
 implements OnClickListener, OnItemClickListener, OnCreateContextMenuListener,
-EventListener, ConnectionListener {
+EventListener {
 
 	private static final int MENU_ITEM_DELETE = 1;
 	private static final Logger LOG =
@@ -128,7 +129,6 @@ EventListener, ConnectionListener {
 	public void onResume() {
 		super.onResume();
 		eventBus.addListener(this);
-		connectionRegistry.addListener(this);
 		loadContacts();
 	}
 
@@ -213,7 +213,6 @@ EventListener, ConnectionListener {
 	public void onPause() {
 		super.onPause();
 		eventBus.removeListener(this);
-		connectionRegistry.removeListener(this);
 	}
 
 	public void onClick(View view) {
@@ -271,6 +270,10 @@ EventListener, ConnectionListener {
 	public void eventOccurred(Event e) {
 		if(e instanceof ContactAddedEvent) {
 			loadContacts();
+		} else if(e instanceof ContactConnectedEvent) {
+			setConnected(((ContactConnectedEvent) e).getContactId(), true);
+		} else if(e instanceof ContactDisconnectedEvent) {
+			setConnected(((ContactDisconnectedEvent) e).getContactId(), false);
 		} else if(e instanceof ContactRemovedEvent) {
 			LOG.info("Contact removed");
 			removeItem(((ContactRemovedEvent) e).getContactId());
@@ -335,14 +338,6 @@ EventListener, ConnectionListener {
 		});
 	}
 
-	public void contactConnected(ContactId c) {
-		setConnected(c, true);
-	}
-
-	public void contactDisconnected(ContactId c) {
-		setConnected(c, false);
-	}
-
 	private void setConnected(final ContactId c, final boolean connected) {
 		runOnUiThread(new Runnable() {
 			public void run() {
diff --git a/briar-api/src/org/briarproject/api/event/ContactConnectedEvent.java b/briar-api/src/org/briarproject/api/event/ContactConnectedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..42c8bf7b820c44ae900690f050b605ea16e168b6
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/event/ContactConnectedEvent.java
@@ -0,0 +1,20 @@
+package org.briarproject.api.event;
+
+import org.briarproject.api.ContactId;
+
+/**
+ * An event that is broadcast when a contact connects that was not previously
+ * connected via any transport.
+ */
+public class ContactConnectedEvent extends Event {
+
+	private final ContactId contactId;
+
+	public ContactConnectedEvent(ContactId contactId) {
+		this.contactId = contactId;
+	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/event/ContactDisconnectedEvent.java b/briar-api/src/org/briarproject/api/event/ContactDisconnectedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0f858dfd1fd1972a4985497fb8bdc3b82a03ea1
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/event/ContactDisconnectedEvent.java
@@ -0,0 +1,20 @@
+package org.briarproject.api.event;
+
+import org.briarproject.api.ContactId;
+
+/**
+ * An event that is broadcast when a contact disconnects and is no longer
+ * connected via any transport.
+ */
+public class ContactDisconnectedEvent extends Event {
+
+	private final ContactId contactId;
+
+	public ContactDisconnectedEvent(ContactId contactId) {
+		this.contactId = contactId;
+	}
+
+	public ContactId getContactId() {
+		return contactId;
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/transport/ConnectionListener.java b/briar-api/src/org/briarproject/api/transport/ConnectionListener.java
deleted file mode 100644
index 33052565bc42631e44562864df904db41fabe5d2..0000000000000000000000000000000000000000
--- a/briar-api/src/org/briarproject/api/transport/ConnectionListener.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.api.transport;
-
-import org.briarproject.api.ContactId;
-
-/** An interface for listening for connection and disconnection events. */
-public interface ConnectionListener {
-
-	/** Called when a contact connects and has no existing connections. */
-	void contactConnected(ContactId c);
-
-	/** Called when a contact disconnects and has no remaining connections. */
-	void contactDisconnected(ContactId c);
-}
diff --git a/briar-api/src/org/briarproject/api/transport/ConnectionRegistry.java b/briar-api/src/org/briarproject/api/transport/ConnectionRegistry.java
index 270ea4b640d874896cbff7000abb24f48d4e8a6b..91a5a3da45b96a60321069008a92c55b06f9127f 100644
--- a/briar-api/src/org/briarproject/api/transport/ConnectionRegistry.java
+++ b/briar-api/src/org/briarproject/api/transport/ConnectionRegistry.java
@@ -10,10 +10,6 @@ import org.briarproject.api.TransportId;
  */
 public interface ConnectionRegistry {
 
-	void addListener(ConnectionListener c);
-
-	void removeListener(ConnectionListener c);
-
 	void registerConnection(ContactId c, TransportId t);
 
 	void unregisterConnection(ContactId c, TransportId t);
diff --git a/briar-core/src/org/briarproject/transport/ConnectionRegistryImpl.java b/briar-core/src/org/briarproject/transport/ConnectionRegistryImpl.java
index 94a2b93ea422f776c28fda6d2f631b7d85f05722..2e7485faa5ce86d563a9bb38dbb98100dff9e5c6 100644
--- a/briar-core/src/org/briarproject/transport/ConnectionRegistryImpl.java
+++ b/briar-core/src/org/briarproject/transport/ConnectionRegistryImpl.java
@@ -8,37 +8,33 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.logging.Logger;
 
 import org.briarproject.api.ContactId;
 import org.briarproject.api.TransportId;
-import org.briarproject.api.transport.ConnectionListener;
+import org.briarproject.api.event.ContactConnectedEvent;
+import org.briarproject.api.event.ContactDisconnectedEvent;
+import org.briarproject.api.event.EventBus;
 import org.briarproject.api.transport.ConnectionRegistry;
 
+import com.google.inject.Inject;
+
 class ConnectionRegistryImpl implements ConnectionRegistry {
 
 	private static final Logger LOG =
 			Logger.getLogger(ConnectionRegistryImpl.class.getName());
 
+	private final EventBus eventBus;
 	// Locking: this
 	private final Map<TransportId, Map<ContactId, Integer>> connections;
 	// Locking: this
 	private final Map<ContactId, Integer> contactCounts;
-	private final List<ConnectionListener> listeners;
 
-	ConnectionRegistryImpl() {
+	@Inject
+	ConnectionRegistryImpl(EventBus eventBus) {
+		this.eventBus = eventBus;
 		connections = new HashMap<TransportId, Map<ContactId, Integer>>();
 		contactCounts = new HashMap<ContactId, Integer>();
-		listeners = new CopyOnWriteArrayList<ConnectionListener>();
-	}
-
-	public void addListener(ConnectionListener c) {
-		listeners.add(c);
-	}
-
-	public void removeListener(ConnectionListener c) {
-		listeners.remove(c);
 	}
 
 	public void registerConnection(ContactId c, TransportId t) {
@@ -63,7 +59,7 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
 		}
 		if(firstConnection) {
 			LOG.info("Contact connected");
-			for(ConnectionListener l : listeners) l.contactConnected(c);
+			eventBus.broadcast(new ContactConnectedEvent(c));
 		}
 	}
 
@@ -91,7 +87,7 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
 		}
 		if(lastConnection) {
 			LOG.info("Contact disconnected");
-			for(ConnectionListener l : listeners) l.contactDisconnected(c);
+			eventBus.broadcast(new ContactDisconnectedEvent(c));
 		}
 	}
 
diff --git a/briar-core/src/org/briarproject/transport/TransportModule.java b/briar-core/src/org/briarproject/transport/TransportModule.java
index 3fec3a8068125b97a06ac2885f1bf7aa68c340b5..6ac7a15c939dbfc2b8ab4afd72222a1f2bee2bdc 100644
--- a/briar-core/src/org/briarproject/transport/TransportModule.java
+++ b/briar-core/src/org/briarproject/transport/TransportModule.java
@@ -22,9 +22,10 @@ public class TransportModule extends AbstractModule {
 				ConnectionReaderFactoryImpl.class);
 		bind(ConnectionRecogniser.class).to(
 				ConnectionRecogniserImpl.class).in(Singleton.class);
-		bind(ConnectionRegistry.class).toInstance(new ConnectionRegistryImpl());
-		bind(ConnectionWriterFactory.class).to(
-				ConnectionWriterFactoryImpl.class);
+		bind(ConnectionRegistry.class).to(
+				ConnectionRegistryImpl.class).in(Singleton.class);;
+				bind(ConnectionWriterFactory.class).to(
+						ConnectionWriterFactoryImpl.class);
 	}
 
 	@Provides @Singleton
diff --git a/briar-tests/src/org/briarproject/transport/ConnectionRegistryImplTest.java b/briar-tests/src/org/briarproject/transport/ConnectionRegistryImplTest.java
index a6786db67809b0f6e911d24a69cc3c95250f3951..58a12f437ff273a50e317d7856cad4b36f740fd5 100644
--- a/briar-tests/src/org/briarproject/transport/ConnectionRegistryImplTest.java
+++ b/briar-tests/src/org/briarproject/transport/ConnectionRegistryImplTest.java
@@ -7,7 +7,12 @@ import java.util.Collections;
 import org.briarproject.BriarTestCase;
 import org.briarproject.api.ContactId;
 import org.briarproject.api.TransportId;
+import org.briarproject.api.event.ContactConnectedEvent;
+import org.briarproject.api.event.ContactDisconnectedEvent;
+import org.briarproject.api.event.EventBus;
 import org.briarproject.api.transport.ConnectionRegistry;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
 import org.junit.Test;
 
 public class ConnectionRegistryImplTest extends BriarTestCase {
@@ -24,13 +29,24 @@ public class ConnectionRegistryImplTest extends BriarTestCase {
 
 	@Test
 	public void testRegisterAndUnregister() {
-		ConnectionRegistry c = new ConnectionRegistryImpl();
+		Mockery context = new Mockery();
+		final EventBus eventBus = context.mock(EventBus.class);
+		context.checking(new Expectations() {{
+			exactly(3).of(eventBus).broadcast(with(any(
+					ContactConnectedEvent.class)));
+			oneOf(eventBus).broadcast(with(any(
+					ContactDisconnectedEvent.class)));
+		}});
+
+		ConnectionRegistry c = new ConnectionRegistryImpl(eventBus);
+
 		// The registry should be empty
 		assertEquals(Collections.emptyList(),
 				c.getConnectedContacts(transportId));
 		assertEquals(Collections.emptyList(),
 				c.getConnectedContacts(transportId1));
-		// Check that a registered connection shows up
+		// Check that a registered connection shows up - this should
+		// broadcast a ContactConnectedEvent
 		c.registerConnection(contactId, transportId);
 		assertEquals(Arrays.asList(contactId),
 				c.getConnectedContacts(transportId));
@@ -48,7 +64,8 @@ public class ConnectionRegistryImplTest extends BriarTestCase {
 				c.getConnectedContacts(transportId));
 		assertEquals(Collections.emptyList(),
 				c.getConnectedContacts(transportId1));
-		// Unregister the other connection - lookup should be affected
+		// Unregister the other connection - lookup should be affected -
+		// this should broadcast a ContactDisconnectedEvent
 		c.unregisterConnection(contactId, transportId);
 		assertEquals(Collections.emptyList(),
 				c.getConnectedContacts(transportId));
@@ -59,7 +76,8 @@ public class ConnectionRegistryImplTest extends BriarTestCase {
 			c.unregisterConnection(contactId, transportId);
 			fail();
 		} catch(IllegalArgumentException expected) {}
-		// Register both contacts with one transport, one contact with both
+		// Register both contacts with one transport, one contact with both -
+		// this should broadcast two ContactConnectedEvents
 		c.registerConnection(contactId, transportId);
 		c.registerConnection(contactId1, transportId);
 		c.registerConnection(contactId1, transportId1);
@@ -69,5 +87,6 @@ public class ConnectionRegistryImplTest extends BriarTestCase {
 		assertTrue(connected.contains(contactId1));
 		assertEquals(Arrays.asList(contactId1),
 				c.getConnectedContacts(transportId1));
+		context.assertIsSatisfied();
 	}
 }