From 1be400eb84c5dcff00bc5df1e7af5e20d991cfb4 Mon Sep 17 00:00:00 2001
From: Ernir Erlingsson <ernir@ymirmobile.com>
Date: Thu, 3 Mar 2016 10:24:40 +0100
Subject: [PATCH] Switched Roboguice/Guice out for Dagger 2

---
 briar-android-tests/.gitignore                |   5 +
 briar-android-tests/build.gradle              |  39 +++++
 briar-android-tests/proguard-rules.pro        |  17 ++
 .../briar_android_tests/ApplicationTest.java  |  13 ++
 .../src/main/AndroidManifest.xml              |  12 ++
 .../src/main/res/values/strings.xml           |   3 +
 .../protocol}/ProtocolIntegrationTest.java    |  58 ++++---
 .../protocol/ProtocolTestComponent.java       |  26 +++
 .../briarproject/sync/ConstantsComponent.java |  28 ++++
 .../org/briarproject/sync/ConstantsTest.java  |  56 +++----
 .../sync/SimplexMessagingComponent.java       |  54 +++++++
 .../sync/SimplexMessagingIntegrationTest.java | 133 ++++++---------
 briar-android/build.gradle                    |   9 +-
 briar-android/proguard-rules.txt              |   7 +-
 .../identicons/AsymmetricIdenticon.java       |   5 +-
 .../identicons/SymmetricIdenticon.java        |   5 +-
 .../android/AndroidComponent.java             |  70 ++++++++
 .../briarproject/android/AndroidModule.java   |  46 ++++--
 .../org/briarproject/android/AppModule.java   |  25 +++
 .../briarproject/android/BaseActivity.java    | 108 +------------
 .../briarproject/android/BriarActivity.java   |  14 +-
 .../android/BriarApplication.java             |  11 ++
 .../briarproject/android/BriarService.java    |  15 +-
 .../android/NavDrawerActivity.java            |  46 +++---
 .../android/PasswordActivity.java             |  17 +-
 .../briarproject/android/SetupActivity.java   |  48 ++++--
 .../android/SplashScreenActivity.java         |  61 +++----
 .../android/StartupFailureActivity.java       |   5 +
 .../briarproject/android/TestingActivity.java |  11 +-
 .../android/contact/ContactListFragment.java  |  22 ++-
 .../android/contact/ConversationActivity.java |  22 ++-
 .../forum/AvailableForumsActivity.java        |  12 +-
 .../android/forum/CreateForumActivity.java    |   8 +-
 .../android/forum/ForumActivity.java          |  12 +-
 .../android/forum/ForumListFragment.java      |  10 +-
 .../android/forum/ReadForumPostActivity.java  |   8 +-
 .../android/forum/ShareForumActivity.java     |  10 +-
 .../android/forum/WriteForumPostActivity.java |  16 +-
 .../android/fragment/BaseFragment.java        |  23 ++-
 .../android/fragment/DashboardFragment.java   |  13 +-
 .../identity/CreateIdentityActivity.java      |  14 +-
 .../invitation/AddContactActivity.java        |  14 +-
 .../invitation/ChooseIdentityView.java        |   7 +-
 .../android/panic/ExitActivity.java           |   6 +
 .../panic/PanicPreferencesActivity.java       |   6 +
 .../android/panic/PanicResponderActivity.java |  16 +-
 .../briarproject/android/util/AuthorView.java |   4 +-
 .../plugins/AndroidPluginsModule.java         |   5 +-
 .../system/AndroidLocationUtils.java          |   4 +-
 .../system/AndroidSystemModule.java           |  33 +++-
 briar-api/build.gradle                        |  14 +-
 .../api/crypto/CryptoExecutor.java            |  14 +-
 .../briarproject/api/db/DatabaseExecutor.java |   4 +-
 .../api/lifecycle/IoExecutor.java             |   4 +-
 .../contact/ContactManagerImpl.java           |  17 +-
 .../briarproject/contact/ContactModule.java   |  18 ++-
 .../org/briarproject/crypto/CryptoModule.java |  56 +++++--
 .../src/org/briarproject/data/DataModule.java |  32 +++-
 .../org/briarproject/db/DatabaseModule.java   |  24 +--
 .../org/briarproject/event/EventModule.java   |  16 +-
 .../briarproject/forum/ForumManagerImpl.java  | 153 +++++++++++++-----
 .../org/briarproject/forum/ForumModule.java   |  72 ++++++---
 .../forum/ForumSharingManagerImpl.java        |   8 +-
 .../identity/IdentityManagerImpl.java         |  16 +-
 .../briarproject/identity/IdentityModule.java |  25 ++-
 .../invitation/InvitationModule.java          |  37 ++++-
 .../lifecycle/LifecycleModule.java            |  32 ++--
 .../messaging/MessagingManagerImpl.java       | 130 +++++++++++----
 .../messaging/MessagingModule.java            |  32 ++--
 .../plugins/ConnectionRegistryImpl.java       |   4 +-
 .../briarproject/plugins/PluginsModule.java   |  52 ++++--
 .../properties/PropertiesModule.java          |  21 ++-
 .../TransportPropertyManagerImpl.java         | 147 +++++++++++------
 .../reliability/ReliabilityModule.java        |  28 +++-
 .../settings/SettingsManagerImpl.java         |   3 +-
 .../briarproject/settings/SettingsModule.java |  16 +-
 .../briarproject/sync/MessageFactoryImpl.java |   3 +-
 .../src/org/briarproject/sync/SyncModule.java |  78 +++++++--
 .../sync/ValidationManagerImpl.java           |   4 +-
 .../transport/TransportModule.java            |  28 ++--
 .../lifecycle/DesktopLifecycleModule.java     |   4 +-
 .../plugins/DesktopPluginsModule.java         |   6 +-
 .../system/DesktopSystemModule.java           |   7 +-
 briar-tests/build.gradle                      |   1 -
 .../org/briarproject/TestDatabaseModule.java  |  14 +-
 .../org/briarproject/TestLifecycleModule.java |  67 +++++---
 .../org/briarproject/TestSystemModule.java    |  25 ++-
 build.gradle                                  |   4 +
 settings.gradle                               |   2 +-
 89 files changed, 1634 insertions(+), 796 deletions(-)
 create mode 100644 briar-android-tests/.gitignore
 create mode 100644 briar-android-tests/build.gradle
 create mode 100644 briar-android-tests/proguard-rules.pro
 create mode 100644 briar-android-tests/src/androidTest/java/com/ymirmobile/briar_android_tests/ApplicationTest.java
 create mode 100644 briar-android-tests/src/main/AndroidManifest.xml
 create mode 100644 briar-android-tests/src/main/res/values/strings.xml
 rename {briar-tests/src/org/briarproject => briar-android-tests/src/test/java/org/briarproject/protocol}/ProtocolIntegrationTest.java (79%)
 create mode 100644 briar-android-tests/src/test/java/org/briarproject/protocol/ProtocolTestComponent.java
 create mode 100644 briar-android-tests/src/test/java/org/briarproject/sync/ConstantsComponent.java
 rename {briar-tests/src => briar-android-tests/src/test/java}/org/briarproject/sync/ConstantsTest.java (76%)
 create mode 100644 briar-android-tests/src/test/java/org/briarproject/sync/SimplexMessagingComponent.java
 rename {briar-tests/src => briar-android-tests/src/test/java}/org/briarproject/sync/SimplexMessagingIntegrationTest.java (66%)
 create mode 100644 briar-android/src/org/briarproject/android/AndroidComponent.java
 create mode 100644 briar-android/src/org/briarproject/android/AppModule.java

diff --git a/briar-android-tests/.gitignore b/briar-android-tests/.gitignore
new file mode 100644
index 0000000000..216c35063e
--- /dev/null
+++ b/briar-android-tests/.gitignore
@@ -0,0 +1,5 @@
+bin
+gen
+build
+local.properties
+.settings
diff --git a/briar-android-tests/build.gradle b/briar-android-tests/build.gradle
new file mode 100644
index 0000000000..858711df47
--- /dev/null
+++ b/briar-android-tests/build.gradle
@@ -0,0 +1,39 @@
+apply plugin: 'com.android.library'
+sourceCompatibility = 1.6
+targetCompatibility = 1.6
+apply plugin: 'witness'
+apply plugin: 'com.neenbedankt.android-apt'
+
+repositories {
+    maven { url 'http://repo1.maven.org/maven2' }
+}
+
+android {
+    compileSdkVersion 23
+    buildToolsVersion "23.0.2"
+
+    defaultConfig {
+        minSdkVersion 10
+        targetSdkVersion 23
+        versionCode 1
+        versionName "1.0"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    compile project(':briar-api')
+    compile project(':briar-core')
+    testCompile 'junit:junit:4.12'
+    compile 'com.android.support:appcompat-v7:23.2.0'
+    testApt 'com.google.dagger:dagger-compiler:2.0.2'
+    provided 'javax.annotation:jsr250-api:1.0'
+    compile 'cglib:cglib-nodep:3.1'
+    testCompile project(':briar-tests')
+}
diff --git a/briar-android-tests/proguard-rules.pro b/briar-android-tests/proguard-rules.pro
new file mode 100644
index 0000000000..2106d3d2c9
--- /dev/null
+++ b/briar-android-tests/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /home/ernir/dev/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/briar-android-tests/src/androidTest/java/com/ymirmobile/briar_android_tests/ApplicationTest.java b/briar-android-tests/src/androidTest/java/com/ymirmobile/briar_android_tests/ApplicationTest.java
new file mode 100644
index 0000000000..9d2a221d17
--- /dev/null
+++ b/briar-android-tests/src/androidTest/java/com/ymirmobile/briar_android_tests/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.ymirmobile.briar_android_tests;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
+ */
+public class ApplicationTest extends ApplicationTestCase<Application> {
+	public ApplicationTest() {
+		super(Application.class);
+	}
+}
\ No newline at end of file
diff --git a/briar-android-tests/src/main/AndroidManifest.xml b/briar-android-tests/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..a152a552bc
--- /dev/null
+++ b/briar-android-tests/src/main/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<manifest package="org.briarproject"
+          xmlns:android="http://schemas.android.com/apk/res/android">
+
+	<application
+		android:allowBackup="true"
+		android:label="@string/app_name"
+		android:supportsRtl="true"
+		>
+
+	</application>
+
+</manifest>
diff --git a/briar-android-tests/src/main/res/values/strings.xml b/briar-android-tests/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..71b096466a
--- /dev/null
+++ b/briar-android-tests/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+	<string name="app_name">briar-android-tests</string>
+</resources>
diff --git a/briar-tests/src/org/briarproject/ProtocolIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/protocol/ProtocolIntegrationTest.java
similarity index 79%
rename from briar-tests/src/org/briarproject/ProtocolIntegrationTest.java
rename to briar-android-tests/src/test/java/org/briarproject/protocol/ProtocolIntegrationTest.java
index e8c939d4cf..cc36c199dd 100644
--- a/briar-tests/src/org/briarproject/ProtocolIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/protocol/ProtocolIntegrationTest.java
@@ -1,8 +1,7 @@
-package org.briarproject;
-
-import com.google.inject.Guice;
-import com.google.inject.Injector;
+package org.briarproject.protocol;
 
+import org.briarproject.BriarTestCase;
+import org.briarproject.TestUtils;
 import org.briarproject.api.TransportId;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.crypto.SecretKey;
@@ -22,14 +21,15 @@ import org.briarproject.api.sync.Request;
 import org.briarproject.api.transport.StreamContext;
 import org.briarproject.api.transport.StreamReaderFactory;
 import org.briarproject.api.transport.StreamWriterFactory;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.data.DataModule;
-import org.briarproject.db.DatabaseModule;
-import org.briarproject.event.EventModule;
-import org.briarproject.sync.SyncModule;
-import org.briarproject.transport.TransportModule;
 import org.junit.Test;
 
+import static org.briarproject.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
+import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
@@ -37,48 +37,43 @@ import java.io.OutputStream;
 import java.util.Arrays;
 import java.util.Collection;
 
-import static org.briarproject.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import javax.inject.Inject;
 
 public class ProtocolIntegrationTest extends BriarTestCase {
 
-	private final StreamReaderFactory streamReaderFactory;
-	private final StreamWriterFactory streamWriterFactory;
-	private final PacketReaderFactory packetReaderFactory;
-	private final PacketWriterFactory packetWriterFactory;
+	@Inject
+	StreamReaderFactory streamReaderFactory;
+	@Inject
+	StreamWriterFactory streamWriterFactory;
+	@Inject
+	PacketReaderFactory packetReaderFactory;
+	@Inject
+	PacketWriterFactory packetWriterFactory;
 
 	private final ContactId contactId;
 	private final TransportId transportId;
 	private final SecretKey tagKey, headerKey;
 	private final Message message, message1;
 	private final Collection<MessageId> messageIds;
+	private final ProtocolTestComponent component;
 
 	public ProtocolIntegrationTest() throws Exception {
-		Injector i = Guice.createInjector(new TestDatabaseModule(),
-				new TestLifecycleModule(), new TestSystemModule(),
-				new CryptoModule(), new DatabaseModule(), new EventModule(),
-				new SyncModule(), new DataModule(),
-				new TransportModule());
-		streamReaderFactory = i.getInstance(StreamReaderFactory.class);
-		streamWriterFactory = i.getInstance(StreamWriterFactory.class);
-		packetReaderFactory = i.getInstance(PacketReaderFactory.class);
-		packetWriterFactory = i.getInstance(PacketWriterFactory.class);
+
+		component = DaggerProtocolTestComponent.builder().build();
+		component.inject(this);
+
 		contactId = new ContactId(234);
 		transportId = new TransportId("id");
 		// Create the transport keys
 		tagKey = TestUtils.createSecretKey();
 		headerKey = TestUtils.createSecretKey();
 		// Create a group
-		GroupFactory groupFactory = i.getInstance(GroupFactory.class);
+		GroupFactory groupFactory = component.getGroupFactory();
 		ClientId clientId = new ClientId(TestUtils.getRandomId());
 		byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
 		Group group = groupFactory.createGroup(clientId, descriptor);
 		// Add two messages to the group
-		MessageFactory messageFactory = i.getInstance(MessageFactory.class);
+		MessageFactory messageFactory = component.getMessageFactory();
 		long timestamp = System.currentTimeMillis();
 		String messageBody = "Hello world";
 		message = messageFactory.createMessage(group.getId(), timestamp,
@@ -159,4 +154,5 @@ public class ProtocolIntegrationTest extends BriarTestCase {
 		assertEquals(m1.getTimestamp(), m2.getTimestamp());
 		assertArrayEquals(m1.getRaw(), m2.getRaw());
 	}
+
 }
diff --git a/briar-android-tests/src/test/java/org/briarproject/protocol/ProtocolTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/protocol/ProtocolTestComponent.java
new file mode 100644
index 0000000000..59f58e0cc1
--- /dev/null
+++ b/briar-android-tests/src/test/java/org/briarproject/protocol/ProtocolTestComponent.java
@@ -0,0 +1,26 @@
+package org.briarproject.protocol;
+
+import org.briarproject.TestDatabaseModule;
+import org.briarproject.TestSystemModule;
+import org.briarproject.api.sync.GroupFactory;
+import org.briarproject.api.sync.MessageFactory;
+import org.briarproject.crypto.CryptoModule;
+import org.briarproject.data.DataModule;
+import org.briarproject.db.DatabaseModule;
+import org.briarproject.event.EventModule;
+import org.briarproject.sync.SyncModule;
+import org.briarproject.transport.TransportModule;
+
+import javax.inject.Singleton;
+
+import dagger.Component;
+
+@Singleton
+@Component(modules = {TestDatabaseModule.class, TestSystemModule.class,
+		CryptoModule.class, DatabaseModule.class, EventModule.class,
+		SyncModule.class, DataModule.class, TransportModule.class})
+public interface ProtocolTestComponent {
+	void inject(ProtocolIntegrationTest testCase);
+	GroupFactory getGroupFactory();
+	MessageFactory getMessageFactory();
+}
diff --git a/briar-android-tests/src/test/java/org/briarproject/sync/ConstantsComponent.java b/briar-android-tests/src/test/java/org/briarproject/sync/ConstantsComponent.java
new file mode 100644
index 0000000000..9a59db135d
--- /dev/null
+++ b/briar-android-tests/src/test/java/org/briarproject/sync/ConstantsComponent.java
@@ -0,0 +1,28 @@
+package org.briarproject.sync;
+
+import org.briarproject.TestDatabaseModule;
+import org.briarproject.TestLifecycleModule;
+import org.briarproject.TestSystemModule;
+import org.briarproject.contact.ContactModule;
+import org.briarproject.crypto.CryptoModule;
+import org.briarproject.data.DataModule;
+import org.briarproject.db.DatabaseModule;
+import org.briarproject.event.EventModule;
+import org.briarproject.forum.ForumModule;
+import org.briarproject.identity.IdentityModule;
+import org.briarproject.messaging.MessagingModule;
+import org.briarproject.transport.TransportModule;
+
+import javax.inject.Singleton;
+
+import dagger.Component;
+
+@Singleton
+@Component(modules = {TestDatabaseModule.class, TestLifecycleModule.class,
+		TestSystemModule.class, ContactModule.class, CryptoModule.class,
+		DatabaseModule.class, EventModule.class, SyncModule.class,
+		DataModule.class, TransportModule.class, ForumModule.class,
+		IdentityModule.class, MessagingModule.class})
+public interface ConstantsComponent {
+	void inject(ConstantsTest testCase);
+}
diff --git a/briar-tests/src/org/briarproject/sync/ConstantsTest.java b/briar-android-tests/src/test/java/org/briarproject/sync/ConstantsTest.java
similarity index 76%
rename from briar-tests/src/org/briarproject/sync/ConstantsTest.java
rename to briar-android-tests/src/test/java/org/briarproject/sync/ConstantsTest.java
index bac9995415..426a38945f 100644
--- a/briar-tests/src/org/briarproject/sync/ConstantsTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/sync/ConstantsTest.java
@@ -1,12 +1,6 @@
 package org.briarproject.sync;
 
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-
 import org.briarproject.BriarTestCase;
-import org.briarproject.TestDatabaseModule;
-import org.briarproject.TestLifecycleModule;
-import org.briarproject.TestSystemModule;
 import org.briarproject.TestUtils;
 import org.briarproject.api.UniqueId;
 import org.briarproject.api.crypto.CryptoComponent;
@@ -21,22 +15,6 @@ import org.briarproject.api.identity.AuthorFactory;
 import org.briarproject.api.messaging.MessagingConstants;
 import org.briarproject.api.messaging.PrivateMessage;
 import org.briarproject.api.messaging.PrivateMessageFactory;
-import org.briarproject.api.sync.GroupId;
-import org.briarproject.api.sync.MessageId;
-import org.briarproject.clients.ClientsModule;
-import org.briarproject.contact.ContactModule;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.data.DataModule;
-import org.briarproject.db.DatabaseModule;
-import org.briarproject.event.EventModule;
-import org.briarproject.forum.ForumModule;
-import org.briarproject.identity.IdentityModule;
-import org.briarproject.messaging.MessagingModule;
-import org.briarproject.transport.TransportModule;
-import org.junit.Test;
-
-import java.util.Random;
-
 import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
 import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
 import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
@@ -45,26 +23,32 @@ import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESS
 import static org.briarproject.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
 import static org.junit.Assert.assertTrue;
 
+import org.briarproject.api.sync.GroupId;
+import org.briarproject.api.sync.MessageId;
+import org.junit.Test;
+
+import java.util.Random;
+
+import javax.inject.Inject;
+
 public class ConstantsTest extends BriarTestCase {
 
 	// TODO: Break this up into tests that are relevant for each package
+	@Inject
+	CryptoComponent crypto;
+	@Inject
+	AuthorFactory authorFactory;
+	@Inject
+	PrivateMessageFactory privateMessageFactory;
+	@Inject
+	ForumPostFactory forumPostFactory;
 
-	private final CryptoComponent crypto;
-	private final AuthorFactory authorFactory;
-	private final PrivateMessageFactory privateMessageFactory;
-	private final ForumPostFactory forumPostFactory;
+	private final ConstantsComponent component;
 
 	public ConstantsTest() throws Exception {
-		Injector i = Guice.createInjector(new TestDatabaseModule(),
-				new TestLifecycleModule(), new TestSystemModule(),
-				new ClientsModule(), new ContactModule(), new CryptoModule(),
-				new DatabaseModule(), new DataModule(), new EventModule(),
-				new ForumModule(), new IdentityModule(), new MessagingModule(),
-				new SyncModule(), new TransportModule());
-		crypto = i.getInstance(CryptoComponent.class);
-		authorFactory = i.getInstance(AuthorFactory.class);
-		privateMessageFactory = i.getInstance(PrivateMessageFactory.class);
-		forumPostFactory = i.getInstance(ForumPostFactory.class);
+
+		component = DaggerConstantsComponent.builder().build();
+		component.inject(this);
 	}
 
 	@Test
diff --git a/briar-android-tests/src/test/java/org/briarproject/sync/SimplexMessagingComponent.java b/briar-android-tests/src/test/java/org/briarproject/sync/SimplexMessagingComponent.java
new file mode 100644
index 0000000000..83bc5f1c84
--- /dev/null
+++ b/briar-android-tests/src/test/java/org/briarproject/sync/SimplexMessagingComponent.java
@@ -0,0 +1,54 @@
+package org.briarproject.sync;
+
+import org.briarproject.TestDatabaseModule;
+import org.briarproject.TestSystemModule;
+import org.briarproject.api.contact.ContactManager;
+import org.briarproject.api.db.DatabaseComponent;
+import org.briarproject.api.event.EventBus;
+import org.briarproject.api.identity.IdentityManager;
+import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.api.messaging.MessagingManager;
+import org.briarproject.api.messaging.PrivateMessageFactory;
+import org.briarproject.api.sync.PacketReaderFactory;
+import org.briarproject.api.sync.PacketWriterFactory;
+import org.briarproject.api.transport.KeyManager;
+import org.briarproject.api.transport.StreamReaderFactory;
+import org.briarproject.api.transport.StreamWriterFactory;
+import org.briarproject.contact.ContactModule;
+import org.briarproject.crypto.CryptoModule;
+import org.briarproject.data.DataModule;
+import org.briarproject.db.DatabaseModule;
+import org.briarproject.event.EventModule;
+import org.briarproject.identity.IdentityModule;
+import org.briarproject.lifecycle.LifecycleModule;
+import org.briarproject.messaging.MessagingModule;
+import org.briarproject.transport.TransportModule;
+
+import javax.inject.Singleton;
+
+import dagger.Component;
+
+/**
+ * Created by Ernir Erlingsson (ernir@ymirmobile.com) on 3.3.2016.
+ */
+@Singleton
+@Component(modules = {TestDatabaseModule.class, TestSystemModule.class,
+		LifecycleModule.class, ContactModule.class, CryptoModule.class,
+		DatabaseModule.class, EventModule.class, SyncModule.class,
+		DataModule.class, TransportModule.class, IdentityModule.class,
+		MessagingModule.class})
+public interface SimplexMessagingComponent {
+	void inject(SimplexMessagingIntegrationTest testCase);
+	LifecycleManager getLifeCycleManager();
+	DatabaseComponent getDatabaseComponent();
+	IdentityManager getIdentityManager();
+	ContactManager getContactManager();
+	MessagingManager getMessagingManager();
+	KeyManager getKeyManager();
+	PrivateMessageFactory getPrivateMessageFactory();
+	PacketWriterFactory getPacketWriterFactory();
+	EventBus getEventBus();
+	StreamWriterFactory getStreamWriterFactory();
+	StreamReaderFactory getStreamReaderFactory();
+	PacketReaderFactory getPacketReaderFactory();
+}
diff --git a/briar-tests/src/org/briarproject/sync/SimplexMessagingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/sync/SimplexMessagingIntegrationTest.java
similarity index 66%
rename from briar-tests/src/org/briarproject/sync/SimplexMessagingIntegrationTest.java
rename to briar-android-tests/src/test/java/org/briarproject/sync/SimplexMessagingIntegrationTest.java
index 0c95d8b3b6..dbc1b6a4f3 100644
--- a/briar-tests/src/org/briarproject/sync/SimplexMessagingIntegrationTest.java
+++ b/briar-android-tests/src/test/java/org/briarproject/sync/SimplexMessagingIntegrationTest.java
@@ -1,19 +1,14 @@
 package org.briarproject.sync;
 
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-
 import org.briarproject.BriarTestCase;
-import org.briarproject.ImmediateExecutor;
 import org.briarproject.TestDatabaseModule;
-import org.briarproject.TestSystemModule;
 import org.briarproject.TestUtils;
 import org.briarproject.api.TransportId;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.contact.ContactManager;
 import org.briarproject.api.crypto.SecretKey;
 import org.briarproject.api.db.DatabaseComponent;
-import org.briarproject.api.db.Transaction;
+import org.briarproject.api.db.StorageStatus;
 import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
 import org.briarproject.api.event.EventListener;
@@ -36,33 +31,24 @@ import org.briarproject.api.transport.KeyManager;
 import org.briarproject.api.transport.StreamContext;
 import org.briarproject.api.transport.StreamReaderFactory;
 import org.briarproject.api.transport.StreamWriterFactory;
-import org.briarproject.clients.ClientsModule;
-import org.briarproject.contact.ContactModule;
-import org.briarproject.crypto.CryptoModule;
-import org.briarproject.data.DataModule;
-import org.briarproject.db.DatabaseModule;
-import org.briarproject.event.EventModule;
-import org.briarproject.identity.IdentityModule;
-import org.briarproject.lifecycle.LifecycleModule;
-import org.briarproject.messaging.MessagingModule;
-import org.briarproject.transport.TransportModule;
+import org.briarproject.plugins.ImmediateExecutor;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
+import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.InputStream;
 import java.io.OutputStream;
 
-import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
-import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
 public class SimplexMessagingIntegrationTest extends BriarTestCase {
 
 	private static final int MAX_LATENCY = 2 * 60 * 1000; // 2 minutes
@@ -76,22 +62,16 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
 	private final AuthorId aliceId = new AuthorId(TestUtils.getRandomId());
 	private final AuthorId bobId = new AuthorId(TestUtils.getRandomId());
 
-	private Injector alice, bob;
+	//	private Injector alice, bob;
+	private SimplexMessagingComponent alice, bob;
 
 	@Before
 	public void setUp() {
 		assertTrue(testDir.mkdirs());
-		alice = createInjector(aliceDir);
-		bob = createInjector(bobDir);
-	}
-
-	private Injector createInjector(File dir) {
-		return Guice.createInjector(new TestDatabaseModule(dir),
-				new TestSystemModule(), new ClientsModule(),
-				new ContactModule(), new CryptoModule(), new DatabaseModule(),
-				new DataModule(), new EventModule(), new IdentityModule(),
-				new LifecycleModule(), new MessagingModule(), new SyncModule(),
-				new TransportModule());
+		alice = DaggerSimplexMessagingComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(aliceDir)).build();
+		bob = DaggerSimplexMessagingComponent.builder()
+				.testDatabaseModule(new TestDatabaseModule(bobDir)).build();
 	}
 
 	@Test
@@ -101,43 +81,34 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
 
 	private byte[] write() throws Exception {
 		// Instantiate Alice's services
-		LifecycleManager lifecycleManager =
-				alice.getInstance(LifecycleManager.class);
-		DatabaseComponent db = alice.getInstance(DatabaseComponent.class);
-		IdentityManager identityManager =
-				alice.getInstance(IdentityManager.class);
-		ContactManager contactManager = alice.getInstance(ContactManager.class);
-		MessagingManager messagingManager =
-				alice.getInstance(MessagingManager.class);
-		KeyManager keyManager = alice.getInstance(KeyManager.class);
-		PrivateMessageFactory privateMessageFactory =
-				alice.getInstance(PrivateMessageFactory.class);
-		PacketWriterFactory packetWriterFactory =
-				alice.getInstance(PacketWriterFactory.class);
-		EventBus eventBus = alice.getInstance(EventBus.class);
-		StreamWriterFactory streamWriterFactory =
-				alice.getInstance(StreamWriterFactory.class);
+		LifecycleManager lifecycleManager = alice.getLifeCycleManager();
+		DatabaseComponent db = alice.getDatabaseComponent();
+		IdentityManager identityManager = alice.getIdentityManager();
+
+		ContactManager contactManager = alice.getContactManager();
+		MessagingManager messagingManager = alice.getMessagingManager();
+		KeyManager keyManager = alice.getKeyManager();
+		PrivateMessageFactory privateMessageFactory = alice.getPrivateMessageFactory();
+		PacketWriterFactory packetWriterFactory = alice.getPacketWriterFactory();
+		EventBus eventBus = alice.getEventBus();
+		StreamWriterFactory streamWriterFactory = alice.getStreamWriterFactory();
 
 		// Start the lifecycle manager
 		lifecycleManager.startServices();
 		lifecycleManager.waitForStartup();
 		// Add a transport
-		Transaction txn = db.startTransaction();
-		try {
-			db.addTransport(txn, transportId, MAX_LATENCY);
-			txn.setComplete();
-		} finally {
-			db.endTransaction(txn);
-		}
+		db.addTransport(transportId, MAX_LATENCY);
 		// Add an identity for Alice
 		LocalAuthor aliceAuthor = new LocalAuthor(aliceId, "Alice",
-				new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp);
+				new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp,
+				StorageStatus.ADDING);
 		identityManager.addLocalAuthor(aliceAuthor);
 		// Add Bob as a contact
 		Author bobAuthor = new Author(bobId, "Bob",
 				new byte[MAX_PUBLIC_KEY_LENGTH]);
-		ContactId contactId = contactManager.addContact(bobAuthor, aliceId,
-				master, timestamp, true, true);
+		ContactId contactId = contactManager.addContact(bobAuthor, aliceId);
+		// Derive and store the transport keys
+		keyManager.addContact(contactId, master, timestamp, true);
 
 		// Send Bob a message
 		GroupId groupId = messagingManager.getConversationId(contactId);
@@ -172,45 +143,37 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
 
 	private void read(byte[] stream) throws Exception {
 		// Instantiate Bob's services
-		LifecycleManager lifecycleManager =
-				bob.getInstance(LifecycleManager.class);
-		DatabaseComponent db = bob.getInstance(DatabaseComponent.class);
-		IdentityManager identityManager =
-				bob.getInstance(IdentityManager.class);
-		ContactManager contactManager = bob.getInstance(ContactManager.class);
-		KeyManager keyManager = bob.getInstance(KeyManager.class);
-		StreamReaderFactory streamReaderFactory =
-				bob.getInstance(StreamReaderFactory.class);
-		PacketReaderFactory packetReaderFactory =
-				bob.getInstance(PacketReaderFactory.class);
-		EventBus eventBus = bob.getInstance(EventBus.class);
+		LifecycleManager lifecycleManager = bob.getLifeCycleManager();
+		DatabaseComponent db = bob.getDatabaseComponent();
+		IdentityManager identityManager = bob.getIdentityManager();
+		ContactManager contactManager = bob.getContactManager();
+		KeyManager keyManager = bob.getKeyManager();
+		StreamReaderFactory streamReaderFactory = bob.getStreamReaderFactory();
+		PacketReaderFactory packetReaderFactory = bob.getPacketReaderFactory();
+		EventBus eventBus = bob.getEventBus();
 		// Bob needs a MessagingManager even though we're not using it directly
-		bob.getInstance(MessagingManager.class);
+		bob.getMessagingManager();
 
 		// Start the lifecyle manager
 		lifecycleManager.startServices();
 		lifecycleManager.waitForStartup();
 		// Add a transport
-		Transaction txn = db.startTransaction();
-		try {
-			db.addTransport(txn, transportId, MAX_LATENCY);
-			txn.setComplete();
-		} finally {
-			db.endTransaction(txn);
-		}
+		db.addTransport(transportId, MAX_LATENCY);
 		// Add an identity for Bob
 		LocalAuthor bobAuthor = new LocalAuthor(bobId, "Bob",
-				new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp);
+				new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp,
+				StorageStatus.ADDING);
 		identityManager.addLocalAuthor(bobAuthor);
 		// Add Alice as a contact
 		Author aliceAuthor = new Author(aliceId, "Alice",
 				new byte[MAX_PUBLIC_KEY_LENGTH]);
-		ContactId contactId = contactManager.addContact(aliceAuthor, bobId,
-				master, timestamp, false, true);
+		ContactId contactId = contactManager.addContact(aliceAuthor, bobId);
+		// Derive and store the transport keys
+		keyManager.addContact(contactId, master, timestamp, false);
 
 		// Set up an event listener
 		MessageListener listener = new MessageListener();
-		bob.getInstance(EventBus.class).addListener(listener);
+		bob.getEventBus().addListener(listener);
 		// Read and recognise the tag
 		ByteArrayInputStream in = new ByteArrayInputStream(stream);
 		byte[] tag = new byte[TAG_LENGTH];
diff --git a/briar-android/build.gradle b/briar-android/build.gradle
index fd7393e4b8..c3a03b93a7 100644
--- a/briar-android/build.gradle
+++ b/briar-android/build.gradle
@@ -1,5 +1,6 @@
 apply plugin: 'com.android.application'
 apply plugin: 'witness'
+apply plugin: 'com.neenbedankt.android-apt'
 
 repositories {
 	jcenter()
@@ -27,10 +28,13 @@ dependencies {
 		exclude module: 'support-v4'
 		exclude module: 'recyclerview-v7'
 	}
-	compile "org.roboguice:roboguice:2.0"
 	compile "info.guardianproject.panic:panic:0.5"
 	compile "info.guardianproject.trustedintents:trustedintents:0.2"
 	compile "de.hdodenhof:circleimageview:2.0.0"
+	apt 'com.google.dagger:dagger-compiler:2.0.2'
+	provided 'javax.annotation:jsr250-api:1.0'
+
+	compile 'cglib:cglib-nodep:3.1'
 }
 
 dependencyVerification {
@@ -42,7 +46,6 @@ dependencyVerification {
 			'com.android.support:design:41a9cd75ca78f25df5f573db7cedf8bb66beae00c330943923ba9f3e2051736d',
 			'com.android.support:support-annotations:f347a35b9748a4103b39a6714a77e2100f488d623fd6268e259c177b200e9d82',
 			'com.android.support:recyclerview-v7:7606373da0931a1e62588335465a0e390cd676c98117edab29220317495faefd',
-			'org.roboguice:roboguice:c5302f2648170ee6015a0d18fe0fcc87e09e415a34aeae3566e8d1a9dbb53f28',
 			'info.guardianproject.panic:panic:a7ed9439826db2e9901649892cf9afbe76f00991b768d8f4c26332d7c9406cb2',
 			'info.guardianproject.trustedintents:trustedintents:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e',
 	]
@@ -95,4 +98,4 @@ android {
 	lintOptions {
 		abortOnError false
 	}
-}
+}
\ No newline at end of file
diff --git a/briar-android/proguard-rules.txt b/briar-android/proguard-rules.txt
index 1ee57c5685..48d785a430 100644
--- a/briar-android/proguard-rules.txt
+++ b/briar-android/proguard-rules.txt
@@ -46,6 +46,8 @@
 -keep class javax.inject.** { *; }
 -keep class javax.annotation.** { *; }
 -keep class roboguice.** { *; }
+-keep class dagger.** { *; }
+-keep class com.google.** { *; }
 
 -dontwarn org.h2.**
 -dontnote org.h2.**
@@ -53,4 +55,7 @@
 -dontwarn org.briarproject.plugins.tcp.**
 -dontwarn roboguice.**
 -dontwarn net.sourceforge.jsocks.**
--dontnote android.support.**
\ No newline at end of file
+-dontnote android.support.**
+-dontnote dagger.**
+-dontwarn dagger.**
+-dontwarn com.google.common.**
\ No newline at end of file
diff --git a/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java b/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java
index fa5c1c35a7..5be0994009 100644
--- a/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java
+++ b/briar-android/src/im/delight/android/identicons/AsymmetricIdenticon.java
@@ -23,11 +23,9 @@ import org.briarproject.api.crypto.CryptoComponent;
 
 import javax.inject.Inject;
 
-import roboguice.RoboGuice;
-
 public class AsymmetricIdenticon extends IdenticonView {
 
-	@Inject private CryptoComponent mCrypto;
+	@Inject protected CryptoComponent mCrypto;
 	private IdenticonBase mDelegate;
 
 	public AsymmetricIdenticon(Context context) {
@@ -51,7 +49,6 @@ public class AsymmetricIdenticon extends IdenticonView {
 	}
 
 	private void initDelegate() {
-		RoboGuice.injectMembers(getContext(), this);
 		mDelegate = new IdenticonBase() {
 			@Override
 			protected CryptoComponent getCrypto() {
diff --git a/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java b/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java
index f390270815..e89068e392 100644
--- a/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java
+++ b/briar-android/src/im/delight/android/identicons/SymmetricIdenticon.java
@@ -23,13 +23,11 @@ import org.briarproject.api.crypto.CryptoComponent;
 
 import javax.inject.Inject;
 
-import roboguice.RoboGuice;
-
 public class SymmetricIdenticon extends IdenticonView {
 
 	private static final int CENTER_COLUMN_INDEX = 5;
 
-	@Inject private CryptoComponent mCrypto;
+	@Inject protected CryptoComponent mCrypto;
 	private IdenticonBase mDelegate;
 
 	public SymmetricIdenticon(Context context) {
@@ -48,7 +46,6 @@ public class SymmetricIdenticon extends IdenticonView {
 	}
 
 	private void initDelegate() {
-		RoboGuice.injectMembers(getContext(), this);
 		mDelegate = new IdenticonBase() {
 			@Override
 			protected CryptoComponent getCrypto() {
diff --git a/briar-android/src/org/briarproject/android/AndroidComponent.java b/briar-android/src/org/briarproject/android/AndroidComponent.java
new file mode 100644
index 0000000000..e360a10ec0
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/AndroidComponent.java
@@ -0,0 +1,70 @@
+package org.briarproject.android;
+
+import org.briarproject.android.contact.ContactListFragment;
+import org.briarproject.android.contact.ConversationActivity;
+import org.briarproject.android.forum.AvailableForumsActivity;
+import org.briarproject.android.forum.CreateForumActivity;
+import org.briarproject.android.forum.ForumActivity;
+import org.briarproject.android.forum.ForumListFragment;
+import org.briarproject.android.forum.ReadForumPostActivity;
+import org.briarproject.android.forum.ShareForumActivity;
+import org.briarproject.android.forum.WriteForumPostActivity;
+import org.briarproject.android.fragment.SettingsFragment;
+import org.briarproject.android.identity.CreateIdentityActivity;
+import org.briarproject.android.invitation.AddContactActivity;
+import org.briarproject.android.panic.PanicPreferencesActivity;
+import org.briarproject.android.panic.PanicResponderActivity;
+import org.briarproject.contact.ContactModule;
+import org.briarproject.crypto.CryptoModule;
+import org.briarproject.data.DataModule;
+import org.briarproject.db.DatabaseModule;
+import org.briarproject.event.EventModule;
+import org.briarproject.forum.ForumModule;
+import org.briarproject.identity.IdentityModule;
+import org.briarproject.invitation.InvitationModule;
+import org.briarproject.lifecycle.LifecycleModule;
+import org.briarproject.messaging.MessagingModule;
+import org.briarproject.plugins.AndroidPluginsModule;
+import org.briarproject.properties.PropertiesModule;
+import org.briarproject.reliability.ReliabilityModule;
+import org.briarproject.settings.SettingsModule;
+import org.briarproject.sync.SyncModule;
+import org.briarproject.system.AndroidSystemModule;
+import org.briarproject.transport.TransportModule;
+
+
+import javax.inject.Singleton;
+import dagger.Component;
+@Singleton
+@Component(
+		modules = {AppModule.class, AndroidModule.class, DatabaseModule.class,
+				CryptoModule.class, LifecycleModule.class,
+				ReliabilityModule.class, MessagingModule.class,
+				InvitationModule.class, ForumModule.class, IdentityModule.class,
+				EventModule.class, DataModule.class, ContactModule.class,
+				AndroidSystemModule.class, AndroidPluginsModule.class,
+				PropertiesModule.class, TransportModule.class, SyncModule.class,
+				SettingsModule.class})
+public interface AndroidComponent {
+	void inject(SplashScreenActivity activity);
+	void inject(SetupActivity activity);
+	void inject(NavDrawerActivity activity);
+	void inject(PasswordActivity activity);
+	void inject(BriarService activity);
+	void inject(PanicResponderActivity activity);
+	void inject(PanicPreferencesActivity activity);
+	void inject(AddContactActivity activity);
+	void inject(ConversationActivity activity);
+	void inject(CreateIdentityActivity activity);
+	void inject(TestingActivity activity);
+	void inject(AvailableForumsActivity activity);
+	void inject(WriteForumPostActivity activity);
+	void inject(CreateForumActivity activity);
+	void inject(ShareForumActivity activity);
+	void inject(ReadForumPostActivity activity);
+	void inject(ForumActivity activity);
+	void inject(ContactListFragment fragment);
+	void inject(SettingsFragment fragment);
+	void inject(ForumListFragment fragment);
+
+}
diff --git a/briar-android/src/org/briarproject/android/AndroidModule.java b/briar-android/src/org/briarproject/android/AndroidModule.java
index 1a46ec730a..427b884b5a 100644
--- a/briar-android/src/org/briarproject/android/AndroidModule.java
+++ b/briar-android/src/org/briarproject/android/AndroidModule.java
@@ -1,9 +1,8 @@
 package org.briarproject.android;
 
 import android.app.Application;
-
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
+import android.content.SharedPreferences;
+import android.support.v7.preference.PreferenceManager;
 
 import org.briarproject.api.android.AndroidExecutor;
 import org.briarproject.api.android.AndroidNotificationManager;
@@ -18,9 +17,13 @@ import java.io.File;
 
 import javax.inject.Singleton;
 
+import dagger.Module;
+import dagger.Provides;
+
 import static android.content.Context.MODE_PRIVATE;
 
-public class AndroidModule extends AbstractModule {
+@Module
+public class AndroidModule {
 
 	private final UiCallback uiCallback;
 
@@ -42,17 +45,27 @@ public class AndroidModule extends AbstractModule {
 		};
 	}
 
-	@Override
-	protected void configure() {
-		bind(AndroidExecutor.class).to(AndroidExecutorImpl.class).in(
-				Singleton.class);
-		bind(ReferenceManager.class).to(ReferenceManagerImpl.class).in(
-				Singleton.class);
-		bind(UiCallback.class).toInstance(uiCallback);
+	@Provides
+	UiCallback provideUICallback() {
+		return uiCallback;
+	}
+
+	@Provides
+	@Singleton
+	ReferenceManager provideReferenceManager() {
+		return new ReferenceManagerImpl();
 	}
 
-	@Provides @Singleton
-	DatabaseConfig getDatabaseConfig(final Application app) {
+	@Provides
+	@Singleton
+	AndroidExecutor provideAndroidExecutor(
+			AndroidExecutorImpl androidExecutor) {
+		return androidExecutor;
+	}
+
+	@Provides
+	@Singleton
+	DatabaseConfig provideDatabaseConfig(final Application app) {
 		final File dir = app.getApplicationContext().getDir("db", MODE_PRIVATE);
 		return new DatabaseConfig() {
 
@@ -80,12 +93,15 @@ public class AndroidModule extends AbstractModule {
 		};
 	}
 
-	@Provides @Singleton
-	AndroidNotificationManager getAndroidNotificationManager(
+
+	@Provides
+	@Singleton
+	AndroidNotificationManager provideAndroidNotificationManager(
 			LifecycleManager lifecycleManager, EventBus eventBus,
 			AndroidNotificationManagerImpl notificationManager) {
 		lifecycleManager.register(notificationManager);
 		eventBus.addListener(notificationManager);
 		return notificationManager;
 	}
+
 }
diff --git a/briar-android/src/org/briarproject/android/AppModule.java b/briar-android/src/org/briarproject/android/AppModule.java
new file mode 100644
index 0000000000..d3779d1a1a
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/AppModule.java
@@ -0,0 +1,25 @@
+package org.briarproject.android;
+
+import android.app.Application;
+import android.content.Context;
+
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class AppModule {
+
+	Application application;
+
+	public AppModule(Application application) {
+		this.application = application;
+	}
+
+	@Provides
+	@Singleton
+	Application providesApplication() {
+		return application;
+	}
+}
diff --git a/briar-android/src/org/briarproject/android/BaseActivity.java b/briar-android/src/org/briarproject/android/BaseActivity.java
index 35cfab4b4d..8fc2f16be2 100644
--- a/briar-android/src/org/briarproject/android/BaseActivity.java
+++ b/briar-android/src/org/briarproject/android/BaseActivity.java
@@ -9,125 +9,31 @@ import android.support.v7.app.AppCompatActivity;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 
-import com.google.inject.Inject;
-import com.google.inject.Key;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import roboguice.RoboGuice;
-import roboguice.activity.event.OnActivityResultEvent;
-import roboguice.activity.event.OnConfigurationChangedEvent;
-import roboguice.activity.event.OnContentChangedEvent;
-import roboguice.activity.event.OnCreateEvent;
-import roboguice.activity.event.OnDestroyEvent;
-import roboguice.activity.event.OnNewIntentEvent;
-import roboguice.activity.event.OnPauseEvent;
-import roboguice.activity.event.OnRestartEvent;
-import roboguice.activity.event.OnResumeEvent;
-import roboguice.activity.event.OnStartEvent;
-import roboguice.activity.event.OnStopEvent;
-import roboguice.event.EventManager;
-import roboguice.inject.RoboInjector;
-import roboguice.util.RoboContext;
+
+import javax.inject.Inject;
 
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
 import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS;
 
-public abstract class BaseActivity extends AppCompatActivity
-		implements RoboContext {
+public abstract class BaseActivity extends AppCompatActivity {
 
 	public final static String PREFS_NAME = "db";
 	public final static String PREF_DB_KEY = "key";
 	public final static String PREF_SEEN_WELCOME_MESSAGE = "welcome_message";
 
-	private final HashMap<Key<?>, Object> scopedObjects =
-			new HashMap<Key<?>, Object>();
-
-	@Inject private EventManager eventManager;
-
 	@Override
 	public void onCreate(Bundle savedInstanceState) {
-		RoboInjector injector = RoboGuice.getInjector(this);
-		injector.injectMembersWithoutViews(this);
 		super.onCreate(savedInstanceState);
-		eventManager.fire(new OnCreateEvent(savedInstanceState));
 
 		if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
-	}
-
-	protected void onRestart() {
-		super.onRestart();
-		eventManager.fire(new OnRestartEvent());
-	}
-
-	protected void onStart() {
-		super.onStart();
-		eventManager.fire(new OnStartEvent());
-	}
-
-	protected void onResume() {
-		super.onResume();
-		eventManager.fire(new OnResumeEvent());
-	}
-
-	protected void onPause() {
-		super.onPause();
-		eventManager.fire(new OnPauseEvent());
-	}
-
-	protected void onNewIntent(Intent intent) {
-		super.onNewIntent(intent);
-		eventManager.fire(new OnNewIntentEvent());
-	}
-
-	protected void onStop() {
-		try {
-			eventManager.fire(new OnStopEvent());
-		} finally {
-			super.onStop();
-		}
-
-	}
-
-	protected void onDestroy() {
-		try {
-			eventManager.fire(new OnDestroyEvent());
-		} finally {
-			try {
-				RoboGuice.destroyInjector(this);
-			} finally {
-				super.onDestroy();
-			}
-		}
-
-	}
 
-	public void onConfigurationChanged(Configuration newConfig) {
-		Configuration currentConfig = getResources().getConfiguration();
-		super.onConfigurationChanged(newConfig);
-		eventManager.fire(new OnConfigurationChangedEvent(currentConfig,
-				newConfig));
+		AndroidComponent component =
+				((BriarApplication) getApplication()).getApplicationComponent();
+		injectActivity(component);
 	}
 
-	public void onContentChanged() {
-		super.onContentChanged();
-		RoboGuice.getInjector(this).injectViewMembers(this);
-		eventManager.fire(new OnContentChangedEvent());
-	}
-
-	protected void onActivityResult(int requestCode, int resultCode,
-			Intent data) {
-		super.onActivityResult(requestCode, resultCode, data);
-		eventManager.fire(new OnActivityResultEvent(requestCode, resultCode,
-				data));
-	}
-
-	@Override
-	public Map<Key<?>, Object> getScopedObjectMap() {
-		return scopedObjects;
-	}
+	public abstract void injectActivity(AndroidComponent component);
 
 	private SharedPreferences getSharedPrefs() {
 		return getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
diff --git a/briar-android/src/org/briarproject/android/BriarActivity.java b/briar-android/src/org/briarproject/android/BriarActivity.java
index dc0249ff57..80d33959e8 100644
--- a/briar-android/src/org/briarproject/android/BriarActivity.java
+++ b/briar-android/src/org/briarproject/android/BriarActivity.java
@@ -27,7 +27,8 @@ import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
 @SuppressLint("Registered")
 public abstract class BriarActivity extends BaseActivity {
 
-	public static final String KEY_LOCAL_AUTHOR_HANDLE = "briar.LOCAL_AUTHOR_HANDLE";
+	public static final String KEY_LOCAL_AUTHOR_HANDLE =
+			"briar.LOCAL_AUTHOR_HANDLE";
 	public static final String KEY_STARTUP_FAILED = "briar.STARTUP_FAILED";
 
 	public static final int REQUEST_PASSWORD = 1;
@@ -38,16 +39,21 @@ public abstract class BriarActivity extends BaseActivity {
 	private final BriarServiceConnection serviceConnection =
 			new BriarServiceConnection();
 
-	@Inject private DatabaseConfig databaseConfig;
+	@Inject
+	DatabaseConfig databaseConfig;
 	private boolean bound = false;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject @DatabaseExecutor private volatile Executor dbExecutor;
-	@Inject private volatile LifecycleManager lifecycleManager;
+	@Inject
+	@DatabaseExecutor
+	protected volatile Executor dbExecutor;
+	@Inject
+	protected volatile LifecycleManager lifecycleManager;
 
 	@Override
 	public void onCreate(Bundle state) {
 		super.onCreate(state);
+
 		if (databaseConfig.getEncryptionKey() != null) startAndBindService();
 	}
 
diff --git a/briar-android/src/org/briarproject/android/BriarApplication.java b/briar-android/src/org/briarproject/android/BriarApplication.java
index 8e54544cfe..1478b6e2d5 100644
--- a/briar-android/src/org/briarproject/android/BriarApplication.java
+++ b/briar-android/src/org/briarproject/android/BriarApplication.java
@@ -11,6 +11,8 @@ public class BriarApplication extends Application {
 	private static final Logger LOG =
 			Logger.getLogger(BriarApplication.class.getName());
 
+	private AndroidComponent applicationComponent;
+
 	@Override
 	public void onCreate() {
 		super.onCreate();
@@ -20,5 +22,14 @@ public class BriarApplication extends Application {
 		Context ctx = getApplicationContext();
 		CrashHandler newHandler = new CrashHandler(ctx, oldHandler);
 		Thread.setDefaultUncaughtExceptionHandler(newHandler);
+
+		applicationComponent = DaggerAndroidComponent.builder()
+				.appModule(new AppModule(this))
+				.androidModule(new AndroidModule())
+				.build();
+	}
+
+	public AndroidComponent getApplicationComponent() {
+		return applicationComponent;
 	}
 }
diff --git a/briar-android/src/org/briarproject/android/BriarService.java b/briar-android/src/org/briarproject/android/BriarService.java
index f11019303e..3d88616f3f 100644
--- a/briar-android/src/org/briarproject/android/BriarService.java
+++ b/briar-android/src/org/briarproject/android/BriarService.java
@@ -2,6 +2,7 @@ package org.briarproject.android;
 
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.Service;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.ServiceConnection;
@@ -22,8 +23,6 @@ import java.util.logging.Logger;
 
 import javax.inject.Inject;
 
-import roboguice.service.RoboService;
-
 import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -34,7 +33,7 @@ import static java.util.logging.Level.WARNING;
 import static org.briarproject.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING;
 import static org.briarproject.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
 
-public class BriarService extends RoboService {
+public class BriarService extends Service {
 
 	private static final int ONGOING_NOTIFICATION_ID = 1;
 	private static final int FAILURE_NOTIFICATION_ID = 2;
@@ -45,16 +44,20 @@ public class BriarService extends RoboService {
 	private final AtomicBoolean created = new AtomicBoolean(false);
 	private final Binder binder = new BriarBinder();
 
-	@Inject private DatabaseConfig databaseConfig;
+	@Inject protected DatabaseConfig databaseConfig;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile LifecycleManager lifecycleManager;
-	@Inject private volatile AndroidExecutor androidExecutor;
+	@Inject protected volatile LifecycleManager lifecycleManager;
+	@Inject protected volatile AndroidExecutor androidExecutor;
 	private volatile boolean started = false;
 
 	@Override
 	public void onCreate() {
 		super.onCreate();
+
+		((BriarApplication) this.getApplication())
+				.getApplicationComponent().inject(this);
+
 		LOG.info("Created");
 		if (created.getAndSet(true)) {
 			LOG.info("Already created");
diff --git a/briar-android/src/org/briarproject/android/NavDrawerActivity.java b/briar-android/src/org/briarproject/android/NavDrawerActivity.java
index c6bc58b788..8342c58379 100644
--- a/briar-android/src/org/briarproject/android/NavDrawerActivity.java
+++ b/briar-android/src/org/briarproject/android/NavDrawerActivity.java
@@ -14,6 +14,7 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
+import android.widget.Button;
 import android.widget.GridView;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -42,9 +43,6 @@ import java.util.logging.Logger;
 
 import javax.inject.Inject;
 
-import roboguice.RoboGuice;
-import roboguice.inject.InjectView;
-
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 
@@ -60,33 +58,23 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
 	private ActionBarDrawerToggle drawerToggle;
 
 	@Inject
-	private ReferenceManager referenceManager;
+	protected ReferenceManager referenceManager;
 	// Fields that are accessed from background threads must be volatile
 	@Inject
-	private volatile IdentityManager identityManager;
+	protected volatile IdentityManager identityManager;
 	@Inject
-	private PluginManager pluginManager;
+	protected PluginManager pluginManager;
 	@Inject
 	protected volatile EventBus eventBus;
 
-	@InjectView(R.id.toolbar)
 	private Toolbar toolbar;
-	@InjectView(R.id.drawer_layout)
 	private DrawerLayout drawerLayout;
-	@InjectView(R.id.nav_btn_contacts)
-	private AppCompatButton contactButton;
-	@InjectView(R.id.nav_btn_contacts)
-	private AppCompatButton forumsButton;
-	@InjectView(R.id.nav_btn_contacts)
-	private AppCompatButton settingsButton;
-	@InjectView(R.id.nav_menu_header)
-	private TextView menuHeader;
-	@InjectView(R.id.title_progress_bar)
-	private TextView progressTitle;
-	@InjectView(R.id.container_progress)
-	ViewGroup progressViewGroup;
-	@InjectView(R.id.transportsView)
+	private Button contactButton;
+	private Button forumsButton;
+	private Button settingsButton;
 	private GridView transportsView;
+	private TextView progressTitle;
+	private ViewGroup progressViewGroup;
 
 	private List<Transport> transports;
 	private BaseAdapter transportsAdapter;
@@ -104,6 +92,11 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
 		}
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	@SuppressWarnings("ConstantConditions")
 	@Override
 	public void onCreate(Bundle state) {
@@ -112,9 +105,16 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
 		if (isStartupFailed(getIntent()))
 			return;
 
-		// TODO inflate and inject with @ContentView with RoboGuice 3.0 and later
 		setContentView(R.layout.activity_nav_drawer);
-		RoboGuice.getInjector(this).injectViewMembers(this);
+
+		toolbar = (Toolbar)findViewById(R.id.toolbar);
+		drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
+		contactButton = (Button)findViewById(R.id.nav_btn_contacts);
+		forumsButton = (Button)findViewById(R.id.nav_btn_forums);
+		settingsButton = (Button)findViewById(R.id.nav_btn_settings);
+		transportsView = (GridView)findViewById(R.id.transportsView);
+		progressTitle = (TextView)findViewById(R.id.title_progress_bar);
+		progressViewGroup = (ViewGroup)findViewById(R.id.container_progress);
 
 		setSupportActionBar(toolbar);
 		getSupportActionBar().setDisplayHomeAsUpEnabled(true);
diff --git a/briar-android/src/org/briarproject/android/PasswordActivity.java b/briar-android/src/org/briarproject/android/PasswordActivity.java
index f9f60ed1a5..d1653207fe 100644
--- a/briar-android/src/org/briarproject/android/PasswordActivity.java
+++ b/briar-android/src/org/briarproject/android/PasswordActivity.java
@@ -34,7 +34,7 @@ import static android.view.View.VISIBLE;
 
 public class PasswordActivity extends BaseActivity {
 
-	@Inject @CryptoExecutor private Executor cryptoExecutor;
+	@Inject @CryptoExecutor protected Executor cryptoExecutor;
 	private Button signInButton;
 	private ProgressBar progress;
 	private TextInputLayout input;
@@ -43,8 +43,8 @@ public class PasswordActivity extends BaseActivity {
 	private byte[] encrypted;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile CryptoComponent crypto;
-	@Inject private volatile DatabaseConfig databaseConfig;
+	@Inject protected volatile CryptoComponent crypto;
+	@Inject protected volatile DatabaseConfig databaseConfig;
 
 	@Override
 	public void onCreate(Bundle state) {
@@ -74,7 +74,8 @@ public class PasswordActivity extends BaseActivity {
 		password.addTextChangedListener(new TextWatcher() {
 			@Override
 			public void beforeTextChanged(CharSequence s, int start, int count,
-					int after) {}
+					int after) {
+			}
 
 			@Override
 			public void onTextChanged(CharSequence s, int start, int before,
@@ -83,10 +84,16 @@ public class PasswordActivity extends BaseActivity {
 			}
 
 			@Override
-			public void afterTextChanged(Editable s) {}
+			public void afterTextChanged(Editable s) {
+			}
 		});
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	@Override
 	public void onBackPressed() {
 		// Show the home screen rather than another password prompt
diff --git a/briar-android/src/org/briarproject/android/SetupActivity.java b/briar-android/src/org/briarproject/android/SetupActivity.java
index 81e832d5f0..4aba12d056 100644
--- a/briar-android/src/org/briarproject/android/SetupActivity.java
+++ b/briar-android/src/org/briarproject/android/SetupActivity.java
@@ -33,8 +33,6 @@ import java.util.logging.Logger;
 
 import javax.inject.Inject;
 
-import roboguice.inject.InjectView;
-
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
@@ -50,29 +48,40 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
 	private static final Logger LOG =
 			Logger.getLogger(SetupActivity.class.getName());
 
-	@Inject @CryptoExecutor private Executor cryptoExecutor;
-	@Inject private PasswordStrengthEstimator strengthEstimator;
-	@InjectView(R.id.nickname_entry_wrapper) TextInputLayout nicknameEntryWrapper;
-	@InjectView(R.id.password_entry_wrapper) TextInputLayout passwordEntryWrapper;
-	@InjectView(R.id.password_confirm_wrapper) TextInputLayout passwordConfirmationWrapper;
-	@InjectView(R.id.nickname_entry) EditText nicknameEntry;
-	@InjectView(R.id.password_entry) EditText passwordEntry;
-	@InjectView(R.id.password_confirm) EditText passwordConfirmation;
-	@InjectView(R.id.strength_meter) StrengthMeter strengthMeter;
-	@InjectView(R.id.create_account) Button createAccountButton;
-	@InjectView(R.id.progress_wheel) ProgressBar progress;
+	@Inject @CryptoExecutor protected Executor cryptoExecutor;
+	@Inject protected PasswordStrengthEstimator strengthEstimator;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile CryptoComponent crypto;
-	@Inject private volatile DatabaseConfig databaseConfig;
-	@Inject private volatile AuthorFactory authorFactory;
-	@Inject private volatile ReferenceManager referenceManager;
+	@Inject protected volatile CryptoComponent crypto;
+	@Inject protected volatile DatabaseConfig databaseConfig;
+	@Inject protected volatile AuthorFactory authorFactory;
+	@Inject protected volatile ReferenceManager referenceManager;
+
+	TextInputLayout nicknameEntryWrapper;
+	TextInputLayout passwordEntryWrapper;
+	TextInputLayout passwordConfirmationWrapper;
+	EditText nicknameEntry;
+	EditText passwordEntry;
+	EditText passwordConfirmation;
+	StrengthMeter strengthMeter;
+	Button createAccountButton;
+	ProgressBar progress;
 
 	@Override
 	public void onCreate(Bundle state) {
 		super.onCreate(state);
 		setContentView(R.layout.activity_setup);
 
+		nicknameEntryWrapper = (TextInputLayout)findViewById(R.id.nickname_entry_wrapper);
+		passwordEntryWrapper = (TextInputLayout)findViewById(R.id.password_entry_wrapper);
+		passwordConfirmationWrapper = (TextInputLayout)findViewById(R.id.password_confirm_wrapper);
+		nicknameEntry = (EditText)findViewById(R.id.nickname_entry);
+		passwordEntry = (EditText)findViewById(R.id.password_entry);
+		passwordConfirmation = (EditText)findViewById(R.id.password_confirm);
+		strengthMeter = (StrengthMeter)findViewById(R.id.strength_meter);
+		createAccountButton = (Button)findViewById(R.id.create_account);
+		progress = (ProgressBar)findViewById(R.id.progress_wheel);
+
 		if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
 
 		TextWatcher tw = new TextWatcher() {
@@ -99,6 +108,11 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
 		createAccountButton.setOnClickListener(this);
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	private void enableOrDisableContinueButton() {
 		if (progress == null) return; // Not created yet
 		if (passwordEntry.getText().length() > 0 && passwordEntry.hasFocus())
diff --git a/briar-android/src/org/briarproject/android/SplashScreenActivity.java b/briar-android/src/org/briarproject/android/SplashScreenActivity.java
index c58427834b..c79f9a3505 100644
--- a/briar-android/src/org/briarproject/android/SplashScreenActivity.java
+++ b/briar-android/src/org/briarproject/android/SplashScreenActivity.java
@@ -1,9 +1,11 @@
 package org.briarproject.android;
 
+import android.app.Activity;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.graphics.Color;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.StrictMode;
 import android.os.StrictMode.ThreadPolicy;
 import android.os.StrictMode.VmPolicy;
@@ -11,29 +13,22 @@ import android.support.v7.preference.PreferenceManager;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
-import com.google.inject.Injector;
-
 import org.briarproject.R;
-import org.briarproject.android.util.AndroidUtils;
 import org.briarproject.android.util.LayoutUtils;
 import org.briarproject.api.db.DatabaseConfig;
+import org.briarproject.api.ui.UiCallback;
+import org.briarproject.util.FileUtils;
 
 import java.util.logging.Logger;
 
-import roboguice.RoboGuice;
-import roboguice.activity.RoboSplashActivity;
+import javax.inject.Inject;
 
 import static android.view.Gravity.CENTER;
-import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
-import static java.util.logging.Level.INFO;
-import static org.briarproject.android.BaseActivity.PREFS_NAME;
-import static org.briarproject.android.BaseActivity.PREF_DB_KEY;
 import static org.briarproject.android.TestingConstants.DEFAULT_LOG_LEVEL;
-import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS;
 import static org.briarproject.android.TestingConstants.TESTING;
 import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
 
-public class SplashScreenActivity extends RoboSplashActivity {
+public class SplashScreenActivity extends BaseActivity {
 
 	private static final Logger LOG =
 			Logger.getLogger(SplashScreenActivity.class.getName());
@@ -43,18 +38,18 @@ public class SplashScreenActivity extends RoboSplashActivity {
 
 	private long now = System.currentTimeMillis();
 
+	@Inject
+	DatabaseConfig dbConfig;
+
 	public SplashScreenActivity() {
 		Logger.getLogger("").setLevel(DEFAULT_LOG_LEVEL);
 		enableStrictMode();
-		minDisplayMs = 500;
 	}
 
 	@Override
 	public void onCreate(Bundle state) {
 		super.onCreate(state);
 
-		if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
-
 		LinearLayout layout = new LinearLayout(this);
 		layout.setLayoutParams(MATCH_MATCH);
 		layout.setGravity(CENTER);
@@ -70,28 +65,36 @@ public class SplashScreenActivity extends RoboSplashActivity {
 		setPreferencesDefaults();
 
 		setContentView(layout);
+
+		new Handler().postDelayed(new Runnable() {
+			@Override
+			public void run() {
+				startNextActivity();
+			}
+		}, 500);
 	}
 
 	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	protected void startNextActivity() {
-		long duration = System.currentTimeMillis() - now;
-		if (LOG.isLoggable(INFO))
-			LOG.info("Guice startup took " + duration + " ms");
 		if (System.currentTimeMillis() >= EXPIRY_DATE) {
 			LOG.info("Expired");
 			startActivity(new Intent(this, ExpiredActivity.class));
 		} else {
-			SharedPreferences prefs = getSharedPreferences(PREFS_NAME,
-					MODE_PRIVATE);
-			String hex = prefs.getString(PREF_DB_KEY, null);
-			Injector i = RoboGuice.getBaseApplicationInjector(getApplication());
-			DatabaseConfig databaseConfig = i.getInstance(DatabaseConfig.class);
-			if (hex != null && databaseConfig.databaseExists()) {
-				startActivity(new Intent(this, NavDrawerActivity.class));
-			} else {
-				prefs.edit().clear().apply();
-				AndroidUtils.deleteAppData(this);
-				startActivity(new Intent(this, SetupActivity.class));
+			String hex = getEncryptedDatabaseKey();
+
+			if (dbConfig != null) {
+				if (hex != null && dbConfig.databaseExists()) {
+					startActivity(new Intent(this, NavDrawerActivity.class));
+				} else {
+					clearSharedPrefs();
+					FileUtils.deleteFileOrDir(
+							dbConfig.getDatabaseDirectory());
+					startActivity(new Intent(this, SetupActivity.class));
+				}
 			}
 		}
 	}
@@ -114,7 +117,7 @@ public class SplashScreenActivity extends RoboSplashActivity {
 			@Override
 			public void run() {
 				PreferenceManager.setDefaultValues(SplashScreenActivity.this,
-								R.xml.panic_preferences, false);
+						R.xml.panic_preferences, false);
 			}
 		}.start();
 	}
diff --git a/briar-android/src/org/briarproject/android/StartupFailureActivity.java b/briar-android/src/org/briarproject/android/StartupFailureActivity.java
index 25d0372894..5180c33c27 100644
--- a/briar-android/src/org/briarproject/android/StartupFailureActivity.java
+++ b/briar-android/src/org/briarproject/android/StartupFailureActivity.java
@@ -19,6 +19,11 @@ public class StartupFailureActivity extends BaseActivity {
 		handleIntent(getIntent());
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+
+	}
+
 	private void handleIntent(Intent i) {
 		StartResult result = (StartResult) i.getSerializableExtra("briar.START_RESULT");
 		int notificationId = i.getIntExtra("briar.FAILURE_NOTIFICATION_ID", -1);
diff --git a/briar-android/src/org/briarproject/android/TestingActivity.java b/briar-android/src/org/briarproject/android/TestingActivity.java
index 47c319cf01..a7446b0cd2 100644
--- a/briar-android/src/org/briarproject/android/TestingActivity.java
+++ b/briar-android/src/org/briarproject/android/TestingActivity.java
@@ -75,9 +75,9 @@ public class TestingActivity extends BriarActivity implements OnClickListener {
 	private static final Logger LOG =
 			Logger.getLogger(TestingActivity.class.getName());
 
-	@Inject private PluginManager pluginManager;
-	@Inject private LifecycleManager lifecycleManager;
-	@Inject private TransportPropertyManager transportPropertyManager;
+	@Inject protected PluginManager pluginManager;
+	@Inject protected LifecycleManager lifecycleManager;
+	@Inject protected TransportPropertyManager transportPropertyManager;
 	private ScrollView scroll = null;
 	private ListLoadingProgressBar progress = null;
 	private LinearLayout status = null;
@@ -137,6 +137,11 @@ public class TestingActivity extends BriarActivity implements OnClickListener {
 		setContentView(layout);
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	@Override
 	public void onResume() {
 		super.onResume();
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
index b1352dda77..afdb74a427 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
@@ -10,6 +10,8 @@ import android.view.View;
 import android.view.ViewGroup;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
+import org.briarproject.android.BriarApplication;
 import org.briarproject.android.fragment.BaseEventFragment;
 import org.briarproject.android.invitation.AddContactActivity;
 import org.briarproject.android.util.BriarRecyclerView;
@@ -64,19 +66,29 @@ public class ContactListFragment extends BaseEventFragment {
 	}
 
 	@Inject
-	private CryptoComponent crypto;
+	protected CryptoComponent crypto;
 	@Inject
-	private ConnectionRegistry connectionRegistry;
+	protected ConnectionRegistry connectionRegistry;
 	private ContactListAdapter adapter = null;
 	private BriarRecyclerView list = null;
 
 	// Fields that are accessed from background threads must be volatile
 	@Inject
-	private volatile ContactManager contactManager;
+	protected volatile ContactManager contactManager;
 	@Inject
-	private volatile MessagingManager messagingManager;
+	protected volatile MessagingManager messagingManager;
 	@Inject
-	private volatile EventBus eventBus;
+	protected volatile EventBus eventBus;
+
+	@Override
+	public void onCreate(@Nullable Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+	}
+
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
 
 	@Nullable
 	@Override
diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
index b3f562949b..a170bfdb2a 100644
--- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java
@@ -17,6 +17,7 @@ import android.widget.ImageButton;
 import android.widget.Toast;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.android.util.BriarRecyclerView;
 import org.briarproject.api.FormatException;
@@ -71,10 +72,10 @@ public class ConversationActivity extends BriarActivity
 	private static final Logger LOG =
 			Logger.getLogger(ConversationActivity.class.getName());
 
-	@Inject private CryptoComponent crypto;
-	@Inject private AndroidNotificationManager notificationManager;
-	@Inject private ConnectionRegistry connectionRegistry;
-	@Inject @CryptoExecutor private Executor cryptoExecutor;
+	@Inject protected CryptoComponent crypto;
+	@Inject protected AndroidNotificationManager notificationManager;
+	@Inject protected ConnectionRegistry connectionRegistry;
+	@Inject @CryptoExecutor protected Executor cryptoExecutor;
 	private Map<MessageId, byte[]> bodyCache = new HashMap<MessageId, byte[]>();
 	private ConversationAdapter adapter = null;
 	private BriarRecyclerView list = null;
@@ -82,10 +83,10 @@ public class ConversationActivity extends BriarActivity
 	private ImageButton sendButton = null;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile ContactManager contactManager;
-	@Inject private volatile MessagingManager messagingManager;
-	@Inject private volatile EventBus eventBus;
-	@Inject private volatile PrivateMessageFactory privateMessageFactory;
+	@Inject protected volatile ContactManager contactManager;
+	@Inject protected volatile MessagingManager messagingManager;
+	@Inject protected volatile EventBus eventBus;
+	@Inject protected volatile PrivateMessageFactory privateMessageFactory;
 	private volatile GroupId groupId = null;
 	private volatile ContactId contactId = null;
 	private volatile String contactName = null;
@@ -115,6 +116,11 @@ public class ConversationActivity extends BriarActivity
 		sendButton.setOnClickListener(this);
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	@Override
 	public void onResume() {
 		super.onResume();
diff --git a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
index 2a9beba3c1..6ce64a2a1b 100644
--- a/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/AvailableForumsActivity.java
@@ -8,6 +8,7 @@ import android.widget.ListView;
 import android.widget.Toast;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.android.util.ListLoadingProgressBar;
 import org.briarproject.api.contact.Contact;
@@ -47,9 +48,9 @@ implements EventListener, OnItemClickListener {
 	private ListView list = null;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile ForumManager forumManager;
-	@Inject private volatile ForumSharingManager forumSharingManager;
-	@Inject private volatile EventBus eventBus;
+	@Inject protected volatile ForumManager forumManager;
+	@Inject protected volatile ForumSharingManager forumSharingManager;
+	@Inject protected volatile EventBus eventBus;
 
 	@Override
 	public void onCreate(Bundle state) {
@@ -66,6 +67,11 @@ implements EventListener, OnItemClickListener {
 		setContentView(loading);
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	@Override
 	public void onResume() {
 		super.onResume();
diff --git a/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java b/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
index ca0b2ab13c..9307bbb43b 100644
--- a/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/CreateForumActivity.java
@@ -14,6 +14,7 @@ import android.widget.TextView.OnEditorActionListener;
 import android.widget.Toast;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.android.util.LayoutUtils;
 import org.briarproject.api.db.DbException;
@@ -51,7 +52,7 @@ implements OnEditorActionListener, OnClickListener {
 	private TextView feedback = null;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile ForumSharingManager forumSharingManager;
+	@Inject protected volatile ForumSharingManager forumSharingManager;
 
 	@Override
 	public void onCreate(Bundle state) {
@@ -102,6 +103,11 @@ implements OnEditorActionListener, OnClickListener {
 		setContentView(layout);
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	private void enableOrDisableCreateButton() {
 		if (progress == null) return; // Not created yet
 		createForumButton.setEnabled(validateName());
diff --git a/briar-android/src/org/briarproject/android/forum/ForumActivity.java b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
index 943db62697..96add7ce47 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumActivity.java
@@ -13,6 +13,7 @@ import android.widget.ListView;
 import android.widget.TextView;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.android.util.ElasticHorizontalSpace;
 import org.briarproject.android.util.HorizontalBorder;
@@ -62,7 +63,7 @@ public class ForumActivity extends BriarActivity implements EventListener,
 	private static final Logger LOG =
 			Logger.getLogger(ForumActivity.class.getName());
 
-	@Inject private AndroidNotificationManager notificationManager;
+	@Inject protected AndroidNotificationManager notificationManager;
 	private Map<MessageId, byte[]> bodyCache = new HashMap<MessageId, byte[]>();
 	private TextView empty = null;
 	private ForumAdapter adapter = null;
@@ -71,8 +72,8 @@ public class ForumActivity extends BriarActivity implements EventListener,
 	private ImageButton composeButton = null, shareButton = null;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile ForumManager forumManager;
-	@Inject private volatile EventBus eventBus;
+	@Inject protected volatile ForumManager forumManager;
+	@Inject protected volatile EventBus eventBus;
 	private volatile GroupId groupId = null;
 	private volatile Forum forum = null;
 
@@ -139,6 +140,11 @@ public class ForumActivity extends BriarActivity implements EventListener,
 		setContentView(layout);
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	@Override
 	public void onResume() {
 		super.onResume();
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
index 30b62b2827..1684a14fc6 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
@@ -19,6 +19,7 @@ import android.widget.TextView;
 import android.widget.Toast;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.fragment.BaseEventFragment;
 import org.briarproject.android.util.HorizontalBorder;
 import org.briarproject.android.util.LayoutUtils;
@@ -83,8 +84,8 @@ public class ForumListFragment extends BaseEventFragment implements
 	private ImageButton newForumButton = null;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile ForumManager forumManager;
-	@Inject private volatile ForumSharingManager forumSharingManager;
+	@Inject protected volatile ForumManager forumManager;
+	@Inject protected volatile ForumSharingManager forumSharingManager;
 
 	@Nullable
 	@Override
@@ -152,6 +153,11 @@ public class ForumListFragment extends BaseEventFragment implements
 		return TAG;
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	@Override
 	public void onResume() {
 		super.onResume();
diff --git a/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java b/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java
index 45cec82f65..890cc03984 100644
--- a/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ReadForumPostActivity.java
@@ -12,6 +12,7 @@ import android.widget.ScrollView;
 import android.widget.TextView;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.android.util.AuthorView;
 import org.briarproject.android.util.ElasticHorizontalSpace;
@@ -59,7 +60,7 @@ implements OnClickListener {
 	private int position = -1;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile ForumManager forumManager;
+	@Inject protected volatile ForumManager forumManager;
 	private volatile MessageId messageId = null;
 
 	@Override
@@ -164,6 +165,11 @@ implements OnClickListener {
 		setContentView(layout);
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	@Override
 	public void onPause() {
 		super.onPause();
diff --git a/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java b/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
index 59821f9a12..cf252102ec 100644
--- a/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ShareForumActivity.java
@@ -11,6 +11,7 @@ import android.widget.RadioButton;
 import android.widget.RadioGroup;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.android.contact.SelectContactsDialog;
 import org.briarproject.android.invitation.AddContactActivity;
@@ -51,8 +52,8 @@ SelectContactsDialog.Listener {
 	private boolean changed = false;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile ContactManager contactManager;
-	@Inject private volatile ForumSharingManager forumSharingManager;
+	@Inject protected volatile ContactManager contactManager;
+	@Inject protected volatile ForumSharingManager forumSharingManager;
 	private volatile GroupId groupId = null;
 	private volatile Collection<Contact> contacts = null;
 	private volatile Collection<ContactId> selected = null;
@@ -109,6 +110,11 @@ SelectContactsDialog.Listener {
 		setContentView(layout);
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	public void onClick(View view) {
 		if (view == shareWithAll) {
 			changed = true;
diff --git a/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java b/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
index 6bd289e3ee..a3f038f48e 100644
--- a/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/WriteForumPostActivity.java
@@ -16,6 +16,7 @@ import android.widget.TextView;
 import android.widget.Toast;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.android.identity.CreateIdentityActivity;
 import org.briarproject.android.identity.LocalAuthorItem;
@@ -67,7 +68,7 @@ implements OnItemSelectedListener, OnClickListener {
 	private static final Logger LOG =
 			Logger.getLogger(WriteForumPostActivity.class.getName());
 
-	@Inject @CryptoExecutor private Executor cryptoExecutor;
+	@Inject @CryptoExecutor protected Executor cryptoExecutor;
 	private LocalAuthorSpinnerAdapter adapter = null;
 	private Spinner spinner = null;
 	private ImageButton sendButton = null;
@@ -76,10 +77,10 @@ implements OnItemSelectedListener, OnClickListener {
 	private GroupId groupId = null;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile IdentityManager identityManager;
-	@Inject private volatile ForumManager forumManager;
-	@Inject private volatile ForumPostFactory forumPostFactory;
-	@Inject private volatile CryptoComponent crypto;
+	@Inject protected volatile IdentityManager identityManager;
+	@Inject protected volatile ForumManager forumManager;
+	@Inject protected volatile ForumPostFactory forumPostFactory;
+	@Inject protected volatile CryptoComponent crypto;
 	private volatile MessageId parentId = null;
 	private volatile long minTimestamp = -1;
 	private volatile LocalAuthor localAuthor = null;
@@ -157,6 +158,11 @@ implements OnItemSelectedListener, OnClickListener {
 		setContentView(layout);
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	@Override
 	public void onResume() {
 		super.onResume();
diff --git a/briar-android/src/org/briarproject/android/fragment/BaseFragment.java b/briar-android/src/org/briarproject/android/fragment/BaseFragment.java
index 5d69a5870e..03dd189537 100644
--- a/briar-android/src/org/briarproject/android/fragment/BaseFragment.java
+++ b/briar-android/src/org/briarproject/android/fragment/BaseFragment.java
@@ -1,12 +1,14 @@
 package org.briarproject.android.fragment;
 
 import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
 
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
+import org.briarproject.android.BriarApplication;
 
-import roboguice.fragment.RoboFragment;
-
-public abstract class BaseFragment extends RoboFragment {
+public abstract class BaseFragment extends Fragment {
 
 	public abstract String getUniqueTag();
 
@@ -25,10 +27,25 @@ public abstract class BaseFragment extends RoboFragment {
 		}
 	}
 
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+
+		AndroidComponent component =
+				((BriarApplication) getActivity().getApplication())
+						.getApplicationComponent();
+		injectActivity(component);
+	}
+
+	public abstract void injectActivity(AndroidComponent component);
+
 	public interface BaseFragmentListener {
 		void showLoadingScreen(boolean isBlocking, int stringId);
+
 		void hideLoadingScreen();
+
 		void runOnUiThread(Runnable runnable);
+
 		void runOnDbThread(Runnable runnable);
 	}
 
diff --git a/briar-android/src/org/briarproject/android/fragment/DashboardFragment.java b/briar-android/src/org/briarproject/android/fragment/DashboardFragment.java
index b1eb92585b..f98c16ab08 100644
--- a/briar-android/src/org/briarproject/android/fragment/DashboardFragment.java
+++ b/briar-android/src/org/briarproject/android/fragment/DashboardFragment.java
@@ -9,6 +9,7 @@ import android.view.ViewGroup;
 import android.widget.GridView;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.api.event.Event;
 import org.briarproject.api.plugins.PluginManager;
 
@@ -16,8 +17,6 @@ import java.util.logging.Logger;
 
 import javax.inject.Inject;
 
-import roboguice.inject.InjectView;
-
 public class DashboardFragment extends BaseEventFragment {
 
 	public final static String TAG = "DashboardFragment";
@@ -26,10 +25,7 @@ public class DashboardFragment extends BaseEventFragment {
 			Logger.getLogger(DashboardFragment.class.getName());
 
 	@Inject
-	private PluginManager pluginManager;
-
-	@InjectView(R.id.transportsView)
-	private GridView transportsView;
+	protected PluginManager pluginManager;
 
 	public static DashboardFragment newInstance() {
 
@@ -59,6 +55,11 @@ public class DashboardFragment extends BaseEventFragment {
 		return TAG;
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+
+	}
+
 	@Override
 	public void eventOccurred(Event e) {
 
diff --git a/briar-android/src/org/briarproject/android/identity/CreateIdentityActivity.java b/briar-android/src/org/briarproject/android/identity/CreateIdentityActivity.java
index 2b293e4e05..d1d37f9fac 100644
--- a/briar-android/src/org/briarproject/android/identity/CreateIdentityActivity.java
+++ b/briar-android/src/org/briarproject/android/identity/CreateIdentityActivity.java
@@ -14,6 +14,7 @@ import android.widget.TextView.OnEditorActionListener;
 import android.widget.Toast;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.android.util.LayoutUtils;
 import org.briarproject.api.crypto.CryptoComponent;
@@ -50,16 +51,16 @@ implements OnEditorActionListener, OnClickListener {
 	private static final Logger LOG =
 			Logger.getLogger(CreateIdentityActivity.class.getName());
 
-	@Inject @CryptoExecutor private Executor cryptoExecutor;
+	@Inject @CryptoExecutor protected Executor cryptoExecutor;
 	private EditText nicknameEntry = null;
 	private Button createIdentityButton = null;
 	private ProgressBar progress = null;
 	private TextView feedback = null;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile CryptoComponent crypto;
-	@Inject private volatile AuthorFactory authorFactory;
-	@Inject private volatile IdentityManager identityManager;
+	@Inject protected volatile CryptoComponent crypto;
+	@Inject protected volatile AuthorFactory authorFactory;
+	@Inject protected volatile IdentityManager identityManager;
 
 	@Override
 	public void onCreate(Bundle state) {
@@ -112,6 +113,11 @@ implements OnEditorActionListener, OnClickListener {
 		setContentView(layout);
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	private void enableOrDisableCreateButton() {
 		if (progress == null) return; // Not created yet
 		createIdentityButton.setEnabled(validateNickname());
diff --git a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java b/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
index 3ae2ae4bce..39f2b578eb 100644
--- a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
+++ b/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
@@ -5,6 +5,7 @@ import android.os.Bundle;
 import android.widget.Toast;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
 import org.briarproject.api.android.ReferenceManager;
 import org.briarproject.api.crypto.CryptoComponent;
@@ -38,9 +39,9 @@ implements InvitationListener {
 	private static final Logger LOG =
 			Logger.getLogger(AddContactActivity.class.getName());
 
-	@Inject private CryptoComponent crypto;
-	@Inject private InvitationTaskFactory invitationTaskFactory;
-	@Inject private ReferenceManager referenceManager;
+	@Inject protected CryptoComponent crypto;
+	@Inject protected InvitationTaskFactory invitationTaskFactory;
+	@Inject protected ReferenceManager referenceManager;
 	private AddContactView view = null;
 	private InvitationTask task = null;
 	private long taskHandle = -1;
@@ -53,7 +54,7 @@ implements InvitationListener {
 	private String contactName = null;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile IdentityManager identityManager;
+	@Inject protected volatile IdentityManager identityManager;
 
 	@Override
 	public void onCreate(Bundle state) {
@@ -138,6 +139,11 @@ implements InvitationListener {
 		}
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	private void showToastAndFinish() {
 		String format = getString(R.string.contact_added_toast);
 		String text = String.format(format, contactName);
diff --git a/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java b/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java
index 912d28cceb..80a997b266 100644
--- a/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java
+++ b/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java
@@ -24,8 +24,6 @@ import java.util.Collection;
 
 import javax.inject.Inject;
 
-import roboguice.RoboGuice;
-
 import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
 import static android.bluetooth.BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION;
 import static org.briarproject.android.identity.LocalAuthorItem.NEW;
@@ -35,7 +33,7 @@ import static org.briarproject.android.invitation.AddContactActivity.REQUEST_CRE
 class ChooseIdentityView extends AddContactView
 implements OnItemSelectedListener, OnClickListener {
 
-	@Inject private CryptoComponent crypto;
+	@Inject protected CryptoComponent crypto;
 	private LocalAuthorSpinnerAdapter adapter = null;
 	private Spinner spinner = null;
 
@@ -46,7 +44,8 @@ implements OnItemSelectedListener, OnClickListener {
 	void populate() {
 		removeAllViews();
 		Context ctx = getContext();
-		RoboGuice.injectMembers(ctx, this);
+		// TODO
+//		RoboGuice.injectMembers(ctx, this);
 
 		LayoutInflater inflater = (LayoutInflater) ctx.getSystemService
 				(Context.LAYOUT_INFLATER_SERVICE);
diff --git a/briar-android/src/org/briarproject/android/panic/ExitActivity.java b/briar-android/src/org/briarproject/android/panic/ExitActivity.java
index 9cfb775d24..4417c1fe8f 100644
--- a/briar-android/src/org/briarproject/android/panic/ExitActivity.java
+++ b/briar-android/src/org/briarproject/android/panic/ExitActivity.java
@@ -3,6 +3,7 @@ package org.briarproject.android.panic;
 import android.os.Build;
 import android.os.Bundle;
 
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BaseActivity;
 
 import java.util.logging.Logger;
@@ -20,4 +21,9 @@ public class ExitActivity extends BaseActivity {
 		LOG.info("Exiting");
 		System.exit(0);
 	}
+
+	@Override
+	public void injectActivity(AndroidComponent component) {
+
+	}
 }
\ No newline at end of file
diff --git a/briar-android/src/org/briarproject/android/panic/PanicPreferencesActivity.java b/briar-android/src/org/briarproject/android/panic/PanicPreferencesActivity.java
index 13556f838d..c25461c347 100644
--- a/briar-android/src/org/briarproject/android/panic/PanicPreferencesActivity.java
+++ b/briar-android/src/org/briarproject/android/panic/PanicPreferencesActivity.java
@@ -5,6 +5,7 @@ import android.support.v7.app.ActionBar;
 import android.view.MenuItem;
 
 import org.briarproject.R;
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
 
 public class PanicPreferencesActivity extends BriarActivity {
@@ -22,6 +23,11 @@ public class PanicPreferencesActivity extends BriarActivity {
 		setContentView(R.layout.activity_panic_preferences);
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	public boolean onOptionsItemSelected(MenuItem item) {
 		if (item.getItemId() == android.R.id.home) {
 			onBackPressed();
diff --git a/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java b/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
index 2dd25617c0..5e71c113fe 100644
--- a/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
+++ b/briar-android/src/org/briarproject/android/panic/PanicResponderActivity.java
@@ -7,12 +7,16 @@ import android.os.Build;
 import android.os.Bundle;
 import android.support.v7.preference.PreferenceManager;
 
+import org.briarproject.android.AndroidComponent;
 import org.briarproject.android.BriarActivity;
-import org.briarproject.android.util.AndroidUtils;
+import org.briarproject.api.db.DatabaseConfig;
+import org.briarproject.util.FileUtils;
 import org.iilab.IilabEngineeringRSA2048Pin;
 
 import java.util.logging.Logger;
 
+import javax.inject.Inject;
+
 import info.guardianproject.GuardianProjectRSA4096;
 import info.guardianproject.panic.Panic;
 import info.guardianproject.panic.PanicResponder;
@@ -26,6 +30,7 @@ public class PanicResponderActivity extends BriarActivity {
 
 	private static final Logger LOG =
 			Logger.getLogger(PanicResponderActivity.class.getName());
+	@Inject protected DatabaseConfig databaseConfig;
 
 	@Override
 	public void onCreate(Bundle savedInstanceState) {
@@ -95,13 +100,20 @@ public class PanicResponderActivity extends BriarActivity {
 		}
 	}
 
+	@Override
+	public void injectActivity(AndroidComponent component) {
+		component.inject(this);
+	}
+
 	private void deleteAllData() {
 		new Thread() {
 			@Override
 			public void run() {
 				clearSharedPrefs();
 				// TODO somehow delete/shred the database more thoroughly
-				AndroidUtils.deleteAppData(PanicResponderActivity.this);
+				FileUtils
+						.deleteFileOrDir(
+								databaseConfig.getDatabaseDirectory());
 				PanicResponder.deleteAllAppData(PanicResponderActivity.this);
 
 				// nothing left to do after everything is deleted,
diff --git a/briar-android/src/org/briarproject/android/util/AuthorView.java b/briar-android/src/org/briarproject/android/util/AuthorView.java
index 0f247ce7cd..7a5d38f9e1 100644
--- a/briar-android/src/org/briarproject/android/util/AuthorView.java
+++ b/briar-android/src/org/briarproject/android/util/AuthorView.java
@@ -16,11 +16,10 @@ import org.briarproject.api.identity.AuthorId;
 import javax.inject.Inject;
 
 import im.delight.android.identicons.IdenticonDrawable;
-import roboguice.RoboGuice;
 
 public class AuthorView extends FrameLayout {
 
-	@Inject private CryptoComponent crypto;
+	@Inject protected CryptoComponent crypto;
 	private ImageView avatarView;
 	private TextView nameView;
 	private ImageView statusView;
@@ -45,7 +44,6 @@ public class AuthorView extends FrameLayout {
 	}
 
 	private void initViews() {
-		RoboGuice.injectMembers(getContext(), this);
 		if (isInEditMode())
 			return;
 
diff --git a/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java b/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java
index d9625b36a6..678725df86 100644
--- a/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java
+++ b/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java
@@ -3,7 +3,6 @@ package org.briarproject.plugins;
 import android.app.Application;
 import android.content.Context;
 
-import com.google.inject.Provides;
 
 import org.briarproject.api.android.AndroidExecutor;
 import org.briarproject.api.event.EventBus;
@@ -24,6 +23,10 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.concurrent.Executor;
 
+import dagger.Module;
+import dagger.Provides;
+
+@Module
 public class AndroidPluginsModule extends PluginsModule {
 
 	@Provides
diff --git a/briar-android/src/org/briarproject/system/AndroidLocationUtils.java b/briar-android/src/org/briarproject/system/AndroidLocationUtils.java
index 3fe05e036a..e5907c9c00 100644
--- a/briar-android/src/org/briarproject/system/AndroidLocationUtils.java
+++ b/briar-android/src/org/briarproject/system/AndroidLocationUtils.java
@@ -6,13 +6,13 @@ import android.content.Context;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 
-import com.google.inject.Inject;
-
 import org.briarproject.api.system.LocationUtils;
 
 import java.util.Locale;
 import java.util.logging.Logger;
 
+import javax.inject.Inject;
+
 import static android.content.Context.TELEPHONY_SERVICE;
 
 class AndroidLocationUtils implements LocationUtils {
diff --git a/briar-android/src/org/briarproject/system/AndroidSystemModule.java b/briar-android/src/org/briarproject/system/AndroidSystemModule.java
index 9528cb7dbe..2cd79468cc 100644
--- a/briar-android/src/org/briarproject/system/AndroidSystemModule.java
+++ b/briar-android/src/org/briarproject/system/AndroidSystemModule.java
@@ -1,18 +1,37 @@
 package org.briarproject.system;
 
-import com.google.inject.AbstractModule;
+
+import android.app.Application;
 
 import org.briarproject.api.system.Clock;
 import org.briarproject.api.system.LocationUtils;
 import org.briarproject.api.system.SeedProvider;
 import org.briarproject.api.system.Timer;
 
-public class AndroidSystemModule extends AbstractModule {
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class AndroidSystemModule {
 
-	protected void configure() {
-		bind(Clock.class).to(SystemClock.class);
-		bind(Timer.class).to(SystemTimer.class);
-		bind(SeedProvider.class).to(AndroidSeedProvider.class);
-		bind(LocationUtils.class).to(AndroidLocationUtils.class);
+	@Provides
+	Clock provideClock() {
+		return new SystemClock();
 	}
+
+	@Provides
+	Timer provideTimer() {
+		return new SystemTimer();
+	}
+
+	@Provides
+	SeedProvider provideSeedProvider(final Application app) {
+		return new AndroidSeedProvider(app);
+	}
+
+	@Provides
+	LocationUtils provideLocationUtils(final Application app) {
+		return new AndroidLocationUtils(app);
+	}
+
 }
diff --git a/briar-api/build.gradle b/briar-api/build.gradle
index bd5a660938..fc84125c80 100644
--- a/briar-api/build.gradle
+++ b/briar-api/build.gradle
@@ -9,17 +9,17 @@ repositories {
 }
 
 dependencies {
-	compile "javax.inject:javax.inject:1"
-	compile "com.google.inject:guice:3.0:no_aop"
+	compile "com.google.dagger:dagger:2.0.2"
+	compile 'com.google.dagger:dagger-compiler:2.0.2'
 }
 
 dependencyVerification {
 	verify = [
-			'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
-			'com.google.inject:guice:7c0624d0986ae2bd7a8f1cf4789bcaae5b82a042a7e3d27ba3041ed7b7f2cd3a',
-			'aopalliance:aopalliance:0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08',
-			'org.sonatype.sisu.inject:cglib:42e1dfb26becbf1a633f25b47e39fcc422b85e77e4c0468d9a44f885f5fa0be2',
-			'asm:asm:333ff5369043975b7e031b8b27206937441854738e038c1f47f98d072a20437a',
+//			'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
+//			'com.google.inject:guice:7c0624d0986ae2bd7a8f1cf4789bcaae5b82a042a7e3d27ba3041ed7b7f2cd3a',
+//			'aopalliance:aopalliance:0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08',
+//			'org.sonatype.sisu.inject:cglib:42e1dfb26becbf1a633f25b47e39fcc422b85e77e4c0468d9a44f885f5fa0be2',
+//			'asm:asm:333ff5369043975b7e031b8b27206937441854738e038c1f47f98d072a20437a',
 	]
 }
 
diff --git a/briar-api/src/org/briarproject/api/crypto/CryptoExecutor.java b/briar-api/src/org/briarproject/api/crypto/CryptoExecutor.java
index c527c5812a..340ee08843 100644
--- a/briar-api/src/org/briarproject/api/crypto/CryptoExecutor.java
+++ b/briar-api/src/org/briarproject/api/crypto/CryptoExecutor.java
@@ -5,13 +5,21 @@ import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.ElementType.PARAMETER;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
+import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
-import com.google.inject.BindingAnnotation;
+import javax.inject.Qualifier;
+
+//import com.google.inject.BindingAnnotation;
 
 /** Annotation for injecting the executor for long-running crypto tasks. */
-@BindingAnnotation
-@Target({ FIELD, METHOD, PARAMETER })
+//@BindingAnnotation
+//@Target({ FIELD, METHOD, PARAMETER })
+//@Retention(RUNTIME)
+//public @interface CryptoExecutor {}
+
+@Qualifier
+@Target({FIELD, METHOD, PARAMETER})
 @Retention(RUNTIME)
 public @interface CryptoExecutor {}
diff --git a/briar-api/src/org/briarproject/api/db/DatabaseExecutor.java b/briar-api/src/org/briarproject/api/db/DatabaseExecutor.java
index 22d04d0150..f682121d07 100644
--- a/briar-api/src/org/briarproject/api/db/DatabaseExecutor.java
+++ b/briar-api/src/org/briarproject/api/db/DatabaseExecutor.java
@@ -8,7 +8,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
-import com.google.inject.BindingAnnotation;
+import javax.inject.Qualifier;
 
 /**
  * Annotation for injecting the executor for database tasks.
@@ -17,7 +17,7 @@ import com.google.inject.BindingAnnotation;
  * they're submitted, tasks are not executed concurrently, and submitting a
  * task will never block.
  */
-@BindingAnnotation
+@Qualifier
 @Target({ FIELD, METHOD, PARAMETER })
 @Retention(RUNTIME)
 public @interface DatabaseExecutor {}
diff --git a/briar-api/src/org/briarproject/api/lifecycle/IoExecutor.java b/briar-api/src/org/briarproject/api/lifecycle/IoExecutor.java
index 01e0ea4995..02bc5bf875 100644
--- a/briar-api/src/org/briarproject/api/lifecycle/IoExecutor.java
+++ b/briar-api/src/org/briarproject/api/lifecycle/IoExecutor.java
@@ -8,10 +8,10 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
-import com.google.inject.BindingAnnotation;
+import javax.inject.Qualifier;
 
 /** Annotation for injecting the executor used by long-lived IO tasks. */
-@BindingAnnotation
+@Qualifier
 @Target({ FIELD, METHOD, PARAMETER })
 @Retention(RUNTIME)
 public @interface IoExecutor {}
\ No newline at end of file
diff --git a/briar-core/src/org/briarproject/contact/ContactManagerImpl.java b/briar-core/src/org/briarproject/contact/ContactManagerImpl.java
index 4f5698acfa..83de8540da 100644
--- a/briar-core/src/org/briarproject/contact/ContactManagerImpl.java
+++ b/briar-core/src/org/briarproject/contact/ContactManagerImpl.java
@@ -1,7 +1,5 @@
 package org.briarproject.contact;
 
-import com.google.inject.Inject;
-
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.contact.ContactManager;
@@ -21,7 +19,22 @@ import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+<<<<<<< 08099714bab27d1ed48a8bee431a35a38098ecec
 class ContactManagerImpl implements ContactManager, RemoveIdentityHook {
+=======
+import javax.inject.Inject;
+
+import static java.util.logging.Level.WARNING;
+import static org.briarproject.api.db.StorageStatus.ACTIVE;
+import static org.briarproject.api.db.StorageStatus.ADDING;
+import static org.briarproject.api.db.StorageStatus.REMOVING;
+
+class ContactManagerImpl implements ContactManager, Service,
+		RemoveIdentityHook {
+
+	private static final Logger LOG =
+			Logger.getLogger(ContactManagerImpl.class.getName());
+>>>>>>> Switched Roboguice/Guice out for Dagger 2
 
 	private final DatabaseComponent db;
 	private final KeyManager keyManager;
diff --git a/briar-core/src/org/briarproject/contact/ContactModule.java b/briar-core/src/org/briarproject/contact/ContactModule.java
index 8e9f3d632b..55bb854b33 100644
--- a/briar-core/src/org/briarproject/contact/ContactModule.java
+++ b/briar-core/src/org/briarproject/contact/ContactModule.java
@@ -1,21 +1,23 @@
 package org.briarproject.contact;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-
 import org.briarproject.api.contact.ContactManager;
 import org.briarproject.api.identity.IdentityManager;
+import org.briarproject.api.lifecycle.LifecycleManager;
 
 import javax.inject.Singleton;
 
-public class ContactModule extends AbstractModule {
+import dagger.Module;
+import dagger.Provides;
 
-	@Override
-	protected void configure() {}
+@Module
+public class ContactModule {
 
-	@Provides @Singleton
-	ContactManager getContactManager(IdentityManager identityManager,
+	@Provides
+	@Singleton
+	ContactManager getContactManager(LifecycleManager lifecycleManager,
+			IdentityManager identityManager,
 			ContactManagerImpl contactManager) {
+		lifecycleManager.register(contactManager);
 		identityManager.registerRemoveIdentityHook(contactManager);
 		return contactManager;
 	}
diff --git a/briar-core/src/org/briarproject/crypto/CryptoModule.java b/briar-core/src/org/briarproject/crypto/CryptoModule.java
index 5df7e38f0e..04e216b80b 100644
--- a/briar-core/src/org/briarproject/crypto/CryptoModule.java
+++ b/briar-core/src/org/briarproject/crypto/CryptoModule.java
@@ -1,14 +1,12 @@
 package org.briarproject.crypto;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-
 import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.crypto.CryptoExecutor;
 import org.briarproject.api.crypto.PasswordStrengthEstimator;
 import org.briarproject.api.crypto.StreamDecrypterFactory;
 import org.briarproject.api.crypto.StreamEncrypterFactory;
 import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.api.system.SeedProvider;
 
 import java.security.SecureRandom;
 import java.util.concurrent.BlockingQueue;
@@ -18,13 +16,20 @@ import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.RejectedExecutionHandler;
 import java.util.concurrent.ThreadPoolExecutor;
 
+import javax.inject.Provider;
 import javax.inject.Singleton;
 
+import dagger.Module;
+import dagger.Provides;
+
 import static java.util.concurrent.TimeUnit.SECONDS;
 
-public class CryptoModule extends AbstractModule {
+@Module
+public class CryptoModule {
 
-	/** The maximum number of executor threads. */
+	/**
+	 * The maximum number of executor threads.
+	 */
 	private static final int MAX_EXECUTOR_THREADS =
 			Runtime.getRuntime().availableProcessors();
 
@@ -41,19 +46,37 @@ public class CryptoModule extends AbstractModule {
 				60, SECONDS, queue, policy);
 	}
 
-	@Override
-	protected void configure() {
-		bind(AuthenticatedCipher.class).to(
-				XSalsa20Poly1305AuthenticatedCipher.class);
-		bind(CryptoComponent.class).to(
-				CryptoComponentImpl.class).in(Singleton.class);
-		bind(PasswordStrengthEstimator.class).to(
-				PasswordStrengthEstimatorImpl.class);
-		bind(StreamDecrypterFactory.class).to(StreamDecrypterFactoryImpl.class);
-		bind(StreamEncrypterFactory.class).to(StreamEncrypterFactoryImpl.class);
+	@Provides
+	AuthenticatedCipher provideAuthenticatedCipher() {
+		return new XSalsa20Poly1305AuthenticatedCipher();
+	}
+
+	@Provides
+	@Singleton
+	CryptoComponent provideCryptoComponent(SeedProvider seedProvider) {
+		return new CryptoComponentImpl(seedProvider);
+	}
+
+	@Provides
+	PasswordStrengthEstimator providePasswordStrengthEstimator() {
+		return new PasswordStrengthEstimatorImpl();
 	}
 
-	@Provides @Singleton @CryptoExecutor
+	@Provides
+	StreamDecrypterFactory provideStreamDecrypterFactory(
+			Provider<AuthenticatedCipher> cipherProvider) {
+		return new StreamDecrypterFactoryImpl(cipherProvider);
+	}
+
+	@Provides
+	StreamEncrypterFactory provideStreamEncrypterFactory(CryptoComponent crypto,
+			Provider<AuthenticatedCipher> cipherProvider) {
+		return new StreamEncrypterFactoryImpl(crypto, cipherProvider);
+	}
+
+	@Provides
+	@Singleton
+	@CryptoExecutor
 	Executor getCryptoExecutor(LifecycleManager lifecycleManager) {
 		lifecycleManager.registerForShutdown(cryptoExecutor);
 		return cryptoExecutor;
@@ -63,4 +86,5 @@ public class CryptoModule extends AbstractModule {
 	SecureRandom getSecureRandom(CryptoComponent crypto) {
 		return crypto.getSecureRandom();
 	}
+
 }
diff --git a/briar-core/src/org/briarproject/data/DataModule.java b/briar-core/src/org/briarproject/data/DataModule.java
index c3fe841aee..5c77b8ac73 100644
--- a/briar-core/src/org/briarproject/data/DataModule.java
+++ b/briar-core/src/org/briarproject/data/DataModule.java
@@ -1,19 +1,35 @@
 package org.briarproject.data;
 
-import com.google.inject.AbstractModule;
 
 import org.briarproject.api.data.BdfReaderFactory;
 import org.briarproject.api.data.BdfWriterFactory;
 import org.briarproject.api.data.MetadataEncoder;
 import org.briarproject.api.data.MetadataParser;
 
-public class DataModule extends AbstractModule {
+import dagger.Module;
+import dagger.Provides;
 
-	@Override
-	protected void configure() {
-		bind(BdfReaderFactory.class).to(BdfReaderFactoryImpl.class);
-		bind(BdfWriterFactory.class).to(BdfWriterFactoryImpl.class);
-		bind(MetadataParser.class).to(MetadataParserImpl.class);
-		bind(MetadataEncoder.class).to(MetadataEncoderImpl.class);
+@Module
+public class DataModule {
+
+	@Provides
+	BdfReaderFactory provideBdfReaderFactory() {
+		return new BdfReaderFactoryImpl();
+	}
+
+	@Provides
+	BdfWriterFactory provideBdfWriterFactory() {
+		return new BdfWriterFactoryImpl();
+	}
+
+	@Provides
+	MetadataParser provideMetaDataParser() {
+		return new MetadataParserImpl();
+	}
+
+	@Provides
+	MetadataEncoder provideMetaDataEncoider() {
+		return new MetadataEncoderImpl();
 	}
+
 }
diff --git a/briar-core/src/org/briarproject/db/DatabaseModule.java b/briar-core/src/org/briarproject/db/DatabaseModule.java
index 6a050ed44b..74512c9c0f 100644
--- a/briar-core/src/org/briarproject/db/DatabaseModule.java
+++ b/briar-core/src/org/briarproject/db/DatabaseModule.java
@@ -1,8 +1,5 @@
 package org.briarproject.db;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-
 import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DatabaseConfig;
 import org.briarproject.api.db.DatabaseExecutor;
@@ -20,11 +17,16 @@ import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.RejectedExecutionHandler;
 import java.util.concurrent.ThreadPoolExecutor;
 
+import javax.inject.Named;
 import javax.inject.Singleton;
 
+import dagger.Module;
+import dagger.Provides;
+
 import static java.util.concurrent.TimeUnit.SECONDS;
 
-public class DatabaseModule extends AbstractModule {
+@Module
+public class DatabaseModule {
 
 	private final ExecutorService databaseExecutor;
 
@@ -39,30 +41,28 @@ public class DatabaseModule extends AbstractModule {
 				policy);
 	}
 
-	@Override
-	protected void configure() {}
-
-	@Provides @Singleton
-	Database<Connection> getDatabase(DatabaseConfig config,
+	@Provides
+	@Singleton
+	Database<Connection> provideDatabase(DatabaseConfig config,
 			SecureRandom random, Clock clock) {
 		return new H2Database(config, random, clock);
 	}
 
 	@Provides @Singleton
-	DatabaseComponent getDatabaseComponent(Database<Connection> db,
+	DatabaseComponent provideDatabaseComponent(Database<Connection> db,
 			EventBus eventBus, ShutdownManager shutdown) {
 		return new DatabaseComponentImpl<Connection>(db, Connection.class,
 				eventBus, shutdown);
 	}
 
 	@Provides @Singleton @DatabaseExecutor
-	ExecutorService getDatabaseExecutor(LifecycleManager lifecycleManager) {
+	ExecutorService provideDatabaseExecutorService(LifecycleManager lifecycleManager) {
 		lifecycleManager.registerForShutdown(databaseExecutor);
 		return databaseExecutor;
 	}
 
 	@Provides @Singleton @DatabaseExecutor
-	Executor getDatabaseExecutor(@DatabaseExecutor ExecutorService dbExecutor) {
+	Executor provideDatabaseExecutor(@DatabaseExecutor ExecutorService dbExecutor) {
 		return dbExecutor;
 	}
 }
diff --git a/briar-core/src/org/briarproject/event/EventModule.java b/briar-core/src/org/briarproject/event/EventModule.java
index 34aa23eb66..e7f92f0379 100644
--- a/briar-core/src/org/briarproject/event/EventModule.java
+++ b/briar-core/src/org/briarproject/event/EventModule.java
@@ -2,13 +2,17 @@ package org.briarproject.event;
 
 import org.briarproject.api.event.EventBus;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Singleton;
+import javax.inject.Singleton;
 
-public class EventModule extends AbstractModule {
+import dagger.Module;
+import dagger.Provides;
 
-	@Override
-	protected void configure() {
-		bind(EventBus.class).to(EventBusImpl.class).in(Singleton.class);
+@Module
+public class EventModule {
+
+	@Provides
+	@Singleton
+	EventBus provideEventBus() {
+		return new EventBusImpl();
 	}
 }
diff --git a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java
index fe51b778b3..534369d2d5 100644
--- a/briar-core/src/org/briarproject/forum/ForumManagerImpl.java
+++ b/briar-core/src/org/briarproject/forum/ForumManagerImpl.java
@@ -1,14 +1,15 @@
 package org.briarproject.forum;
 
-import com.google.inject.Inject;
-
 import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
+import org.briarproject.api.data.BdfReader;
+import org.briarproject.api.data.BdfReaderFactory;
+import org.briarproject.api.data.MetadataEncoder;
+import org.briarproject.api.data.MetadataParser;
 import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.db.Metadata;
 import org.briarproject.api.db.Transaction;
 import org.briarproject.api.forum.Forum;
 import org.briarproject.api.forum.ForumManager;
@@ -23,6 +24,8 @@ import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.util.StringUtils;
 
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -31,10 +34,18 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
 
+import static java.util.logging.Level.WARNING;
+import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
+import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
+import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
 import static org.briarproject.api.identity.Author.Status.ANONYMOUS;
 import static org.briarproject.api.identity.Author.Status.UNKNOWN;
 import static org.briarproject.api.identity.Author.Status.VERIFIED;
+import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
 
 class ForumManagerImpl implements ForumManager {
 
@@ -42,13 +53,21 @@ class ForumManagerImpl implements ForumManager {
 			"859a7be50dca035b64bd6902fb797097"
 					+ "795af837abbf8c16d750b3c2ccc186ea"));
 
+	private static final Logger LOG =
+			Logger.getLogger(ForumManagerImpl.class.getName());
+
 	private final DatabaseComponent db;
-	private final ClientHelper clientHelper;
+	private final BdfReaderFactory bdfReaderFactory;
+	private final MetadataEncoder metadataEncoder;
+	private final MetadataParser metadataParser;
 
 	@Inject
-	ForumManagerImpl(DatabaseComponent db, ClientHelper clientHelper) {
+	ForumManagerImpl(DatabaseComponent db, BdfReaderFactory bdfReaderFactory,
+			MetadataEncoder metadataEncoder, MetadataParser metadataParser) {
 		this.db = db;
-		this.clientHelper = clientHelper;
+		this.bdfReaderFactory = bdfReaderFactory;
+		this.metadataEncoder = metadataEncoder;
+		this.metadataParser = metadataParser;
 	}
 
 	@Override
@@ -59,21 +78,29 @@ class ForumManagerImpl implements ForumManager {
 	@Override
 	public void addLocalPost(ForumPost p) throws DbException {
 		try {
-			BdfDictionary meta = new BdfDictionary();
-			meta.put("timestamp", p.getMessage().getTimestamp());
-			if (p.getParent() != null) meta.put("parent", p.getParent());
+			BdfDictionary d = new BdfDictionary();
+			d.put("timestamp", p.getMessage().getTimestamp());
+			if (p.getParent() != null)
+				d.put("parent", p.getParent().getBytes());
 			if (p.getAuthor() != null) {
 				Author a = p.getAuthor();
-				BdfDictionary authorMeta = new BdfDictionary();
-				authorMeta.put("id", a.getId());
-				authorMeta.put("name", a.getName());
-				authorMeta.put("publicKey", a.getPublicKey());
-				meta.put("author", authorMeta);
+				BdfDictionary d1 = new BdfDictionary();
+				d1.put("id", a.getId().getBytes());
+				d1.put("name", a.getName());
+				d1.put("publicKey", a.getPublicKey());
+				d.put("author", d1);
+			}
+			d.put("contentType", p.getContentType());
+			d.put("local", true);
+			d.put("read", true);
+			Metadata meta = metadataEncoder.encode(d);
+			Transaction txn = db.startTransaction();
+			try {
+				db.addLocalMessage(txn, p.getMessage(), CLIENT_ID, meta, true);
+				txn.setComplete();
+			} finally {
+				db.endTransaction(txn);
 			}
-			meta.put("contentType", p.getContentType());
-			meta.put("local", true);
-			meta.put("read", true);
-			clientHelper.addLocalMessage(p.getMessage(), CLIENT_ID, meta, true);
 		} catch (FormatException e) {
 			throw new RuntimeException(e);
 		}
@@ -118,11 +145,34 @@ class ForumManagerImpl implements ForumManager {
 	@Override
 	public byte[] getPostBody(MessageId m) throws DbException {
 		try {
-			// Parent ID, author, content type, forum post body, signature
-			BdfList message = clientHelper.getMessageAsList(m);
-			return message.getRaw(3);
+			byte[] raw;
+			Transaction txn = db.startTransaction();
+			try {
+				raw = db.getRawMessage(txn, m);
+				txn.setComplete();
+			} finally {
+				db.endTransaction(txn);
+			}
+			ByteArrayInputStream in = new ByteArrayInputStream(raw,
+					MESSAGE_HEADER_LENGTH, raw.length - MESSAGE_HEADER_LENGTH);
+			BdfReader r = bdfReaderFactory.createReader(in);
+			r.readListStart();
+			if (r.hasRaw()) r.skipRaw(); // Parent ID
+			else r.skipNull(); // No parent
+			if (r.hasList()) r.skipList(); // Author
+			else r.skipNull(); // No author
+			r.skipString(); // Content type
+			byte[] postBody = r.readRaw(MAX_FORUM_POST_BODY_LENGTH);
+			if (r.hasRaw()) r.skipRaw(); // Signature
+			else r.skipNull();
+			r.readListEnd();
+			if (!r.eof()) throw new FormatException();
+			return postBody;
 		} catch (FormatException e) {
 			throw new DbException(e);
+		} catch (IOException e) {
+			// Shouldn't happen with ByteArrayInputStream
+			throw new RuntimeException(e);
 		}
 	}
 
@@ -131,7 +181,7 @@ class ForumManagerImpl implements ForumManager {
 			throws DbException {
 		Set<AuthorId> localAuthorIds = new HashSet<AuthorId>();
 		Set<AuthorId> contactAuthorIds = new HashSet<AuthorId>();
-		Map<MessageId, BdfDictionary> metadata;
+		Map<MessageId, Metadata> metadata;
 		Transaction txn = db.startTransaction();
 		try {
 			// Load the IDs of the user's identities
@@ -141,22 +191,20 @@ class ForumManagerImpl implements ForumManager {
 			for (Contact c : db.getContacts(txn))
 				contactAuthorIds.add(c.getAuthor().getId());
 			// Load the metadata
-			metadata = clientHelper.getMessageMetadataAsDictionary(txn, g);
+			metadata = db.getMessageMetadata(txn, g);
 			txn.setComplete();
-		} catch (FormatException e) {
-			throw new DbException(e);
 		} finally {
 			db.endTransaction(txn);
 		}
 		// Parse the metadata
 		Collection<ForumPostHeader> headers = new ArrayList<ForumPostHeader>();
-		for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
+		for (Entry<MessageId, Metadata> e : metadata.entrySet()) {
 			try {
-				BdfDictionary meta = entry.getValue();
-				long timestamp = meta.getLong("timestamp");
+				BdfDictionary d = metadataParser.parse(e.getValue());
+				long timestamp = d.getLong("timestamp");
 				Author author = null;
 				Author.Status authorStatus = ANONYMOUS;
-				BdfDictionary d1 = meta.getDictionary("author", null);
+				BdfDictionary d1 = d.getDictionary("author", null);
 				if (d1 != null) {
 					AuthorId authorId = new AuthorId(d1.getRaw("id"));
 					String name = d1.getString("name");
@@ -168,12 +216,13 @@ class ForumManagerImpl implements ForumManager {
 						authorStatus = VERIFIED;
 					else authorStatus = UNKNOWN;
 				}
-				String contentType = meta.getString("contentType");
-				boolean read = meta.getBoolean("read");
-				headers.add(new ForumPostHeader(entry.getKey(), timestamp,
-						author, authorStatus, contentType, read));
-			} catch (FormatException e) {
-				throw new DbException(e);
+				String contentType = d.getString("contentType");
+				boolean read = d.getBoolean("read");
+				headers.add(new ForumPostHeader(e.getKey(), timestamp, author,
+						authorStatus, contentType, read));
+			} catch (FormatException ex) {
+				if (LOG.isLoggable(WARNING))
+					LOG.log(WARNING, ex.toString(), ex);
 			}
 		}
 		return headers;
@@ -182,18 +231,36 @@ class ForumManagerImpl implements ForumManager {
 	@Override
 	public void setReadFlag(MessageId m, boolean read) throws DbException {
 		try {
-			BdfDictionary meta = new BdfDictionary();
-			meta.put("read", read);
-			clientHelper.mergeMessageMetadata(m, meta);
+			BdfDictionary d = new BdfDictionary();
+			d.put("read", read);
+			Metadata meta = metadataEncoder.encode(d);
+			Transaction txn = db.startTransaction();
+			try {
+				db.mergeMessageMetadata(txn, m, meta);
+				txn.setComplete();
+			} finally {
+				db.endTransaction(txn);
+			}
 		} catch (FormatException e) {
 			throw new RuntimeException(e);
 		}
 	}
 
 	private Forum parseForum(Group g) throws FormatException {
-		byte[] descriptor = g.getDescriptor();
-		// Name, salt
-		BdfList forum = clientHelper.toList(descriptor, 0, descriptor.length);
-		return new Forum(g, forum.getString(0), forum.getRaw(1));
+		ByteArrayInputStream in = new ByteArrayInputStream(g.getDescriptor());
+		BdfReader r = bdfReaderFactory.createReader(in);
+		try {
+			r.readListStart();
+			String name = r.readString(MAX_FORUM_NAME_LENGTH);
+			byte[] salt = r.readRaw(FORUM_SALT_LENGTH);
+			r.readListEnd();
+			if (!r.eof()) throw new FormatException();
+			return new Forum(g, name, salt);
+		} catch (FormatException e) {
+			throw e;
+		} catch (IOException e) {
+			// Shouldn't happen with ByteArrayInputStream
+			throw new RuntimeException(e);
+		}
 	}
 }
diff --git a/briar-core/src/org/briarproject/forum/ForumModule.java b/briar-core/src/org/briarproject/forum/ForumModule.java
index 19e7ce06f1..e58b7e2a01 100644
--- a/briar-core/src/org/briarproject/forum/ForumModule.java
+++ b/briar-core/src/org/briarproject/forum/ForumModule.java
@@ -1,54 +1,80 @@
 package org.briarproject.forum;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-
-import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.contact.ContactManager;
 import org.briarproject.api.crypto.CryptoComponent;
+import org.briarproject.api.data.BdfReaderFactory;
+import org.briarproject.api.data.BdfWriterFactory;
 import org.briarproject.api.data.MetadataEncoder;
+import org.briarproject.api.data.MetadataParser;
+import org.briarproject.api.data.ObjectReader;
+import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.forum.ForumManager;
 import org.briarproject.api.forum.ForumPostFactory;
 import org.briarproject.api.forum.ForumSharingManager;
-import org.briarproject.api.identity.AuthorFactory;
+import org.briarproject.api.identity.Author;
+import org.briarproject.api.sync.MessageFactory;
 import org.briarproject.api.sync.ValidationManager;
 import org.briarproject.api.system.Clock;
 
 import javax.inject.Singleton;
 
-public class ForumModule extends AbstractModule {
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class ForumModule {
+
+	@Provides
+	@Singleton
+	ForumManager provideForumManager(DatabaseComponent db,
+			ContactManager contactManager,
+			BdfReaderFactory bdfReaderFactory, MetadataEncoder metadataEncoder,
+			MetadataParser metadataParser) {
+		return new ForumManagerImpl(db, contactManager, bdfReaderFactory,
+				metadataEncoder, metadataParser);
+	}
 
-	@Override
-	protected void configure() {
-		bind(ForumManager.class).to(ForumManagerImpl.class).in(Singleton.class);
-		bind(ForumPostFactory.class).to(ForumPostFactoryImpl.class);
+	@Provides
+	ForumPostFactory provideForumPostFactory(CryptoComponent crypto,
+			MessageFactory messageFactory,
+			BdfWriterFactory bdfWriterFactory) {
+		return new ForumPostFactoryImpl(crypto, messageFactory,
+				bdfWriterFactory);
 	}
 
-	@Provides @Singleton
-	ForumPostValidator getForumPostValidator(
+	@Provides
+	@Singleton
+	ForumPostValidator provideForumPostValidator(
 			ValidationManager validationManager, CryptoComponent crypto,
-			AuthorFactory authorFactory, ClientHelper clientHelper,
-			MetadataEncoder metadataEncoder, Clock clock) {
+			BdfReaderFactory bdfReaderFactory,
+			BdfWriterFactory bdfWriterFactory,
+			ObjectReader<Author> authorReader, MetadataEncoder metadataEncoder,
+			Clock clock) {
 		ForumPostValidator validator = new ForumPostValidator(crypto,
-				authorFactory, clientHelper, metadataEncoder, clock);
+				bdfReaderFactory, bdfWriterFactory, authorReader,
+				metadataEncoder, clock);
 		validationManager.registerMessageValidator(
 				ForumManagerImpl.CLIENT_ID, validator);
 		return validator;
 	}
 
-	@Provides @Singleton
-	ForumListValidator getForumListValidator(
-			ValidationManager validationManager, ClientHelper clientHelper,
-			MetadataEncoder metadataEncoder, Clock clock) {
-		ForumListValidator validator = new ForumListValidator(clientHelper,
-				metadataEncoder, clock);
+	@Provides
+	@Singleton
+	ForumListValidator provideForumListValidator(
+			ValidationManager validationManager,
+			BdfReaderFactory bdfReaderFactory,
+			MetadataEncoder metadataEncoder) {
+		ForumListValidator validator = new ForumListValidator(bdfReaderFactory,
+				metadataEncoder);
 		validationManager.registerMessageValidator(
 				ForumSharingManagerImpl.CLIENT_ID, validator);
 		return validator;
 	}
 
-	@Provides @Singleton
-	ForumSharingManager getForumSharingManager(ContactManager contactManager,
+	@Provides
+	@Singleton
+	ForumSharingManager provideForumSharingManager(
+			ContactManager contactManager,
 			ValidationManager validationManager,
 			ForumSharingManagerImpl forumSharingManager) {
 		contactManager.registerAddContactHook(forumSharingManager);
diff --git a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
index aa083679df..c916a54e66 100644
--- a/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
+++ b/briar-core/src/org/briarproject/forum/ForumSharingManagerImpl.java
@@ -1,7 +1,5 @@
 package org.briarproject.forum;
 
-import com.google.inject.Inject;
-
 import org.briarproject.api.FormatException;
 import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.clients.PrivateGroupFactory;
@@ -39,6 +37,12 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
+<<<<<<< 08099714bab27d1ed48a8bee431a35a38098ecec
+=======
+import javax.inject.Inject;
+
+import static java.util.logging.Level.WARNING;
+>>>>>>> Switched Roboguice/Guice out for Dagger 2
 import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH;
 import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_NAME_LENGTH;
 import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
diff --git a/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java b/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java
index 0ae2e5aa58..a35a85f6d6 100644
--- a/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java
+++ b/briar-core/src/org/briarproject/identity/IdentityManagerImpl.java
@@ -1,7 +1,5 @@
 package org.briarproject.identity;
 
-import com.google.inject.Inject;
-
 import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.db.Transaction;
@@ -13,7 +11,21 @@ import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
+<<<<<<< 08099714bab27d1ed48a8bee431a35a38098ecec
 class IdentityManagerImpl implements IdentityManager {
+=======
+import javax.inject.Inject;
+
+import static java.util.logging.Level.WARNING;
+import static org.briarproject.api.db.StorageStatus.ACTIVE;
+import static org.briarproject.api.db.StorageStatus.ADDING;
+import static org.briarproject.api.db.StorageStatus.REMOVING;
+
+class IdentityManagerImpl implements IdentityManager, Service {
+
+	private static final Logger LOG =
+			Logger.getLogger(IdentityManagerImpl.class.getName());
+>>>>>>> Switched Roboguice/Guice out for Dagger 2
 
 	private final DatabaseComponent db;
 	private final List<AddIdentityHook> addHooks;
diff --git a/briar-core/src/org/briarproject/identity/IdentityModule.java b/briar-core/src/org/briarproject/identity/IdentityModule.java
index c987a8a55a..78d2b776c8 100644
--- a/briar-core/src/org/briarproject/identity/IdentityModule.java
+++ b/briar-core/src/org/briarproject/identity/IdentityModule.java
@@ -1,23 +1,20 @@
 package org.briarproject.identity;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-
-import org.briarproject.api.data.ObjectReader;
-import org.briarproject.api.identity.Author;
-import org.briarproject.api.identity.AuthorFactory;
+import org.briarproject.api.db.DatabaseComponent;
+import org.briarproject.api.event.EventBus;
 import org.briarproject.api.identity.IdentityManager;
 
-public class IdentityModule extends AbstractModule {
+import javax.inject.Singleton;
 
-	@Override
-	protected void configure() {
-		bind(AuthorFactory.class).to(AuthorFactoryImpl.class);
-		bind(IdentityManager.class).to(IdentityManagerImpl.class);
-	}
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class IdentityModule {
 
 	@Provides
-	ObjectReader<Author> getAuthorReader(AuthorFactory authorFactory) {
-		return new AuthorReader(authorFactory);
+	@Singleton
+	IdentityManager provideIdendityModule(DatabaseComponent db, EventBus eventBus) {
+		return new IdentityManagerImpl(db, eventBus);
 	}
 }
diff --git a/briar-core/src/org/briarproject/invitation/InvitationModule.java b/briar-core/src/org/briarproject/invitation/InvitationModule.java
index 057ec97320..de6d8bde25 100644
--- a/briar-core/src/org/briarproject/invitation/InvitationModule.java
+++ b/briar-core/src/org/briarproject/invitation/InvitationModule.java
@@ -2,14 +2,41 @@ package org.briarproject.invitation;
 
 import javax.inject.Singleton;
 
+import org.briarproject.api.contact.ContactManager;
+import org.briarproject.api.crypto.CryptoComponent;
+import org.briarproject.api.data.BdfReaderFactory;
+import org.briarproject.api.data.BdfWriterFactory;
+import org.briarproject.api.identity.AuthorFactory;
+import org.briarproject.api.identity.IdentityManager;
 import org.briarproject.api.invitation.InvitationTaskFactory;
+import org.briarproject.api.plugins.ConnectionManager;
+import org.briarproject.api.plugins.PluginManager;
+import org.briarproject.api.sync.GroupFactory;
+import org.briarproject.api.system.Clock;
+import org.briarproject.api.transport.KeyManager;
+import org.briarproject.api.transport.StreamReaderFactory;
+import org.briarproject.api.transport.StreamWriterFactory;
 
-import com.google.inject.AbstractModule;
+import dagger.Module;
+import dagger.Provides;
 
-public class InvitationModule extends AbstractModule {
+@Module
+public class InvitationModule {
 
-	protected void configure() {
-		bind(InvitationTaskFactory.class).to(
-				InvitationTaskFactoryImpl.class).in(Singleton.class);
+	@Provides
+	@Singleton
+	InvitationTaskFactory provideInvitationTaskFactory(CryptoComponent crypto,
+			BdfReaderFactory bdfReaderFactory,
+			BdfWriterFactory bdfWriterFactory,
+			StreamReaderFactory streamReaderFactory,
+			StreamWriterFactory streamWriterFactory,
+			AuthorFactory authorFactory, GroupFactory groupFactory,
+			KeyManager keyManager, ConnectionManager connectionManager,
+			IdentityManager identityManager, ContactManager contactManager,
+			Clock clock, PluginManager pluginManager) {
+		return new InvitationTaskFactoryImpl(crypto, bdfReaderFactory,
+				bdfWriterFactory, streamReaderFactory, streamWriterFactory,
+				authorFactory, groupFactory, keyManager, connectionManager,
+				identityManager, contactManager, clock, pluginManager);
 	}
 }
diff --git a/briar-core/src/org/briarproject/lifecycle/LifecycleModule.java b/briar-core/src/org/briarproject/lifecycle/LifecycleModule.java
index 0714a0555e..5685dd2a2d 100644
--- a/briar-core/src/org/briarproject/lifecycle/LifecycleModule.java
+++ b/briar-core/src/org/briarproject/lifecycle/LifecycleModule.java
@@ -11,14 +11,18 @@ import java.util.concurrent.ThreadPoolExecutor;
 
 import javax.inject.Singleton;
 
+import org.briarproject.api.db.DatabaseComponent;
+import org.briarproject.api.event.EventBus;
 import org.briarproject.api.lifecycle.IoExecutor;
 import org.briarproject.api.lifecycle.LifecycleManager;
 import org.briarproject.api.lifecycle.ShutdownManager;
+import org.briarproject.api.system.Clock;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
+import dagger.Module;
+import dagger.Provides;
 
-public class LifecycleModule extends AbstractModule {
+@Module
+public class LifecycleModule {
 
 	private final ExecutorService ioExecutor;
 
@@ -33,17 +37,25 @@ public class LifecycleModule extends AbstractModule {
 				60, SECONDS, queue, policy);
 	}
 
-	@Override
-	protected void configure() {
-		bind(LifecycleManager.class).to(
-				LifecycleManagerImpl.class).in(Singleton.class);
-		bind(ShutdownManager.class).to(
-				ShutdownManagerImpl.class).in(Singleton.class);
+	@Provides
+	@Singleton
+	ShutdownManager provideShutdownManager() {
+		return new ShutdownManagerImpl();
 	}
 
-	@Provides @Singleton @IoExecutor
+	@Provides
+	@Singleton
+	LifecycleManager provideLifeCycleManager(Clock clock, DatabaseComponent db,
+			EventBus eventBus) {
+		return new LifecycleManagerImpl(clock, db, eventBus);
+	}
+
+	@Provides
+	@Singleton
+	@IoExecutor
 	Executor getIoExecutor(LifecycleManager lifecycleManager) {
 		lifecycleManager.registerForShutdown(ioExecutor);
 		return ioExecutor;
 	}
+
 }
diff --git a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java b/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java
index 928b793bf3..657126053d 100644
--- a/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java
+++ b/briar-core/src/org/briarproject/messaging/MessagingManagerImpl.java
@@ -1,18 +1,19 @@
 package org.briarproject.messaging;
 
-import com.google.inject.Inject;
-
 import org.briarproject.api.FormatException;
-import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.clients.PrivateGroupFactory;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.contact.ContactManager.AddContactHook;
 import org.briarproject.api.contact.ContactManager.RemoveContactHook;
 import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
+import org.briarproject.api.data.BdfReader;
+import org.briarproject.api.data.BdfReaderFactory;
+import org.briarproject.api.data.MetadataEncoder;
+import org.briarproject.api.data.MetadataParser;
 import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.db.Metadata;
 import org.briarproject.api.db.Transaction;
 import org.briarproject.api.messaging.MessagingManager;
 import org.briarproject.api.messaging.PrivateMessage;
@@ -24,9 +25,18 @@ import org.briarproject.api.sync.MessageId;
 import org.briarproject.api.sync.MessageStatus;
 import org.briarproject.util.StringUtils;
 
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+import static java.util.logging.Level.WARNING;
+import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
+import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
 
 class MessagingManagerImpl implements MessagingManager, AddContactHook,
 		RemoveContactHook {
@@ -35,16 +45,25 @@ class MessagingManagerImpl implements MessagingManager, AddContactHook,
 			"6bcdc006c0910b0f44e40644c3b31f1a"
 					+ "8bf9a6d6021d40d219c86b731b903070"));
 
+	private static final Logger LOG =
+			Logger.getLogger(MessagingManagerImpl.class.getName());
+
 	private final DatabaseComponent db;
-	private final ClientHelper clientHelper;
 	private final PrivateGroupFactory privateGroupFactory;
+	private final BdfReaderFactory bdfReaderFactory;
+	private final MetadataEncoder metadataEncoder;
+	private final MetadataParser metadataParser;
 
 	@Inject
-	MessagingManagerImpl(DatabaseComponent db, ClientHelper clientHelper,
-			PrivateGroupFactory privateGroupFactory) {
+	MessagingManagerImpl(DatabaseComponent db,
+			PrivateGroupFactory privateGroupFactory,
+			BdfReaderFactory bdfReaderFactory, MetadataEncoder metadataEncoder,
+			MetadataParser metadataParser) {
 		this.db = db;
-		this.clientHelper = clientHelper;
 		this.privateGroupFactory = privateGroupFactory;
+		this.bdfReaderFactory = bdfReaderFactory;
+		this.metadataEncoder = metadataEncoder;
+		this.metadataParser = metadataParser;
 	}
 
 	@Override
@@ -58,7 +77,7 @@ class MessagingManagerImpl implements MessagingManager, AddContactHook,
 			// Attach the contact ID to the group
 			BdfDictionary d = new BdfDictionary();
 			d.put("contactId", c.getId().getInt());
-			clientHelper.mergeGroupMetadata(txn, g.getId(), d);
+			db.mergeGroupMetadata(txn, g.getId(), metadataEncoder.encode(d));
 		} catch (FormatException e) {
 			throw new RuntimeException(e);
 		}
@@ -81,13 +100,21 @@ class MessagingManagerImpl implements MessagingManager, AddContactHook,
 	@Override
 	public void addLocalMessage(PrivateMessage m) throws DbException {
 		try {
-			BdfDictionary meta = new BdfDictionary();
-			meta.put("timestamp", m.getMessage().getTimestamp());
-			if (m.getParent() != null) meta.put("parent", m.getParent());
-			meta.put("contentType", m.getContentType());
-			meta.put("local", true);
-			meta.put("read", true);
-			clientHelper.addLocalMessage(m.getMessage(), CLIENT_ID, meta, true);
+			BdfDictionary d = new BdfDictionary();
+			d.put("timestamp", m.getMessage().getTimestamp());
+			if (m.getParent() != null)
+				d.put("parent", m.getParent().getBytes());
+			d.put("contentType", m.getContentType());
+			d.put("local", true);
+			d.put("read", true);
+			Metadata meta = metadataEncoder.encode(d);
+			Transaction txn = db.startTransaction();
+			try {
+				db.addLocalMessage(txn, m.getMessage(), CLIENT_ID, meta, true);
+				txn.setComplete();
+			} finally {
+				db.endTransaction(txn);
+			}
 		} catch (FormatException e) {
 			throw new RuntimeException(e);
 		}
@@ -96,8 +123,16 @@ class MessagingManagerImpl implements MessagingManager, AddContactHook,
 	@Override
 	public ContactId getContactId(GroupId g) throws DbException {
 		try {
-			BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(g);
-			return new ContactId(meta.getLong("contactId").intValue());
+			Metadata meta;
+			Transaction txn = db.startTransaction();
+			try {
+				meta = db.getGroupMetadata(txn, g);
+				txn.setComplete();
+			} finally {
+				db.endTransaction(txn);
+			}
+			BdfDictionary d = metadataParser.parse(meta);
+			return new ContactId(d.getLong("contactId").intValue());
 		} catch (FormatException e) {
 			throw new DbException(e);
 		}
@@ -119,16 +154,14 @@ class MessagingManagerImpl implements MessagingManager, AddContactHook,
 	@Override
 	public Collection<PrivateMessageHeader> getMessageHeaders(ContactId c)
 			throws DbException {
-		Map<MessageId, BdfDictionary> metadata;
+		Map<MessageId, Metadata> metadata;
 		Collection<MessageStatus> statuses;
 		Transaction txn = db.startTransaction();
 		try {
 			GroupId g = getContactGroup(db.getContact(txn, c)).getId();
-			metadata = clientHelper.getMessageMetadataAsDictionary(txn, g);
+			metadata = db.getMessageMetadata(txn, g);
 			statuses = db.getMessageStatus(txn, c, g);
 			txn.setComplete();
-		} catch (FormatException e) {
-			throw new DbException(e);
 		} finally {
 			db.endTransaction(txn);
 		}
@@ -136,17 +169,18 @@ class MessagingManagerImpl implements MessagingManager, AddContactHook,
 				new ArrayList<PrivateMessageHeader>();
 		for (MessageStatus s : statuses) {
 			MessageId id = s.getMessageId();
-			BdfDictionary meta = metadata.get(id);
-			if (meta == null) continue;
+			Metadata m = metadata.get(id);
+			if (m == null) continue;
 			try {
-				long timestamp = meta.getLong("timestamp");
-				String contentType = meta.getString("contentType");
-				boolean local = meta.getBoolean("local");
-				boolean read = meta.getBoolean("read");
+				BdfDictionary d = metadataParser.parse(m);
+				long timestamp = d.getLong("timestamp");
+				String contentType = d.getString("contentType");
+				boolean local = d.getBoolean("local");
+				boolean read = d.getBoolean("read");
 				headers.add(new PrivateMessageHeader(id, timestamp, contentType,
 						local, read, s.isSent(), s.isSeen()));
 			} catch (FormatException e) {
-				throw new DbException(e);
+				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
 			}
 		}
 		return headers;
@@ -154,21 +188,47 @@ class MessagingManagerImpl implements MessagingManager, AddContactHook,
 
 	@Override
 	public byte[] getMessageBody(MessageId m) throws DbException {
+		byte[] raw;
+		Transaction txn = db.startTransaction();
+		try {
+			raw = db.getRawMessage(txn, m);
+			txn.setComplete();
+		} finally {
+			db.endTransaction(txn);
+		}
+		ByteArrayInputStream in = new ByteArrayInputStream(raw,
+				MESSAGE_HEADER_LENGTH, raw.length - MESSAGE_HEADER_LENGTH);
+		BdfReader r = bdfReaderFactory.createReader(in);
 		try {
-			// Parent ID, content type, private message body
-			BdfList message = clientHelper.getMessageAsList(m);
-			return message.getRaw(2);
+			r.readListStart();
+			if (r.hasRaw()) r.skipRaw(); // Parent ID
+			else r.skipNull(); // No parent
+			r.skipString(); // Content type
+			byte[] messageBody = r.readRaw(MAX_PRIVATE_MESSAGE_BODY_LENGTH);
+			r.readListEnd();
+			if (!r.eof()) throw new FormatException();
+			return messageBody;
 		} catch (FormatException e) {
 			throw new DbException(e);
+		} catch (IOException e) {
+			// Shouldn't happen with ByteArrayInputStream
+			throw new RuntimeException(e);
 		}
 	}
 
 	@Override
 	public void setReadFlag(MessageId m, boolean read) throws DbException {
 		try {
-			BdfDictionary meta = new BdfDictionary();
-			meta.put("read", read);
-			clientHelper.mergeMessageMetadata(m, meta);
+			BdfDictionary d = new BdfDictionary();
+			d.put("read", read);
+			Metadata meta = metadataEncoder.encode(d);
+			Transaction txn = db.startTransaction();
+			try {
+				db.mergeMessageMetadata(txn, m, meta);
+				txn.setComplete();
+			} finally {
+				db.endTransaction(txn);
+			}
 		} catch (FormatException e) {
 			throw new RuntimeException(e);
 		}
diff --git a/briar-core/src/org/briarproject/messaging/MessagingModule.java b/briar-core/src/org/briarproject/messaging/MessagingModule.java
index 4ea10f9078..89c748a59f 100644
--- a/briar-core/src/org/briarproject/messaging/MessagingModule.java
+++ b/briar-core/src/org/briarproject/messaging/MessagingModule.java
@@ -1,38 +1,46 @@
 package org.briarproject.messaging;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-
-import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.contact.ContactManager;
+import org.briarproject.api.data.BdfReaderFactory;
+import org.briarproject.api.data.BdfWriterFactory;
 import org.briarproject.api.data.MetadataEncoder;
 import org.briarproject.api.messaging.MessagingManager;
 import org.briarproject.api.messaging.PrivateMessageFactory;
+import org.briarproject.api.sync.MessageFactory;
 import org.briarproject.api.sync.ValidationManager;
 import org.briarproject.api.system.Clock;
 
 import javax.inject.Singleton;
 
+import dagger.Module;
+import dagger.Provides;
+
 import static org.briarproject.messaging.MessagingManagerImpl.CLIENT_ID;
 
-public class MessagingModule extends AbstractModule {
+@Module
+public class MessagingModule {
 
-	@Override
-	protected void configure() {
-		bind(PrivateMessageFactory.class).to(PrivateMessageFactoryImpl.class);
+	@Provides
+	PrivateMessageFactory providePrivateMessageFactory(
+			MessageFactory messageFactory,
+			BdfWriterFactory bdfWriterFactory) {
+		return new PrivateMessageFactoryImpl(messageFactory, bdfWriterFactory);
 	}
 
-	@Provides @Singleton
+
+	@Provides
+	@Singleton
 	PrivateMessageValidator getValidator(ValidationManager validationManager,
-			ClientHelper clientHelper, MetadataEncoder metadataEncoder,
+			BdfReaderFactory bdfReaderFactory, MetadataEncoder metadataEncoder,
 			Clock clock) {
 		PrivateMessageValidator validator = new PrivateMessageValidator(
-				clientHelper, metadataEncoder, clock);
+				bdfReaderFactory, metadataEncoder, clock);
 		validationManager.registerMessageValidator(CLIENT_ID, validator);
 		return validator;
 	}
 
-	@Provides @Singleton
+	@Provides
+	@Singleton
 	MessagingManager getMessagingManager(ContactManager contactManager,
 			MessagingManagerImpl messagingManager) {
 		contactManager.registerAddContactHook(messagingManager);
diff --git a/briar-core/src/org/briarproject/plugins/ConnectionRegistryImpl.java b/briar-core/src/org/briarproject/plugins/ConnectionRegistryImpl.java
index 245a37dbb4..86cfab5a18 100644
--- a/briar-core/src/org/briarproject/plugins/ConnectionRegistryImpl.java
+++ b/briar-core/src/org/briarproject/plugins/ConnectionRegistryImpl.java
@@ -1,7 +1,5 @@
 package org.briarproject.plugins;
 
-import com.google.inject.Inject;
-
 import org.briarproject.api.TransportId;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.event.ContactConnectedEvent;
@@ -19,6 +17,8 @@ import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.logging.Logger;
 
+import javax.inject.Inject;
+
 import static java.util.logging.Level.INFO;
 
 class ConnectionRegistryImpl implements ConnectionRegistry {
diff --git a/briar-core/src/org/briarproject/plugins/PluginsModule.java b/briar-core/src/org/briarproject/plugins/PluginsModule.java
index d7f8962d78..67f27b08ba 100644
--- a/briar-core/src/org/briarproject/plugins/PluginsModule.java
+++ b/briar-core/src/org/briarproject/plugins/PluginsModule.java
@@ -1,28 +1,54 @@
 package org.briarproject.plugins;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
+import javax.inject.Singleton;
 
+import org.briarproject.api.event.EventBus;
+import org.briarproject.api.lifecycle.IoExecutor;
 import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.plugins.BackoffFactory;
 import org.briarproject.api.plugins.ConnectionManager;
 import org.briarproject.api.plugins.ConnectionRegistry;
 import org.briarproject.api.plugins.PluginManager;
+import org.briarproject.api.sync.SyncSessionFactory;
+import org.briarproject.api.system.Timer;
+import org.briarproject.api.transport.KeyManager;
+import org.briarproject.api.transport.StreamReaderFactory;
+import org.briarproject.api.transport.StreamWriterFactory;
+
+import java.util.concurrent.Executor;
+
+import dagger.Module;
+import dagger.Provides;
 
-import javax.inject.Singleton;
 
-public class PluginsModule extends AbstractModule {
+@Module
+public class PluginsModule {
+
+	@Provides
+	Poller providePoller(@IoExecutor Executor ioExecutor,
+			ConnectionRegistry connectionRegistry, Timer timer) {
+		return new PollerImpl(ioExecutor, connectionRegistry, timer);
+	}
+
+	@Provides
+	ConnectionManager provideConnectionManager(
+			@IoExecutor Executor ioExecutor,
+			KeyManager keyManager, StreamReaderFactory streamReaderFactory,
+			StreamWriterFactory streamWriterFactory,
+			SyncSessionFactory syncSessionFactory,
+			ConnectionRegistry connectionRegistry) {
+		return new ConnectionManagerImpl(ioExecutor, keyManager,
+				streamReaderFactory, streamWriterFactory, syncSessionFactory,
+				connectionRegistry);
+	}
 
-	@Override
-	protected void configure() {
-		bind(BackoffFactory.class).to(BackoffFactoryImpl.class);
-		bind(Poller.class).to(PollerImpl.class);
-		bind(ConnectionManager.class).to(ConnectionManagerImpl.class);
-		bind(ConnectionRegistry.class).to(
-				ConnectionRegistryImpl.class).in(Singleton.class);
+	@Provides
+	@Singleton
+	ConnectionRegistry provideConnectionRegistry(EventBus eventBus) {
+		return new ConnectionRegistryImpl(eventBus);
 	}
 
-	@Provides @Singleton
+	@Provides
+	@Singleton
 	PluginManager getPluginManager(LifecycleManager lifecycleManager,
 			PluginManagerImpl pluginManager) {
 		lifecycleManager.register(pluginManager);
diff --git a/briar-core/src/org/briarproject/properties/PropertiesModule.java b/briar-core/src/org/briarproject/properties/PropertiesModule.java
index cd40134deb..057f685ba5 100644
--- a/briar-core/src/org/briarproject/properties/PropertiesModule.java
+++ b/briar-core/src/org/briarproject/properties/PropertiesModule.java
@@ -1,10 +1,7 @@
 package org.briarproject.properties;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-
-import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.contact.ContactManager;
+import org.briarproject.api.data.BdfReaderFactory;
 import org.briarproject.api.data.MetadataEncoder;
 import org.briarproject.api.properties.TransportPropertyManager;
 import org.briarproject.api.sync.ValidationManager;
@@ -12,19 +9,21 @@ import org.briarproject.api.system.Clock;
 
 import javax.inject.Singleton;
 
-import static org.briarproject.properties.TransportPropertyManagerImpl.CLIENT_ID;
+import dagger.Module;
+import dagger.Provides;
 
-public class PropertiesModule extends AbstractModule {
+import static org.briarproject.properties.TransportPropertyManagerImpl.CLIENT_ID;
 
-	@Override
-	protected void configure() {}
+@Module
+public class PropertiesModule {
 
-	@Provides @Singleton
+	@Provides
+	@Singleton
 	TransportPropertyValidator getValidator(ValidationManager validationManager,
-			ClientHelper clientHelper, MetadataEncoder metadataEncoder,
+			BdfReaderFactory bdfReaderFactory, MetadataEncoder metadataEncoder,
 			Clock clock) {
 		TransportPropertyValidator validator = new TransportPropertyValidator(
-				clientHelper, metadataEncoder, clock);
+				bdfReaderFactory, metadataEncoder, clock);
 		validationManager.registerMessageValidator(CLIENT_ID, validator);
 		return validator;
 	}
diff --git a/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java b/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java
index 9c04d99fe9..6bf9b5281f 100644
--- a/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java
+++ b/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java
@@ -1,20 +1,23 @@
 package org.briarproject.properties;
 
-import com.google.inject.Inject;
-
 import org.briarproject.api.DeviceId;
 import org.briarproject.api.FormatException;
 import org.briarproject.api.TransportId;
-import org.briarproject.api.clients.ClientHelper;
 import org.briarproject.api.clients.PrivateGroupFactory;
 import org.briarproject.api.contact.Contact;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.contact.ContactManager.AddContactHook;
 import org.briarproject.api.contact.ContactManager.RemoveContactHook;
 import org.briarproject.api.data.BdfDictionary;
-import org.briarproject.api.data.BdfList;
+import org.briarproject.api.data.BdfReader;
+import org.briarproject.api.data.BdfReaderFactory;
+import org.briarproject.api.data.BdfWriter;
+import org.briarproject.api.data.BdfWriterFactory;
+import org.briarproject.api.data.MetadataEncoder;
+import org.briarproject.api.data.MetadataParser;
 import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
+import org.briarproject.api.db.Metadata;
 import org.briarproject.api.db.NoSuchGroupException;
 import org.briarproject.api.db.Transaction;
 import org.briarproject.api.properties.TransportProperties;
@@ -24,15 +27,24 @@ import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupFactory;
 import org.briarproject.api.sync.GroupId;
 import org.briarproject.api.sync.Message;
+import org.briarproject.api.sync.MessageFactory;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.api.system.Clock;
 import org.briarproject.util.StringUtils;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import javax.inject.Inject;
+
+import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
+import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
+
 class TransportPropertyManagerImpl implements TransportPropertyManager,
 		AddContactHook, RemoveContactHook {
 
@@ -43,18 +55,28 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 	private static final byte[] LOCAL_GROUP_DESCRIPTOR = new byte[0];
 
 	private final DatabaseComponent db;
-	private final ClientHelper clientHelper;
 	private final PrivateGroupFactory privateGroupFactory;
+	private final MessageFactory messageFactory;
+	private final BdfReaderFactory bdfReaderFactory;
+	private final BdfWriterFactory bdfWriterFactory;
+	private final MetadataEncoder metadataEncoder;
+	private final MetadataParser metadataParser;
 	private final Clock clock;
 	private final Group localGroup;
 
 	@Inject
 	TransportPropertyManagerImpl(DatabaseComponent db,
-			ClientHelper clientHelper, GroupFactory groupFactory,
-			PrivateGroupFactory privateGroupFactory, Clock clock) {
+			GroupFactory groupFactory, PrivateGroupFactory privateGroupFactory,
+			MessageFactory messageFactory, BdfReaderFactory bdfReaderFactory,
+			BdfWriterFactory bdfWriterFactory, MetadataEncoder metadataEncoder,
+			MetadataParser metadataParser, Clock clock) {
 		this.db = db;
-		this.clientHelper = clientHelper;
 		this.privateGroupFactory = privateGroupFactory;
+		this.messageFactory = messageFactory;
+		this.bdfReaderFactory = bdfReaderFactory;
+		this.bdfWriterFactory = bdfWriterFactory;
+		this.metadataEncoder = metadataEncoder;
+		this.metadataParser = metadataParser;
 		this.clock = clock;
 		localGroup = groupFactory.createGroup(CLIENT_ID,
 				LOCAL_GROUP_DESCRIPTOR);
@@ -123,9 +145,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 						true);
 				if (latest != null) {
 					// Retrieve and parse the latest local properties
-					BdfList message = clientHelper.getMessageAsList(txn,
-							latest.messageId);
-					p = parseProperties(message);
+					byte[] raw = db.getRawMessage(txn, latest.messageId);
+					p = parseProperties(raw);
 				}
 				txn.setComplete();
 			} finally {
@@ -154,9 +175,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 					LatestUpdate latest = findLatest(txn, g.getId(), t, false);
 					if (latest != null) {
 						// Retrieve and parse the latest remote properties
-						BdfList message = clientHelper.getMessageAsList(txn,
-								latest.messageId);
-						remote.put(c.getId(), parseProperties(message));
+						byte[] raw = db.getRawMessage(txn, latest.messageId);
+						remote.put(c.getId(), parseProperties(raw));
 					}
 				}
 				txn.setComplete();
@@ -186,9 +206,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 					merged = p;
 					changed = true;
 				} else {
-					BdfList message = clientHelper.getMessageAsList(txn,
-							latest.messageId);
-					TransportProperties old = parseProperties(message);
+					byte[] raw = db.getRawMessage(txn, latest.messageId);
+					TransportProperties old = parseProperties(raw);
 					merged = new TransportProperties(old);
 					merged.putAll(p);
 					changed = !merged.equals(old);
@@ -231,9 +250,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 					localGroup.getId(), true);
 			// Retrieve and parse the latest local properties
 			for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) {
-				BdfList message = clientHelper.getMessageAsList(txn,
-						e.getValue().messageId);
-				local.put(e.getKey(), parseProperties(message));
+				byte[] raw = db.getRawMessage(txn, e.getValue().messageId);
+				local.put(e.getKey(), parseProperties(raw));
 			}
 			return local;
 		} catch (NoSuchGroupException e) {
@@ -248,35 +266,48 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 			TransportId t, TransportProperties p, long version, boolean local,
 			boolean shared) throws DbException {
 		try {
-			BdfList body = encodeProperties(dev, t, p, version);
+			byte[] body = encodeProperties(dev, t, p, version);
 			long now = clock.currentTimeMillis();
-			Message m = clientHelper.createMessage(g, now, body);
-			BdfDictionary meta = new BdfDictionary();
-			meta.put("transportId", t.getString());
-			meta.put("version", version);
-			meta.put("local", local);
-			clientHelper.addLocalMessage(txn, m, CLIENT_ID, meta, shared);
+			Message m = messageFactory.createMessage(g, now, body);
+			BdfDictionary d = new BdfDictionary();
+			d.put("transportId", t.getString());
+			d.put("version", version);
+			d.put("local", local);
+			Metadata meta = metadataEncoder.encode(d);
+			db.addLocalMessage(txn, m, CLIENT_ID, meta, shared);
 		} catch (FormatException e) {
 			throw new RuntimeException(e);
 		}
 	}
 
-	private BdfList encodeProperties(DeviceId dev, TransportId t,
+	private byte[] encodeProperties(DeviceId dev, TransportId t,
 			TransportProperties p, long version) {
-		return BdfList.of(dev, t.getString(), version, p);
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		BdfWriter w = bdfWriterFactory.createWriter(out);
+		try {
+			w.writeListStart();
+			w.writeRaw(dev.getBytes());
+			w.writeString(t.getString());
+			w.writeLong(version);
+			w.writeDictionary(p);
+			w.writeListEnd();
+		} catch (IOException e) {
+			// Shouldn't happen with ByteArrayOutputStream
+			throw new RuntimeException(e);
+		}
+		return out.toByteArray();
 	}
 
 	private Map<TransportId, LatestUpdate> findLatest(Transaction txn,
 			GroupId g, boolean local) throws DbException, FormatException {
 		Map<TransportId, LatestUpdate> latestUpdates =
 				new HashMap<TransportId, LatestUpdate>();
-		Map<MessageId, BdfDictionary> metadata =
-				clientHelper.getMessageMetadataAsDictionary(txn, g);
-		for (Entry<MessageId, BdfDictionary> e : metadata.entrySet()) {
-			BdfDictionary meta = e.getValue();
-			if (meta.getBoolean("local") == local) {
-				TransportId t = new TransportId(meta.getString("transportId"));
-				long version = meta.getLong("version");
+		Map<MessageId, Metadata> metadata = db.getMessageMetadata(txn, g);
+		for (Entry<MessageId, Metadata> e : metadata.entrySet()) {
+			BdfDictionary d = metadataParser.parse(e.getValue());
+			if (d.getBoolean("local") == local) {
+				TransportId t = new TransportId(d.getString("transportId"));
+				long version = d.getLong("version");
 				LatestUpdate latest = latestUpdates.get(t);
 				if (latest == null || version > latest.version)
 					latestUpdates.put(t, new LatestUpdate(e.getKey(), version));
@@ -288,13 +319,12 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 	private LatestUpdate findLatest(Transaction txn, GroupId g, TransportId t,
 			boolean local) throws DbException, FormatException {
 		LatestUpdate latest = null;
-		Map<MessageId, BdfDictionary> metadata =
-				clientHelper.getMessageMetadataAsDictionary(txn, g);
-		for (Entry<MessageId, BdfDictionary> e : metadata.entrySet()) {
-			BdfDictionary meta = e.getValue();
-			if (meta.getString("transportId").equals(t.getString())
-					&& meta.getBoolean("local") == local) {
-				long version = meta.getLong("version");
+		Map<MessageId, Metadata> metadata = db.getMessageMetadata(txn, g);
+		for (Entry<MessageId, Metadata> e : metadata.entrySet()) {
+			BdfDictionary d = metadataParser.parse(e.getValue());
+			if (d.getString("transportId").equals(t.getString())
+					&& d.getBoolean("local") == local) {
+				long version = d.getLong("version");
 				if (latest == null || version > latest.version)
 					latest = new LatestUpdate(e.getKey(), version);
 			}
@@ -302,14 +332,33 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
 		return latest;
 	}
 
-	private TransportProperties parseProperties(BdfList message)
+	private TransportProperties parseProperties(byte[] raw)
 			throws FormatException {
-		// Device ID, transport ID, version, properties
-		BdfDictionary dictionary = message.getDictionary(3);
 		TransportProperties p = new TransportProperties();
-		for (String key : dictionary.keySet())
-			p.put(key, dictionary.getString(key));
-		return p;
+		ByteArrayInputStream in = new ByteArrayInputStream(raw,
+				MESSAGE_HEADER_LENGTH, raw.length - MESSAGE_HEADER_LENGTH);
+		BdfReader r = bdfReaderFactory.createReader(in);
+		try {
+			r.readListStart();
+			r.skipRaw(); // Device ID
+			r.skipString(); // Transport ID
+			r.skipLong(); // Version
+			r.readDictionaryStart();
+			while (!r.hasDictionaryEnd()) {
+				String key = r.readString(MAX_PROPERTY_LENGTH);
+				String value = r.readString(MAX_PROPERTY_LENGTH);
+				p.put(key, value);
+			}
+			r.readDictionaryEnd();
+			r.readListEnd();
+			if (!r.eof()) throw new FormatException();
+			return p;
+		} catch (FormatException e) {
+			throw e;
+		} catch (IOException e) {
+			// Shouldn't happen with ByteArrayInputStream
+			throw new RuntimeException(e);
+		}
 	}
 
 	private static class LatestUpdate {
diff --git a/briar-core/src/org/briarproject/reliability/ReliabilityModule.java b/briar-core/src/org/briarproject/reliability/ReliabilityModule.java
index aabd18e875..4c8ef0138b 100644
--- a/briar-core/src/org/briarproject/reliability/ReliabilityModule.java
+++ b/briar-core/src/org/briarproject/reliability/ReliabilityModule.java
@@ -1,14 +1,30 @@
 package org.briarproject.reliability;
 
+import org.briarproject.api.lifecycle.IoExecutor;
 import org.briarproject.api.reliability.ReliabilityLayerFactory;
 
-import com.google.inject.AbstractModule;
+import java.util.concurrent.Executor;
 
-public class ReliabilityModule extends AbstractModule {
+import dagger.Module;
+import dagger.Provides;
 
-	@Override
-	protected void configure() {
-		bind(ReliabilityLayerFactory.class).to(
-				ReliabilityLayerFactoryImpl.class);
+@Module
+public class ReliabilityModule {
+
+	/*
+	@Provides
+	ReliabilityLayerFactory provideReliabilityFactory(@IoExecutor
+	Executor ioExecutor) {
+		return new ReliabilityLayerFactoryImpl(ioExecutor);
+	}
+	*/
+
+
+
+	@Provides
+	ReliabilityLayerFactory provideReliabilityFactory(
+			ReliabilityLayerFactoryImpl reliabilityLayerFactory) {
+		return reliabilityLayerFactory;
 	}
+
 }
diff --git a/briar-core/src/org/briarproject/settings/SettingsManagerImpl.java b/briar-core/src/org/briarproject/settings/SettingsManagerImpl.java
index eb929aa099..4ff0ff2217 100644
--- a/briar-core/src/org/briarproject/settings/SettingsManagerImpl.java
+++ b/briar-core/src/org/briarproject/settings/SettingsManagerImpl.java
@@ -1,6 +1,5 @@
 package org.briarproject.settings;
 
-import com.google.inject.Inject;
 
 import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
@@ -8,6 +7,8 @@ import org.briarproject.api.db.Transaction;
 import org.briarproject.api.settings.Settings;
 import org.briarproject.api.settings.SettingsManager;
 
+import javax.inject.Inject;
+
 class SettingsManagerImpl implements SettingsManager {
 
 	private final DatabaseComponent db;
diff --git a/briar-core/src/org/briarproject/settings/SettingsModule.java b/briar-core/src/org/briarproject/settings/SettingsModule.java
index f2d0e2b460..d8aa3b9158 100644
--- a/briar-core/src/org/briarproject/settings/SettingsModule.java
+++ b/briar-core/src/org/briarproject/settings/SettingsModule.java
@@ -1,13 +1,17 @@
 package org.briarproject.settings;
 
-import com.google.inject.AbstractModule;
-
+import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.settings.SettingsManager;
 
-public class SettingsModule extends AbstractModule {
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class SettingsModule {
 
-	@Override
-	protected void configure() {
-		bind(SettingsManager.class).to(SettingsManagerImpl.class);
+	@Provides
+	SettingsManager provideSettingsManager(DatabaseComponent db) {
+		return new SettingsManagerImpl(db);
 	}
+
 }
diff --git a/briar-core/src/org/briarproject/sync/MessageFactoryImpl.java b/briar-core/src/org/briarproject/sync/MessageFactoryImpl.java
index 1015b7daf7..68b5e01b0d 100644
--- a/briar-core/src/org/briarproject/sync/MessageFactoryImpl.java
+++ b/briar-core/src/org/briarproject/sync/MessageFactoryImpl.java
@@ -1,6 +1,5 @@
 package org.briarproject.sync;
 
-import com.google.inject.Inject;
 
 import org.briarproject.api.UniqueId;
 import org.briarproject.api.crypto.CryptoComponent;
@@ -10,6 +9,8 @@ import org.briarproject.api.sync.MessageFactory;
 import org.briarproject.api.sync.MessageId;
 import org.briarproject.util.ByteUtils;
 
+import javax.inject.Inject;
+
 import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
 import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
 
diff --git a/briar-core/src/org/briarproject/sync/SyncModule.java b/briar-core/src/org/briarproject/sync/SyncModule.java
index 64ed5d5053..d52c9fa359 100644
--- a/briar-core/src/org/briarproject/sync/SyncModule.java
+++ b/briar-core/src/org/briarproject/sync/SyncModule.java
@@ -1,32 +1,84 @@
 package org.briarproject.sync;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-
+import org.briarproject.api.crypto.CryptoComponent;
+import org.briarproject.api.data.BdfWriterFactory;
+import org.briarproject.api.data.ObjectReader;
+import org.briarproject.api.db.DatabaseComponent;
+import org.briarproject.api.db.DatabaseExecutor;
 import org.briarproject.api.event.EventBus;
+import org.briarproject.api.identity.Author;
+import org.briarproject.api.identity.AuthorFactory;
 import org.briarproject.api.lifecycle.LifecycleManager;
+import org.briarproject.api.sync.Group;
 import org.briarproject.api.sync.GroupFactory;
 import org.briarproject.api.sync.MessageFactory;
 import org.briarproject.api.sync.PacketReaderFactory;
 import org.briarproject.api.sync.PacketWriterFactory;
+import org.briarproject.api.sync.PrivateGroupFactory;
 import org.briarproject.api.sync.SyncSessionFactory;
 import org.briarproject.api.sync.ValidationManager;
+import org.briarproject.api.system.Clock;
+
+import java.util.concurrent.Executor;
 
 import javax.inject.Singleton;
 
-public class SyncModule extends AbstractModule {
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class SyncModule {
+
+	@Provides
+	AuthorFactory provideAuthFactory(CryptoComponent crypto,
+			BdfWriterFactory bdfWriterFactory, Clock clock) {
+		return new AuthorFactoryImpl(crypto, bdfWriterFactory, clock);
+	}
+
+	@Provides
+	GroupFactory provideGroupFactory(CryptoComponent crypto) {
+		return new GroupFactoryImpl(crypto);
+	}
+
+	@Provides
+	MessageFactory provideMessageFactory(CryptoComponent crypto) {
+		return new MessageFactoryImpl(crypto);
+	}
+
+	@Provides
+	PacketReaderFactory providePacketReaderFactory(CryptoComponent crypto) {
+		return new PacketReaderFactoryImpl(crypto);
+	}
+
+	@Provides
+	PacketWriterFactory providePacketWriterFactory() {
+		return new PacketWriterFactoryImpl();
+	}
+
+	@Provides
+	PrivateGroupFactory providePrivateGroupFactory(GroupFactory groupFactory,
+			BdfWriterFactory bdfWriterFactory) {
+		return new PrivateGroupFactoryImpl(groupFactory, bdfWriterFactory);
+	}
+
+	@Provides
+	@Singleton
+	SyncSessionFactory provideSyncSessionFactory(DatabaseComponent db,
+			@DatabaseExecutor Executor dbExecutor, EventBus eventBus,
+			Clock clock, PacketReaderFactory packetReaderFactory,
+			PacketWriterFactory packetWriterFactory) {
+		return new SyncSessionFactoryImpl(db, dbExecutor, eventBus, clock,
+				packetReaderFactory, packetWriterFactory);
+	}
+
 
-	@Override
-	protected void configure() {
-		bind(GroupFactory.class).to(GroupFactoryImpl.class);
-		bind(MessageFactory.class).to(MessageFactoryImpl.class);
-		bind(PacketReaderFactory.class).to(PacketReaderFactoryImpl.class);
-		bind(PacketWriterFactory.class).to(PacketWriterFactoryImpl.class);
-		bind(SyncSessionFactory.class).to(
-				SyncSessionFactoryImpl.class).in(Singleton.class);
+	@Provides
+	ObjectReader<Author> getAuthorReader(AuthorFactory authorFactory) {
+		return new AuthorReader(authorFactory);
 	}
 
-	@Provides @Singleton
+	@Provides
+	@Singleton
 	ValidationManager getValidationManager(LifecycleManager lifecycleManager,
 			EventBus eventBus, ValidationManagerImpl validationManager) {
 		lifecycleManager.register(validationManager);
diff --git a/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java b/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java
index 949dcc516e..4837a1b57a 100644
--- a/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java
+++ b/briar-core/src/org/briarproject/sync/ValidationManagerImpl.java
@@ -1,7 +1,5 @@
 package org.briarproject.sync;
 
-import com.google.inject.Inject;
-
 import org.briarproject.api.UniqueId;
 import org.briarproject.api.crypto.CryptoExecutor;
 import org.briarproject.api.db.DatabaseComponent;
@@ -30,6 +28,8 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.logging.Logger;
 
+import javax.inject.Inject;
+
 import static java.util.logging.Level.WARNING;
 import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
 
diff --git a/briar-core/src/org/briarproject/transport/TransportModule.java b/briar-core/src/org/briarproject/transport/TransportModule.java
index 367340a4cc..090882d1ab 100644
--- a/briar-core/src/org/briarproject/transport/TransportModule.java
+++ b/briar-core/src/org/briarproject/transport/TransportModule.java
@@ -1,8 +1,7 @@
 package org.briarproject.transport;
 
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-
+import org.briarproject.api.crypto.StreamDecrypterFactory;
+import org.briarproject.api.crypto.StreamEncrypterFactory;
 import org.briarproject.api.event.EventBus;
 import org.briarproject.api.lifecycle.LifecycleManager;
 import org.briarproject.api.transport.KeyManager;
@@ -11,15 +10,26 @@ import org.briarproject.api.transport.StreamWriterFactory;
 
 import javax.inject.Singleton;
 
-public class TransportModule extends AbstractModule {
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class TransportModule {
+
+	@Provides
+	StreamReaderFactory provideStreamReaderFactory(
+			StreamDecrypterFactory streamDecrypterFactory) {
+		return new StreamReaderFactoryImpl(streamDecrypterFactory);
+	}
 
-	@Override
-	protected void configure() {
-		bind(StreamReaderFactory.class).to(StreamReaderFactoryImpl.class);
-		bind(StreamWriterFactory.class).to(StreamWriterFactoryImpl.class);
+	@Provides
+	StreamWriterFactory provideStreamWriterFactory(
+			StreamEncrypterFactory streamEncrypterFactory) {
+		return new StreamWriterFactoryImpl(streamEncrypterFactory);
 	}
 
-	@Provides @Singleton
+	@Provides
+	@Singleton
 	KeyManager getKeyManager(LifecycleManager lifecycleManager,
 			EventBus eventBus, KeyManagerImpl keyManager) {
 		lifecycleManager.register(keyManager);
diff --git a/briar-desktop/src/org/briarproject/lifecycle/DesktopLifecycleModule.java b/briar-desktop/src/org/briarproject/lifecycle/DesktopLifecycleModule.java
index bf1a41d2a9..63c913cca5 100644
--- a/briar-desktop/src/org/briarproject/lifecycle/DesktopLifecycleModule.java
+++ b/briar-desktop/src/org/briarproject/lifecycle/DesktopLifecycleModule.java
@@ -4,10 +4,11 @@ import org.briarproject.api.lifecycle.LifecycleManager;
 import org.briarproject.api.lifecycle.ShutdownManager;
 import org.briarproject.util.OsUtils;
 
-import com.google.inject.Singleton;
 
 public class DesktopLifecycleModule extends LifecycleModule {
 
+	/*
+	// TODO
 	@Override
 	protected void configure() {
 		bind(LifecycleManager.class).to(
@@ -20,4 +21,5 @@ public class DesktopLifecycleModule extends LifecycleModule {
 					ShutdownManagerImpl.class).in(Singleton.class);
 		}
 	}
+	*/
 }
diff --git a/briar-desktop/src/org/briarproject/plugins/DesktopPluginsModule.java b/briar-desktop/src/org/briarproject/plugins/DesktopPluginsModule.java
index ff69727386..6d727a6d89 100644
--- a/briar-desktop/src/org/briarproject/plugins/DesktopPluginsModule.java
+++ b/briar-desktop/src/org/briarproject/plugins/DesktopPluginsModule.java
@@ -1,7 +1,5 @@
 package org.briarproject.plugins;
 
-import com.google.inject.Provides;
-
 import org.briarproject.api.lifecycle.IoExecutor;
 import org.briarproject.api.lifecycle.ShutdownManager;
 import org.briarproject.api.plugins.BackoffFactory;
@@ -22,6 +20,10 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.concurrent.Executor;
 
+import dagger.Module;
+import dagger.Provides;
+
+@Module
 public class DesktopPluginsModule extends PluginsModule {
 
 	@Provides
diff --git a/briar-desktop/src/org/briarproject/system/DesktopSystemModule.java b/briar-desktop/src/org/briarproject/system/DesktopSystemModule.java
index 3ed1a7540a..d3186ed1b6 100644
--- a/briar-desktop/src/org/briarproject/system/DesktopSystemModule.java
+++ b/briar-desktop/src/org/briarproject/system/DesktopSystemModule.java
@@ -1,18 +1,19 @@
 package org.briarproject.system;
 
-import com.google.inject.AbstractModule;
-
 import org.briarproject.api.system.Clock;
 import org.briarproject.api.system.SeedProvider;
 import org.briarproject.api.system.Timer;
 import org.briarproject.util.OsUtils;
 
-public class DesktopSystemModule extends AbstractModule {
+public class DesktopSystemModule {
 
+	/*
+	// TODO
 	protected void configure() {
 		bind(Clock.class).to(SystemClock.class);
 		bind(Timer.class).to(SystemTimer.class);
 		if (OsUtils.isLinux())
 			bind(SeedProvider.class).to(LinuxSeedProvider.class);
 	}
+	*/
 }
diff --git a/briar-tests/build.gradle b/briar-tests/build.gradle
index afa7bbb2e4..c5ae112372 100644
--- a/briar-tests/build.gradle
+++ b/briar-tests/build.gradle
@@ -13,7 +13,6 @@ dependencies {
 	compile project(':briar-core')
 	compile fileTree(dir: '../briar-desktop/libs', include: '*.jar')
 	compile project(':briar-desktop')
-
 	compile "junit:junit:4.12"
 	compile "org.jmock:jmock:2.8.1"
 	compile "org.hamcrest:hamcrest-library:1.3"
diff --git a/briar-tests/src/org/briarproject/TestDatabaseModule.java b/briar-tests/src/org/briarproject/TestDatabaseModule.java
index 429f6a9dee..b6659315f2 100644
--- a/briar-tests/src/org/briarproject/TestDatabaseModule.java
+++ b/briar-tests/src/org/briarproject/TestDatabaseModule.java
@@ -1,12 +1,14 @@
 package org.briarproject;
 
-import com.google.inject.AbstractModule;
-
 import org.briarproject.api.db.DatabaseConfig;
 
 import java.io.File;
 
-public class TestDatabaseModule extends AbstractModule {
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class TestDatabaseModule {
 
 	private final DatabaseConfig config;
 
@@ -22,7 +24,9 @@ public class TestDatabaseModule extends AbstractModule {
 		this.config = new TestDatabaseConfig(dir, maxSize);
 	}
 
-	protected void configure() {
-		bind(DatabaseConfig.class).toInstance(config);
+	@Provides
+	DatabaseConfig provideDatabaseConfig() {
+		return config;
 	}
+
 }
diff --git a/briar-tests/src/org/briarproject/TestLifecycleModule.java b/briar-tests/src/org/briarproject/TestLifecycleModule.java
index a6b6a61863..8df124d7d6 100644
--- a/briar-tests/src/org/briarproject/TestLifecycleModule.java
+++ b/briar-tests/src/org/briarproject/TestLifecycleModule.java
@@ -1,7 +1,5 @@
 package org.briarproject;
 
-import com.google.inject.AbstractModule;
-
 import org.briarproject.api.lifecycle.IoExecutor;
 import org.briarproject.api.lifecycle.LifecycleManager;
 import org.briarproject.api.lifecycle.Service;
@@ -11,37 +9,70 @@ import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
-public class TestLifecycleModule extends AbstractModule {
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class TestLifecycleModule {
+
+	@Provides
+	LifecycleManager provideLifecycleManager() {
+		return new LifecycleManager() {
+			@Override
+			public void register(Service s) {
+
+			}
+
+			@Override
+			public void registerForShutdown(ExecutorService e) {
+
+			}
+
+			@Override
+			public StartResult startServices() {
+				return StartResult.SUCCESS;
+			}
 
-	@Override
-	protected void configure() {
-		bind(LifecycleManager.class).toInstance(new LifecycleManager() {
+			@Override
+			public void stopServices() {
 
-			public void register(Service s) {}
+			}
 
-			public void registerForShutdown(ExecutorService e) {}
+			@Override
+			public void waitForDatabase() throws InterruptedException {
 
-			public StartResult startServices() { return StartResult.SUCCESS; }
+			}
 
-			public void stopServices() {}
+			@Override
+			public void waitForStartup() throws InterruptedException {
 
-			public void waitForDatabase() throws InterruptedException {}
+			}
 
-			public void waitForStartup() throws InterruptedException {}
+			@Override
+			public void waitForShutdown() throws InterruptedException {
 
-			public void waitForShutdown() throws InterruptedException {}
-		});
-		bind(ShutdownManager.class).toInstance(new ShutdownManager() {
+			}
+		};
+	}
 
+	ShutdownManager provideShutdownManager() {
+		return new ShutdownManager() {
+			@Override
 			public int addShutdownHook(Runnable hook) {
 				return 0;
 			}
 
+			@Override
 			public boolean removeShutdownHook(int handle) {
 				return true;
 			}
-		});
-		bind(Executor.class).annotatedWith(IoExecutor.class).toInstance(
-				Executors.newCachedThreadPool());
+		};
+	}
+
+	@Provides
+	@IoExecutor
+	Executor provideExecutor() {
+		return Executors.newCachedThreadPool();
 	}
+
 }
diff --git a/briar-tests/src/org/briarproject/TestSystemModule.java b/briar-tests/src/org/briarproject/TestSystemModule.java
index 9734f533e0..2082896a31 100644
--- a/briar-tests/src/org/briarproject/TestSystemModule.java
+++ b/briar-tests/src/org/briarproject/TestSystemModule.java
@@ -1,18 +1,29 @@
 package org.briarproject;
 
-import com.google.inject.AbstractModule;
-
 import org.briarproject.api.system.Clock;
 import org.briarproject.api.system.SeedProvider;
 import org.briarproject.api.system.Timer;
 import org.briarproject.system.SystemClock;
 import org.briarproject.system.SystemTimer;
 
-public class TestSystemModule extends AbstractModule {
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+public class TestSystemModule {
+
+	@Provides
+	Clock provideClock() {
+		return new SystemClock();
+	}
+
+	@Provides
+	Timer provideSystemTimer() {
+		return new SystemTimer();
+	}
 
-	protected void configure() {
-		bind(Clock.class).to(SystemClock.class);
-		bind(Timer.class).to(SystemTimer.class);
-		bind(SeedProvider.class).to(TestSeedProvider.class);
+	@Provides
+	SeedProvider provideSeedProvider() {
+		return new TestSeedProvider();
 	}
 }
diff --git a/build.gradle b/build.gradle
index 614bca7eb4..ced77342bc 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2,9 +2,13 @@
 buildscript {
 	repositories {
 		mavenCentral()
+		maven {
+			url "https://plugins.gradle.org/m2/"
+		}
 	}
 	dependencies {
 		classpath 'com.android.tools.build:gradle:1.5.0'
+		classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
 		classpath files('briar-core/libs/gradle-witness.jar')
 	}
 }
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 06909cf9ea..6de5aebc60 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,4 +1,4 @@
-include ':briar-api'
+include ':briar-api', ':briar-android-tests'
 include ':briar-core'
 include ':briar-desktop'
 include ':briar-tests'
-- 
GitLab