diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml
index f352528d369b63c52908f76b9c1bf852e76e8fac..7a367dbaa8f3a99e2943ab9bc9ef03dca6c8c5c2 100644
--- a/briar-android/AndroidManifest.xml
+++ b/briar-android/AndroidManifest.xml
@@ -1,18 +1,19 @@
 <?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+<manifest
 	package="org.briarproject"
+	xmlns:android="http://schemas.android.com/apk/res/android"
 	android:versionCode="11"
-	android:versionName="0.11" >
+	android:versionName="0.11">
 
 	<uses-sdk
+		xmlns:tools="http://schemas.android.com/tools"
 		android:minSdkVersion="9"
-		android:targetSdkVersion="22"
 
-		xmlns:tools="http://schemas.android.com/tools"
+		android:targetSdkVersion="22"
 		tools:overrideLibrary="android.support.v14.preference"
-	/>
+		/>
 
-	<uses-feature android:name="android.hardware.bluetooth" />
+	<uses-feature android:name="android.hardware.bluetooth"/>
 
 	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@@ -23,183 +24,160 @@
 	<!-- Since API 23, this is needed to add contacts via Bluetooth -->
 	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 	<!-- FIXME: Only needed for alpha and beta builds -->
-	<uses-permission android:name="android.permission.READ_LOGS" />
-	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+	<uses-permission android:name="android.permission.READ_LOGS"/>
+	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 
 	<application
 		android:name=".android.BriarApplication"
-		android:theme="@style/BriarTheme"
+		android:allowBackup="false"
 		android:icon="@drawable/ic_launcher"
 		android:label="@string/app_name"
 		android:logo="@drawable/logo"
-		android:allowBackup="false" >
+		android:theme="@style/BriarTheme">
 		<service
 			android:name=".android.BriarService"
-			android:exported="false" >
+			android:exported="false">
 			<intent-filter>
-				<action android:name="org.briarproject.android.BriarService" />
+				<action android:name="org.briarproject.android.BriarService"/>
 			</intent-filter>
 		</service>
 		<activity
 			android:name=".android.CrashReportActivity"
-			android:label="@string/crash_report_title"
-			android:taskAffinity="org.briarproject.android.CrashHandler"
 			android:excludeFromRecents="true"
+			android:exported="false"
+			android:label="@string/crash_report_title"
 			android:launchMode="singleInstance"
 			android:process=":briar_error_handler"
-			android:exported="false" >
+			android:taskAffinity="org.briarproject.android.CrashHandler">
 			<intent-filter>
-				<action android:name="org.briarproject.REPORT_CRASH" />
-				<category android:name="android.intent.category.DEFAULT" />
+				<action android:name="org.briarproject.REPORT_CRASH"/>
+				<category android:name="android.intent.category.DEFAULT"/>
 			</intent-filter>
 		</activity>
-		<activity
-			android:name=".android.DashboardActivity"
-			android:label="@string/app_name" >
-		</activity>
 		<activity
 			android:name=".android.ExpiredActivity"
-			android:label="@string/app_name" >
+			android:label="@string/app_name">
 		</activity>
 		<activity
 			android:name=".android.PasswordActivity"
 			android:label="@string/app_name"
-			android:windowSoftInputMode="stateVisible" >
-		</activity>
-		<activity
-			android:name=".android.SettingsActivity"
-			android:label="@string/settings_title"
-			android:parentActivityName=".android.DashboardActivity" >
-			<meta-data
-				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.DashboardActivity"
-			/>
+			android:windowSoftInputMode="stateVisible">
 		</activity>
 		<activity
 			android:name=".android.SetupActivity"
-			android:label="@string/setup_title" >
+			android:label="@string/setup_title">
 		</activity>
 		<activity
 			android:name=".android.SplashScreenActivity"
-			android:label="@string/app_name" >
+			android:label="@string/app_name">
 			<intent-filter>
-				<action android:name="android.intent.action.MAIN" />
-				<category android:name="android.intent.category.LAUNCHER" />
+				<action android:name="android.intent.action.MAIN"/>
+				<category android:name="android.intent.category.LAUNCHER"/>
 			</intent-filter>
 		</activity>
 		<activity
 			android:name=".android.TestingActivity"
-			android:label="@string/app_name" >
+			android:label="@string/app_name">
 		</activity>
+
 		<activity
-			android:name=".android.contact.ContactListActivity"
-			android:label="@string/contact_list_title"
-			android:parentActivityName=".android.DashboardActivity" >
-			<meta-data
-				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.DashboardActivity"
+			android:name=".android.NavDrawerActivity"
+			android:theme="@style/BriarThemeNoActionBar.Default"
+		    android:launchMode="singleTop"
 			/>
-		</activity>
+
 		<activity
 			android:name=".android.contact.ConversationActivity"
 			android:label="@string/app_name"
-			android:windowSoftInputMode="stateHidden"
-			android:parentActivityName=".android.contact.ContactListActivity" >
+			android:parentActivityName=".android.NavDrawerActivity"
+			android:windowSoftInputMode="stateHidden">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.contact.ContactListActivity"
-			/>
+				android:value=".android.NavDrawerActivity"
+				/>
 		</activity>
 		<activity
 			android:name=".android.forum.AvailableForumsActivity"
 			android:label="@string/available_forums_title"
-			android:parentActivityName=".android.forum.ForumListActivity" >
+			android:parentActivityName=".android.NavDrawerActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.forum.ForumListActivity"
-			/>
+				android:value=".android.NavDrawerActivity"
+				/>
 		</activity>
 		<activity
 			android:name=".android.forum.CreateForumActivity"
 			android:label="@string/create_forum_title"
-			android:windowSoftInputMode="stateVisible"
-			android:parentActivityName=".android.forum.ForumListActivity" >
+			android:parentActivityName=".android.NavDrawerActivity"
+			android:windowSoftInputMode="stateVisible">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.forum.ForumListActivity"
-			/>
+				android:value=".android.NavDrawerActivity"
+				/>
 		</activity>
 		<activity
 			android:name=".android.forum.ForumActivity"
 			android:label="@string/app_name"
-			android:parentActivityName=".android.forum.ForumListActivity" >
-			<meta-data
-				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.forum.ForumListActivity"
-			/>
-		</activity>
-		<activity
-			android:name=".android.forum.ForumListActivity"
-			android:label="@string/forums_title"
-			android:parentActivityName=".android.DashboardActivity" >
+			android:parentActivityName=".android.NavDrawerActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.DashboardActivity"
-			/>
+				android:value=".android.NavDrawerActivity"
+				/>
 		</activity>
 		<activity
 			android:name=".android.forum.ReadForumPostActivity"
 			android:label="@string/app_name"
-			android:parentActivityName=".android.forum.ForumListActivity" >
+			android:parentActivityName=".android.NavDrawerActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.forum.ForumListActivity"
-			/>
+				android:value=".android.NavDrawerActivity"
+				/>
 		</activity>
 		<activity
 			android:name=".android.forum.ShareForumActivity"
 			android:label="@string/app_name"
-			android:parentActivityName=".android.forum.ForumListActivity" >
+			android:parentActivityName=".android.NavDrawerActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.forum.ForumListActivity"
-			/>
+				android:value=".android.NavDrawerActivity"
+				/>
 		</activity>
 		<activity
 			android:name=".android.forum.WriteForumPostActivity"
 			android:label="@string/app_name"
-			android:windowSoftInputMode="stateVisible"
-			android:parentActivityName=".android.forum.ForumListActivity" >
+			android:parentActivityName=".android.NavDrawerActivity"
+			android:windowSoftInputMode="stateVisible">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.forum.ForumListActivity"
-			/>
+				android:value=".android.NavDrawerActivity"
+				/>
 		</activity>
 		<activity
 			android:name=".android.identity.CreateIdentityActivity"
 			android:label="@string/new_identity_title"
-			android:windowSoftInputMode="stateVisible" >
+			android:windowSoftInputMode="stateVisible">
 		</activity>
 		<activity
 			android:name=".android.invitation.AddContactActivity"
 			android:label="@string/add_contact_title"
-			android:parentActivityName=".android.contact.ContactListActivity" >
+			android:parentActivityName=".android.NavDrawerActivity">
 			<meta-data
 				android:name="android.support.PARENT_ACTIVITY"
-				android:value=".android.contact.ContactListActivity"
-			/>
+				android:value=".android.NavDrawerActivity"
+				/>
 		</activity>
 		<activity
 			android:name=".android.StartupFailureActivity"
-			android:label="@string/startup_failed_activity_title" >
+			android:label="@string/startup_failed_activity_title">
 		</activity>
 		<activity
 			android:name=".android.panic.PanicPreferencesActivity"
-			android:label="@string/panic_setting" >
+			android:label="@string/panic_setting">
 			<intent-filter>
-				<action android:name="info.guardianproject.panic.action.CONNECT" />
-				<action android:name="info.guardianproject.panic.action.DISCONNECT" />
-				<category android:name="android.intent.category.DEFAULT" />
+				<action android:name="info.guardianproject.panic.action.CONNECT"/>
+				<action android:name="info.guardianproject.panic.action.DISCONNECT"/>
+
+				<category android:name="android.intent.category.DEFAULT"/>
 			</intent-filter>
 		</activity>
 		<activity
@@ -208,12 +186,12 @@
 			android:theme="@android:style/Theme.NoDisplay">
 			<!-- this can never have launchMode singleTask or singleInstance! -->
 			<intent-filter>
-				<action android:name="info.guardianproject.panic.action.TRIGGER" />
-				<category android:name="android.intent.category.DEFAULT" />
+				<action android:name="info.guardianproject.panic.action.TRIGGER"/>
+				<category android:name="android.intent.category.DEFAULT"/>
 			</intent-filter>
 		</activity>
 		<activity
 			android:name=".android.panic.ExitActivity"
-			android:theme="@android:style/Theme.NoDisplay" />
+			android:theme="@android:style/Theme.NoDisplay"/>
 	</application>
 </manifest>
diff --git a/briar-android/res/layout/activity_nav_drawer.xml b/briar-android/res/layout/activity_nav_drawer.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f7f90efa8e99a2be3cbf94dc1dc30995d20cc566
--- /dev/null
+++ b/briar-android/res/layout/activity_nav_drawer.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v4.widget.DrawerLayout
+	android:id="@+id/drawer_layout"
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:tools="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent">
+
+	<!-- The first child(root) is the content view -->
+	<LinearLayout
+		android:layout_width="match_parent"
+		android:layout_height="match_parent"
+		android:orientation="vertical">
+
+		<android.support.v7.widget.Toolbar
+			android:id="@+id/toolbar"
+			style="@style/BriarToolbar"
+			android:layout_width="match_parent"
+			android:layout_height="wrap_content"
+			android:background="?attr/colorPrimary"
+			android:minHeight="?attr/actionBarSize"
+			/>
+
+		<FrameLayout
+			android:layout_width="match_parent"
+			android:layout_height="match_parent">
+
+			<FrameLayout
+				android:id="@+id/content_fragment"
+				android:layout_width="match_parent"
+				android:layout_height="match_parent"
+				android:background="@color/default_background"/>
+
+			<RelativeLayout
+				android:id="@+id/container_progress"
+				android:layout_width="match_parent"
+				android:layout_height="match_parent"
+				android:layout_gravity="center"
+				android:background="@color/default_background"
+				android:visibility="invisible"
+				tools:visibility="visible">
+
+				<ProgressBar
+					android:id="@+id/progress_bar"
+					style="?android:attr/progressBarStyleLargeInverse"
+					android:layout_width="wrap_content"
+					android:layout_height="wrap_content"
+					android:layout_centerInParent="true"/>
+
+				<TextView
+					android:id="@+id/title_progress_bar"
+					android:layout_width="match_parent"
+					android:layout_height="wrap_content"
+					android:layout_below="@id/progress_bar"
+					android:gravity="center"
+					android:paddingTop="@dimen/margin_large"
+					tools:text="progress bar title"
+					/>
+
+			</RelativeLayout>
+
+		</FrameLayout>
+	</LinearLayout>
+
+	<!-- The second child is the menu -->
+	<include
+		android:id="@+id/navigation_menu_drawer"
+		layout="@layout/navigation_menu"
+		android:layout_width="@dimen/nav_drawer_width"
+		android:layout_height="match_parent"
+		android:layout_gravity="start"/>
+
+</android.support.v4.widget.DrawerLayout>
\ No newline at end of file
diff --git a/briar-android/res/layout/fragment_dashboard.xml b/briar-android/res/layout/fragment_dashboard.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d73431f59b46c0699d6cef6895bdd8d54bafff1
--- /dev/null
+++ b/briar-android/res/layout/fragment_dashboard.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	android:background="@color/dashboard_background"
+	>
+
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/briar-android/res/layout/navigation_menu.xml b/briar-android/res/layout/navigation_menu.xml
new file mode 100644
index 0000000000000000000000000000000000000000..51360c6758ac9a6bc0ba5892b25dd43fccb0325d
--- /dev/null
+++ b/briar-android/res/layout/navigation_menu.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:tools="http://schemas.android.com/tools"
+	android:layout_width="@dimen/nav_drawer_width"
+	android:layout_height="match_parent"
+	android:background="@color/menu_background"
+	android:orientation="vertical">
+
+	<TextView
+		android:id="@+id/nav_menu_header"
+		style="@style/BriarTextTitleInverted"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:background="@color/briar_primary"
+		android:paddingBottom="@dimen/margin_large"
+		android:paddingLeft="@dimen/margin_large"
+		android:paddingTop="@dimen/margin_xlarge"
+		android:textStyle="bold"
+		tools:text="Username"
+		/>
+
+	<ScrollView
+		android:layout_width="match_parent"
+		android:layout_height="match_parent"
+		android:fadingEdge="none"
+		android:fillViewport="true">
+
+		<LinearLayout
+			android:layout_width="match_parent"
+			android:layout_height="wrap_content"
+			android:orientation="vertical">
+
+			<android.support.v7.widget.AppCompatButton
+				android:id="@+id/nav_btn_contacts"
+				style="@style/NavMenuButton"
+				android:layout_width="match_parent"
+				android:layout_height="wrap_content"
+				android:drawableLeft="@drawable/social_person"
+				android:onClick="onNavigationClick"
+				android:text="@string/contact_list_button"/>
+
+			<View
+				style="@style/Divider"
+				android:layout_width="match_parent"
+				android:layout_height="@dimen/nav_seperator_height"
+				android:layout_marginLeft="@dimen/margin_large"/>
+
+			<android.support.v7.widget.AppCompatButton
+				android:id="@+id/nav_btn_forums"
+				style="@style/NavMenuButton"
+				android:layout_width="match_parent"
+				android:layout_height="wrap_content"
+				android:drawableLeft="@drawable/social_chat"
+				android:onClick="onNavigationClick"
+				android:text="@string/forums_button"/>
+
+			<View
+				style="@style/Divider"
+				android:layout_width="match_parent"
+				android:layout_height="@dimen/margin_seperator"
+				android:layout_marginLeft="@dimen/margin_large"/>
+
+			<android.support.v7.widget.AppCompatButton
+				android:id="@+id/nav_btn_settings"
+				style="@style/NavMenuButton"
+				android:layout_width="match_parent"
+				android:layout_height="wrap_content"
+				android:drawableLeft="@drawable/action_settings"
+				android:onClick="onNavigationClick"
+				android:text="@string/settings_button"/>
+
+			<View
+				style="@style/Divider"
+				android:layout_width="match_parent"
+				android:layout_height="@dimen/margin_seperator"
+				android:layout_marginLeft="@dimen/margin_large"/>
+
+			<android.support.v7.widget.AppCompatButton
+				android:id="@+id/nav_btn_signout"
+				style="@style/NavMenuButton"
+				android:layout_width="match_parent"
+				android:layout_height="wrap_content"
+				android:drawableLeft="@drawable/device_access_accounts"
+				android:onClick="onNavigationClick"
+				android:text="@string/sign_out_button"/>
+
+			<View
+				style="@style/Divider"
+				android:layout_width="match_parent"
+				android:layout_height="@dimen/margin_seperator"
+				android:layout_marginLeft="@dimen/margin_large"/>
+
+			<FrameLayout
+				android:layout_width="match_parent"
+				android:layout_height="0dp"
+				android:layout_weight="1.0"/>
+
+			<include
+				layout="@layout/transports_list"
+				android:layout_width="match_parent"
+				android:layout_height="wrap_content"
+				/>
+
+		</LinearLayout>
+
+	</ScrollView>
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/briar-android/res/values/color.xml b/briar-android/res/values/color.xml
index fc0ea39777f88fcf3c7a538fa03c2afca4f3f34e..94f4ea9cbc52c6fefc3c61c9321bd6aa0eef3c98 100644
--- a/briar-android/res/values/color.xml
+++ b/briar-android/res/values/color.xml
@@ -26,4 +26,8 @@
 
     <!-- this is needed as preference_category_material layout uses this color as the text color -->
     <color name="preference_fallback_accent_color">@color/briar_accent</color>
+    <color name="default_background">#ffffff</color>
+    <color name="default_seperator">#000000</color>
+    <color name="default_seperator_inverted">#ffffff</color>
+    <color name="menu_background">#FFFFFF</color>
 </resources>
\ No newline at end of file
diff --git a/briar-android/res/values/dimens.xml b/briar-android/res/values/dimens.xml
index 35c316f1216ce179e2cc4f1c6120e04fda42d7b4..e417b0897aa47a6ad3824c2cfdd7e7c9bd74d19a 100644
--- a/briar-android/res/values/dimens.xml
+++ b/briar-android/res/values/dimens.xml
@@ -17,5 +17,7 @@
 	<dimen name="text_size_medium">16sp</dimen>
 	<dimen name="text_size_large">20sp</dimen>
 	<dimen name="text_size_xlarge">34sp</dimen>
+	<dimen name="nav_drawer_width">300dp</dimen>
+	<dimen name="nav_seperator_height">1dp</dimen>
 
 </resources>
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 1ac6b50ebce552540c62051b8f8fc2b8f3be1886..70e2d20c5ce7c8204453dfdff75c52284c2872d8 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-
-
+    <string name="nav_drawer_open_description">Open the navigation drawer</string>
+    <string name="nav_drawer_close_description">Close the navigation drawer</string>
     <string name="app_name">Briar</string>
     <string name="crash_report_title">Briar Crash Report</string>
     <string name="ongoing_notification_title">Signed into Briar</string>
@@ -141,4 +141,15 @@
     <string name="dialog_message_delete_contact">Are you sure that you want to remove this contact and all messages exchanged with this contact?</string>
     <string name="dialog_title_connect_panic_app">Confirm Panic App</string>
     <string name="dialog_message_connect_panic_app">Are you sure that you want to allow %1$s to trigger destructive panic button actions?</string>
+    <string name="dialog_title_welcome">Welcome to Briar</string>
+    <string name="dialog_welcome_message">Add a contact to start communicating securely or press the icon in the upper left corner of the screen for more options.</string>
+    <string name="dialog_button_ok">OK</string>
+    <!-- Toolbar headers -->
+    <string name="dashboard_toolbar_header">Briar</string>
+    <string name="settings_toolbar_header">Settings</string>
+    <string name="contacts_toolbar_header">Contacts</string>
+    <string name="forums_toolbar_header">Forums</string>
+    <!-- Progress titles -->
+    <string name="progress_title_logout">Signing out of Briar..</string>
+    <string name="progress_title_please_wait">Please wait..</string>
 </resources>
diff --git a/briar-android/res/values/styles.xml b/briar-android/res/values/styles.xml
index 7a869c9051cf36783ee71cde92ad5d8157f2bfa5..2d10abf414fc10b5ea803aab15049cb8908fafd3 100644
--- a/briar-android/res/values/styles.xml
+++ b/briar-android/res/values/styles.xml
@@ -12,6 +12,36 @@
         <item name="android:textColorLink">@color/briar_text_link</item>
     </style>
 
+    <style name="BriarThemeNoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
+        <item name="toolbarStyle">@style/BriarToolbar</item>
+        <item name="colorPrimary">@color/briar_primary</item>
+        <item name="colorPrimaryDark">@color/briar_primary_dark</item>
+        <item name="colorAccent">@color/briar_primary</item>
+        <item name="android:textColorPrimary">@color/briar_text_primary</item>
+        <item name="android:textColorPrimaryInverse">@color/briar_text_primary_inverse</item>
+        <item name="android:textColorSecondary">@color/briar_text_primary</item>
+        <item name="android:textColorLink">@color/briar_text_link</item>
+    </style>
+
+    <style name="BriarThemeNoActionBar.Default" />
+
+    <style name="BriarToolbar" parent="Widget.AppCompat.Toolbar">
+        <item name="android:background">?colorPrimary</item>
+        <item name="android:textColorPrimary">@color/briar_text_primary_inverse</item>
+        <item name="android:textSize">@dimen/text_size_medium</item>
+        <item name="colorPrimary">@color/briar_primary</item>
+        <item name="titleTextAppearance">@style/BriarToolbarTextAppearance</item>
+        <item name="android:theme">@style/BriarToolbarTheme</item>
+    </style>
+
+    <style name="BriarToolbarTheme">
+        <item name="colorControlNormal">@color/briar_text_primary_inverse</item>
+    </style>
+
+    <style name="BriarToolbarTextAppearance" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
+        <item name="android:textColor">@color/briar_text_primary_inverse</item>
+    </style>
+
     <style name="BriarTheme" parent="BriarBaseTheme">
         <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
         <item name="android:listSeparatorTextViewStyle">@style/BriarTheme.ListSeparatorTextView</item>
@@ -33,6 +63,10 @@
         <item name="android:textColor">@android:color/primary_text_light</item>
     </style>
 
+    <style name="BriarTextTitleInverted" parent="BriarTextTitle">
+        <item name="android:textColor">@android:color/primary_text_dark</item>
+    </style>
+
     <style name="BriarTextBody">
         <item name="android:textSize">@dimen/text_size_small</item>
         <item name="android:textColor">@android:color/primary_text_light</item>
@@ -47,6 +81,17 @@
         <item name="android:layout_height">1px</item>
     </style>
 
+    <style name="NavMenuButton" parent="Widget.AppCompat.Button.Borderless.Colored">
+        <item name="android:textSize">@dimen/text_size_medium</item>
+        <item name="android:textColor">@android:color/tertiary_text_light</item>
+        <item name="android:paddingTop">@dimen/margin_large</item>
+        <item name="android:paddingBottom">@dimen/margin_large</item>
+        <item name="android:drawablePadding">@dimen/margin_xlarge</item>
+        <item name="android:gravity">left|center_vertical</item>
+        <item name="android:layout_margin">0dp</item>
+        <item name="android:paddingLeft">@dimen/margin_large</item>
+    </style>
+
     <!-- This fixes a UI bug in the support preference library -->
     <style name="BriarTheme.ListSeparatorTextView">
         <item name="android:textSize">14sp</item>
diff --git a/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java b/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
index f83f83082e1327a2750c827aa89efaaaef7b573f..a355f6b7375f59055fbb989ca989dc9d5e2cbf17 100644
--- a/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
+++ b/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
@@ -9,10 +9,8 @@ import android.support.v4.app.NotificationCompat;
 import android.support.v4.app.TaskStackBuilder;
 
 import org.briarproject.R;
-import org.briarproject.android.contact.ContactListActivity;
 import org.briarproject.android.contact.ConversationActivity;
 import org.briarproject.android.forum.ForumActivity;
-import org.briarproject.android.forum.ForumListActivity;
 import org.briarproject.api.Settings;
 import org.briarproject.api.android.AndroidExecutor;
 import org.briarproject.api.android.AndroidNotificationManager;
@@ -205,10 +203,11 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 				t.addNextIntent(i);
 				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
 			} else {
-				Intent i = new Intent(appContext, ContactListActivity.class);
+				Intent i = new Intent(appContext, NavDrawerActivity.class);
+				i.putExtra(NavDrawerActivity.INTENT_CONTACTS, true);
 				i.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
 				TaskStackBuilder t = TaskStackBuilder.create(appContext);
-				t.addParentStack(ContactListActivity.class);
+				t.addParentStack(NavDrawerActivity.class);
 				t.addNextIntent(i);
 				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
 			}
@@ -283,10 +282,11 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 				t.addNextIntent(i);
 				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
 			} else {
-				Intent i = new Intent(appContext, ForumListActivity.class);
+				Intent i = new Intent(appContext, NavDrawerActivity.class);
+				i.putExtra(NavDrawerActivity.INTENT_FORUMS, true);
 				i.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
 				TaskStackBuilder t = TaskStackBuilder.create(appContext);
-				t.addParentStack(ForumListActivity.class);
+				t.addParentStack(NavDrawerActivity.class);
 				t.addNextIntent(i);
 				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
 			}
diff --git a/briar-android/src/org/briarproject/android/BriarActivity.java b/briar-android/src/org/briarproject/android/BriarActivity.java
index fcc4ab604db3cb354b3c386d5e4b1e71d1148873..8d88cc5db1748b7a6f85254362eff717096c18e4 100644
--- a/briar-android/src/org/briarproject/android/BriarActivity.java
+++ b/briar-android/src/org/briarproject/android/BriarActivity.java
@@ -14,6 +14,7 @@ import org.briarproject.api.db.DatabaseExecutor;
 import org.briarproject.api.lifecycle.LifecycleManager;
 
 import java.util.concurrent.Executor;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.inject.Inject;
@@ -22,7 +23,10 @@ import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
 import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
 
 @SuppressLint("Registered")
-public class BriarActivity extends BaseActivity {
+public abstract class BriarActivity extends BaseActivity {
+
+	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;
 
@@ -125,7 +129,7 @@ public class BriarActivity extends BaseActivity {
 		});
 	}
 
-	protected void runOnDbThread(final Runnable task) {
+	public void runOnDbThread(final Runnable task) {
 		dbExecutor.execute(new Runnable() {
 			public void run() {
 				try {
diff --git a/briar-android/src/org/briarproject/android/BriarFragmentActivity.java b/briar-android/src/org/briarproject/android/BriarFragmentActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..573866aff27d51f124de60f3d7b332681019211a
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/BriarFragmentActivity.java
@@ -0,0 +1,102 @@
+package org.briarproject.android;
+
+import android.app.AlertDialog;
+import android.support.annotation.AnimRes;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v7.app.ActionBar;
+
+import org.briarproject.R;
+import org.briarproject.android.fragment.BaseFragment;
+import org.briarproject.android.contact.ContactListFragment;
+import org.briarproject.android.fragment.DashboardFragment;
+import org.briarproject.android.forum.ForumListFragment;
+import org.briarproject.android.fragment.SettingsFragment;
+
+/**
+ * This class should be extended by classes that wish to utilise fragments in
+ * Briar, it encapsulates all fragment related code.
+ */
+public abstract class BriarFragmentActivity extends BriarActivity {
+
+	private void updateToolbarTitle(String fragmentTag) {
+		ActionBar actionBar = getSupportActionBar();
+		if (actionBar == null)
+			return;
+
+		if (fragmentTag.equals(DashboardFragment.TAG)) {
+			actionBar.setTitle(R.string.dashboard_toolbar_header);
+		} else if (fragmentTag.equals(SettingsFragment.TAG)) {
+			actionBar.setTitle(R.string.settings_toolbar_header);
+		} else if (fragmentTag.equals(ContactListFragment.TAG)) {
+			actionBar.setTitle(R.string.contacts_toolbar_header);
+		} else if (fragmentTag.equals(ForumListFragment.TAG)) {
+			actionBar.setTitle(R.string.forums_toolbar_header);
+		}
+	}
+
+	protected void clearBackStack() {
+		getSupportFragmentManager()
+				.popBackStackImmediate(
+						null,
+						FragmentManager.POP_BACK_STACK_INCLUSIVE
+				);
+	}
+
+	@Override
+	public void onBackPressed() {
+		if (getSupportFragmentManager().getBackStackEntryCount() == 0 &&
+				getSupportFragmentManager()
+						.findFragmentByTag(ContactListFragment.TAG) == null) {
+			/*
+			This Makes sure that the first fragment (ContactListFragment) the
+			user sees is the same as the last fragment the user sees before
+			exiting. This models the typical Google navigation behaviour such
+			as in Gmail/Inbox.
+			 */
+			startFragment(ContactListFragment.newInstance());
+
+		} else {
+			super.onBackPressed();
+		}
+	}
+
+	protected void startFragment(BaseFragment fragment) {
+		if (getSupportFragmentManager().getBackStackEntryCount() == 0)
+			this.startFragment(fragment, false);
+		else
+			this.startFragment(fragment, true);
+	}
+
+	protected void showMessageDialog(int titleStringId, int msgStringId) {
+		// TODO replace with custom dialog fragment ?
+		AlertDialog.Builder builder = new AlertDialog.Builder(this);
+		builder.setTitle(titleStringId);
+		builder.setMessage(msgStringId);
+		builder.setPositiveButton(R.string.dialog_button_ok, null);
+		AlertDialog dialog = builder.create();
+		dialog.show();
+	}
+
+	protected void startFragment(BaseFragment fragment,
+			boolean isAddedToBackStack) {
+		this.startFragment(fragment, 0, 0, isAddedToBackStack);
+	}
+
+	protected void startFragment(BaseFragment fragment,
+			@AnimRes int inAnimation, @AnimRes int outAnimation,
+			boolean isAddedToBackStack) {
+		FragmentTransaction trans =
+				getSupportFragmentManager().beginTransaction();
+		if (inAnimation != 0 && outAnimation != 0) {
+			trans.setCustomAnimations(inAnimation, 0, 0, outAnimation);
+		}
+		trans.replace(R.id.content_fragment, fragment, fragment.getUniqueTag());
+		if (isAddedToBackStack) {
+			trans.addToBackStack(fragment.getUniqueTag());
+		}
+		trans.commit();
+		updateToolbarTitle(fragment.getUniqueTag());
+	}
+
+}
diff --git a/briar-android/src/org/briarproject/android/BriarService.java b/briar-android/src/org/briarproject/android/BriarService.java
index 90f774272b27d472ed7ad096141f3d3ce2a86d5b..f050d7c11c79901385cbc67139327c0af2f7e12d 100644
--- a/briar-android/src/org/briarproject/android/BriarService.java
+++ b/briar-android/src/org/briarproject/android/BriarService.java
@@ -70,7 +70,7 @@ public class BriarService extends RoboService {
 		b.setContentText(getText(R.string.ongoing_notification_text));
 		b.setWhen(0); // Don't show the time
 		b.setOngoing(true);
-		Intent i = new Intent(this, DashboardActivity.class);
+		Intent i = new Intent(this, NavDrawerActivity.class);
 		i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP |
 				FLAG_ACTIVITY_SINGLE_TOP);
 		b.setContentIntent(PendingIntent.getActivity(this, 0, i, 0));
@@ -117,7 +117,7 @@ public class BriarService extends RoboService {
 				NotificationManager nm = (NotificationManager) o;
 				nm.notify(FAILURE_NOTIFICATION_ID, b.build());
 				// Bring the dashboard to the front to clear the back stack
-				i = new Intent(BriarService.this, DashboardActivity.class);
+				i = new Intent(BriarService.this, NavDrawerActivity.class);
 				i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
 				i.putExtra("briar.STARTUP_FAILED", true);
 				startActivity(i);
diff --git a/briar-android/src/org/briarproject/android/DashboardActivity.java b/briar-android/src/org/briarproject/android/DashboardActivity.java
deleted file mode 100644
index 06e44b9b9d060f2a3647161b816d6c8b2362006e..0000000000000000000000000000000000000000
--- a/briar-android/src/org/briarproject/android/DashboardActivity.java
+++ /dev/null
@@ -1,381 +0,0 @@
-package org.briarproject.android;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.Button;
-import android.widget.GridView;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import org.briarproject.R;
-import org.briarproject.android.contact.ContactListActivity;
-import org.briarproject.android.forum.ForumListActivity;
-import org.briarproject.android.util.LayoutUtils;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.android.ReferenceManager;
-import org.briarproject.api.db.DbException;
-import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
-import org.briarproject.api.event.TransportDisabledEvent;
-import org.briarproject.api.event.TransportEnabledEvent;
-import org.briarproject.api.identity.IdentityManager;
-import org.briarproject.api.identity.LocalAuthor;
-import org.briarproject.api.plugins.Plugin;
-import org.briarproject.api.plugins.PluginManager;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
-
-import javax.inject.Inject;
-
-import static android.view.Gravity.CENTER;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static java.util.logging.Level.INFO;
-import static java.util.logging.Level.WARNING;
-import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
-
-public class DashboardActivity extends BriarActivity implements EventListener {
-
-	private static final Logger LOG =
-			Logger.getLogger(DashboardActivity.class.getName());
-
-	private List<Transport> transports;
-	private BaseAdapter transportsAdapter;
-
-	@Inject private ReferenceManager referenceManager;
-	@Inject private PluginManager pluginManager;
-
-	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile IdentityManager identityManager;
-	@Inject private volatile EventBus eventBus;
-
-	@Override
-	public void onCreate(Bundle state) {
-		super.onCreate(state);
-		handleIntent(getIntent());
-	}
-
-	@Override
-	public void onResume() {
-		super.onResume();
-		updateTransports();
-		eventBus.addListener(this);
-	}
-
-	@Override
-	public void onPause() {
-		super.onPause();
-		eventBus.removeListener(this);
-	}
-
-	@Override
-	public void onNewIntent(Intent i) {
-		super.onNewIntent(i);
-		handleIntent(i);
-	}
-
-	@Override
-	public void eventOccurred(Event e) {
-		if (e instanceof TransportEnabledEvent) {
-			TransportId id = ((TransportEnabledEvent) e).getTransportId();
-			if (LOG.isLoggable(INFO)) {
-				LOG.info("TransportEnabledEvent: " + id.getString());
-			}
-			setTransport(id, true);
-		} else if (e instanceof TransportDisabledEvent) {
-			TransportId id = ((TransportDisabledEvent) e).getTransportId();
-			if (LOG.isLoggable(INFO)) {
-				LOG.info("TransportDisabledEvent: " + id.getString());
-			}
-			setTransport(id, false);
-		}
-	}
-
-	private void handleIntent(Intent i) {
-		boolean failed = i.getBooleanExtra("briar.STARTUP_FAILED", false);
-		long handle = i.getLongExtra("briar.LOCAL_AUTHOR_HANDLE", -1);
-		if (failed) {
-			finish();
-			LOG.info("Exiting");
-			System.exit(0);
-		} else if (handle == -1) {
-			// The activity has been launched before
-			showButtons();
-		} else {
-			// The activity was launched from the setup wizard
-			LocalAuthor a = referenceManager.removeReference(handle,
-					LocalAuthor.class);
-			// The reference may be null if the activity has been recreated,
-			// for example due to screen rotation
-			if (a == null) {
-				showButtons();
-			} else {
-				showSpinner();
-				storeLocalAuthor(a);
-			}
-		}
-	}
-
-	private void showButtons() {
-		ListView.LayoutParams matchMatch =
-				new ListView.LayoutParams(MATCH_PARENT, MATCH_PARENT);
-		final List<Button> buttons = new ArrayList<Button>();
-
-		Button contactsButton = new Button(this);
-		contactsButton.setLayoutParams(matchMatch);
-		contactsButton.setBackgroundResource(0);
-		contactsButton.setCompoundDrawablesWithIntrinsicBounds(0,
-				R.drawable.social_person, 0, 0);
-		contactsButton.setText(R.string.contact_list_button);
-		contactsButton.setOnClickListener(new OnClickListener() {
-			public void onClick(View view) {
-				startActivity(new Intent(DashboardActivity.this,
-						ContactListActivity.class));
-			}
-		});
-		buttons.add(contactsButton);
-
-		Button forumsButton = new Button(this);
-		forumsButton.setLayoutParams(matchMatch);
-		forumsButton.setBackgroundResource(0);
-		forumsButton.setCompoundDrawablesWithIntrinsicBounds(0,
-				R.drawable.social_chat, 0, 0);
-		forumsButton.setText(R.string.forums_button);
-		forumsButton.setOnClickListener(new OnClickListener() {
-			public void onClick(View view) {
-				startActivity(new Intent(DashboardActivity.this,
-						ForumListActivity.class));
-			}
-		});
-		buttons.add(forumsButton);
-
-		Button settingsButton = new Button(this);
-		settingsButton.setLayoutParams(matchMatch);
-		settingsButton.setBackgroundResource(0);
-		settingsButton.setCompoundDrawablesWithIntrinsicBounds(0,
-				R.drawable.action_settings, 0, 0);
-		settingsButton.setText(R.string.settings_button);
-		settingsButton.setOnClickListener(new OnClickListener() {
-			public void onClick(View view) {
-				startActivity(new Intent(DashboardActivity.this,
-						SettingsActivity.class));
-			}
-		});
-		buttons.add(settingsButton);
-
-		Button signOutButton = new Button(this);
-		signOutButton.setLayoutParams(matchMatch);
-		signOutButton.setBackgroundResource(0);
-		signOutButton.setCompoundDrawablesWithIntrinsicBounds(0,
-				R.drawable.device_access_accounts, 0, 0);
-		signOutButton.setText(R.string.sign_out_button);
-		signOutButton.setOnClickListener(new OnClickListener() {
-			public void onClick(View view) {
-				showSpinner();
-				signOut();
-			}
-		});
-		buttons.add(signOutButton);
-
-		int pad = LayoutUtils.getPadding(this);
-
-		LinearLayout layout = new LinearLayout(this);
-		layout.setLayoutParams(MATCH_MATCH);
-		layout.setOrientation(LinearLayout.VERTICAL);
-
-		GridView grid = new GridView(this);
-		LinearLayout.LayoutParams params =
-				new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT, 1f);
-		grid.setLayoutParams(params);
-		grid.setGravity(CENTER);
-		grid.setPadding(pad, pad, pad, pad);
-		Resources res = getResources();
-		grid.setBackgroundColor(res.getColor(R.color.dashboard_background));
-		grid.setNumColumns(2);
-		grid.setAdapter(new BaseAdapter() {
-
-			public int getCount() {
-				return buttons.size();
-			}
-
-			public Object getItem(int position) {
-				return buttons.get(position);
-			}
-
-			public long getItemId(int position) {
-				return 0;
-			}
-
-			public View getView(int position, View convertView,
-					ViewGroup parent) {
-				return buttons.get(position);
-			}
-		});
-		layout.addView(grid);
-
-		// inflate transports layout
-		LayoutInflater inflater = (LayoutInflater) getSystemService
-				(Context.LAYOUT_INFLATER_SERVICE);
-		ViewGroup transportsLayout = (ViewGroup) inflater.
-				inflate(R.layout.transports_list, layout);
-
-		initializeTransports();
-
-		GridView transportsView = (GridView) transportsLayout.findViewById(
-				R.id.transportsView);
-		transportsView.setAdapter(transportsAdapter);
-
-		setContentView(layout);
-	}
-
-	private void showSpinner() {
-		LinearLayout layout = new LinearLayout(this);
-		layout.setLayoutParams(MATCH_MATCH);
-		layout.setGravity(CENTER);
-
-		ProgressBar progress = new ProgressBar(this);
-		progress.setIndeterminate(true);
-		layout.addView(progress);
-
-		setContentView(layout);
-	}
-
-	private void storeLocalAuthor(final LocalAuthor a) {
-		runOnDbThread(new Runnable() {
-			public void run() {
-				try {
-					long now = System.currentTimeMillis();
-					identityManager.addLocalAuthor(a);
-					long duration = System.currentTimeMillis() - now;
-					if (LOG.isLoggable(INFO))
-						LOG.info("Storing author took " + duration + " ms");
-					runOnUiThread(new Runnable() {
-						public void run() {
-							showButtons();
-						}
-					});
-				} catch (DbException e) {
-					if (LOG.isLoggable(WARNING))
-						LOG.log(WARNING, e.toString(), e);
-				}
-			}
-		});
-	}
-
-	private void initializeTransports() {
-		transports = new ArrayList<Transport>(3);
-
-		Transport tor = new Transport();
-		tor.id = new TransportId("tor");
-		Plugin torPlugin = pluginManager.getPlugin(tor.id);
-		tor.enabled = torPlugin != null && torPlugin.isRunning();
-		tor.iconId = R.drawable.transport_tor;
-		tor.textId = R.string.transport_tor;
-		transports.add(tor);
-
-		Transport bt = new Transport();
-		bt.id = new TransportId("bt");
-		Plugin btPlugin = pluginManager.getPlugin(bt.id);
-		bt.enabled = btPlugin != null && btPlugin.isRunning();
-		bt.iconId = R.drawable.transport_bt;
-		bt.textId = R.string.transport_bt;
-		transports.add(bt);
-
-		Transport lan = new Transport();
-		lan.id = new TransportId("lan");
-		Plugin lanPlugin = pluginManager.getPlugin(lan.id);
-		lan.enabled = lanPlugin != null && lanPlugin.isRunning();
-		lan.iconId = R.drawable.transport_lan;
-		lan.textId = R.string.transport_lan;
-		transports.add(lan);
-
-		transportsAdapter = new BaseAdapter() {
-			@Override
-			public int getCount() {
-				return transports.size();
-			}
-
-			@Override
-			public Transport getItem(int position) {
-				return transports.get(position);
-			}
-
-			@Override
-			public long getItemId(int position) {
-				return 0;
-			}
-
-			@Override
-			public View getView(int position, View convertView,
-					ViewGroup parent) {
-				LayoutInflater inflater = (LayoutInflater) getSystemService(
-						Context.LAYOUT_INFLATER_SERVICE);
-				ViewGroup view = (ViewGroup) inflater
-						.inflate(R.layout.list_item_transport, parent, false);
-
-				Transport t = getItem(position);
-				Resources r = getResources();
-
-				int c;
-				if (t.enabled) {
-					c = r.getColor(R.color.briar_green_light);
-				} else {
-					c = r.getColor(android.R.color.tertiary_text_light);
-				}
-
-				ImageView icon = (ImageView) view.findViewById(R.id.imageView);
-				icon.setImageDrawable(r.getDrawable(t.iconId));
-				icon.setColorFilter(c);
-
-				TextView text = (TextView) view.findViewById(R.id.textView);
-				text.setText(getString(t.textId));
-
-				return view;
-			}
-		};
-	}
-
-	private void setTransport(final TransportId id, final boolean enabled) {
-		runOnUiThread(new Runnable() {
-			public void run() {
-				if (transports == null || transportsAdapter == null) return;
-				for (Transport t : transports) {
-					if (t.id.equals(id)) {
-						t.enabled = enabled;
-						transportsAdapter.notifyDataSetChanged();
-						break;
-					}
-				}
-			}
-		});
-	}
-
-	private void updateTransports() {
-		if (transports == null || transportsAdapter == null) return;
-		for (Transport t : transports) {
-			Plugin plugin = pluginManager.getPlugin(t.id);
-			t.enabled = plugin != null && plugin.isRunning();
-		}
-		transportsAdapter.notifyDataSetChanged();
-	}
-
-	private static class Transport {
-		TransportId id;
-		boolean enabled;
-		int iconId;
-		int textId;
-	}
-}
diff --git a/briar-android/src/org/briarproject/android/NavDrawerActivity.java b/briar-android/src/org/briarproject/android/NavDrawerActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..f56f06a6dcdf4fa72dbac24da90b86f32d9b0c4c
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/NavDrawerActivity.java
@@ -0,0 +1,407 @@
+package org.briarproject.android;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBarDrawerToggle;
+import android.support.v7.widget.AppCompatButton;
+import android.support.v7.widget.Toolbar;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.briarproject.R;
+import org.briarproject.android.fragment.BaseFragment;
+import org.briarproject.android.contact.ContactListFragment;
+import org.briarproject.android.forum.ForumListFragment;
+import org.briarproject.android.fragment.SettingsFragment;
+import org.briarproject.android.util.CustomAnimations;
+import org.briarproject.api.TransportId;
+import org.briarproject.api.android.ReferenceManager;
+import org.briarproject.api.db.DbException;
+import org.briarproject.api.event.Event;
+import org.briarproject.api.event.EventBus;
+import org.briarproject.api.event.EventListener;
+import org.briarproject.api.event.TransportDisabledEvent;
+import org.briarproject.api.event.TransportEnabledEvent;
+import org.briarproject.api.identity.IdentityManager;
+import org.briarproject.api.identity.LocalAuthor;
+import org.briarproject.api.plugins.Plugin;
+import org.briarproject.api.plugins.PluginManager;
+
+import java.util.ArrayList;
+import java.util.List;
+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;
+
+public class NavDrawerActivity extends BriarFragmentActivity implements
+		BaseFragment.BaseFragmentListener, EventListener {
+
+	public static final String INTENT_CONTACTS = "intent_contacts";
+	public static final String INTENT_FORUMS = "intent_forums";
+
+	private static final Logger LOG =
+			Logger.getLogger(NavDrawerActivity.class.getName());
+
+	private final static String PREFS_USER_SETTINGS = "prefs_user_settings";
+	private final static String KEY_SEEN_WELCOME_MESSAGE = "welcome_message";
+
+	private ActionBarDrawerToggle drawerToggle;
+
+	@Inject
+	private ReferenceManager referenceManager;
+	// Fields that are accessed from background threads must be volatile
+	@Inject
+	private volatile IdentityManager identityManager;
+	@Inject
+	private 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 GridView transportsView;
+
+	private List<Transport> transports;
+	private BaseAdapter transportsAdapter;
+
+	@Override
+	protected void onNewIntent(Intent intent) {
+		super.onNewIntent(intent);
+		if (!isStartupFailed(intent)) {
+			checkAuthorHandle(intent);
+			clearBackStack();
+			if (intent.getBooleanExtra(INTENT_FORUMS, false))
+				startFragment(ForumListFragment.newInstance());
+			else if (intent.getBooleanExtra(INTENT_CONTACTS, false))
+				startFragment(ContactListFragment.newInstance());
+		}
+	}
+
+	@SuppressWarnings("ConstantConditions")
+	@Override
+	public void onCreate(Bundle state) {
+		super.onCreate(state);
+
+		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);
+
+		setSupportActionBar(toolbar);
+		getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+		getSupportActionBar().setHomeButtonEnabled(true);
+
+		drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar,
+				R.string.nav_drawer_open_description,
+				R.string.nav_drawer_close_description
+		) {
+
+			public void onDrawerClosed(View view) {
+				super.onDrawerClosed(view);
+			}
+
+			public void onDrawerOpened(View drawerView) {
+				super.onDrawerOpened(drawerView);
+			}
+		};
+		drawerLayout.setDrawerListener(drawerToggle);
+		startFragment(ContactListFragment.newInstance());
+		checkAuthorHandle(getIntent());
+
+		initializeTransports(getLayoutInflater());
+		transportsView.setAdapter(transportsAdapter);
+
+		welcomeMessageCheck();
+	}
+
+	private void welcomeMessageCheck() {
+		SharedPreferences prefs = getSharedPreferences(PREFS_USER_SETTINGS,
+				Context.MODE_PRIVATE);
+		if (!prefs.getBoolean(KEY_SEEN_WELCOME_MESSAGE, false)) {
+			showMessageDialog(R.string.dialog_title_welcome,
+					R.string.dialog_welcome_message);
+			prefs.edit().putBoolean(KEY_SEEN_WELCOME_MESSAGE, true).apply();
+		}
+	}
+
+	@Override
+	public void onResume() {
+		super.onResume();
+		eventBus.addListener(this);
+		updateTransports();
+	}
+
+	@Override
+	protected void onPause() {
+		super.onPause();
+		eventBus.removeListener(this);
+	}
+
+	private void checkAuthorHandle(Intent intent) {
+		long handle = intent.getLongExtra(KEY_LOCAL_AUTHOR_HANDLE, -1);
+		if (handle != -1) {
+			// The activity was launched from the setup wizard
+			LocalAuthor a = referenceManager.removeReference(handle,
+					LocalAuthor.class);
+			if (a != null) {
+				showLoadingScreen(true, R.string.progress_title_please_wait);
+				storeLocalAuthor(a);
+			}
+		}
+	}
+
+	private boolean isStartupFailed(Intent intent) {
+		if (intent.getBooleanExtra(KEY_STARTUP_FAILED, false)) {
+			finish();
+			LOG.info("Exiting");
+			System.exit(0);
+			return true;
+		}
+		return false;
+	}
+
+	private void storeLocalAuthor(final LocalAuthor a) {
+		runOnDbThread(new Runnable() {
+			public void run() {
+				try {
+					long now = System.currentTimeMillis();
+					identityManager.addLocalAuthor(a);
+					long duration = System.currentTimeMillis() - now;
+					if (LOG.isLoggable(INFO))
+						LOG.info("Storing author took " + duration + " ms");
+
+					runOnUiThread(new Runnable() {
+						public void run() {
+							hideLoadingScreen();
+						}
+					});
+
+				} catch (DbException e) {
+					if (LOG.isLoggable(WARNING))
+						LOG.log(WARNING, e.toString(), e);
+				}
+			}
+		});
+	}
+
+	public void onNavigationClick(View view) {
+		drawerLayout.closeDrawer(GravityCompat.START);
+		clearBackStack();
+		switch (view.getId()) {
+			case R.id.nav_btn_contacts:
+				startFragment(ContactListFragment.newInstance());
+				break;
+			case R.id.nav_btn_forums:
+				startFragment(ForumListFragment.newInstance());
+				break;
+			case R.id.nav_btn_settings:
+				startFragment(SettingsFragment.newInstance());
+				break;
+			case R.id.nav_btn_signout:
+				signOut();
+				break;
+		}
+	}
+
+
+	@Override
+	public void onBackPressed() {
+		if (getSupportFragmentManager().getBackStackEntryCount() == 0
+				&& drawerLayout.isDrawerOpen(GravityCompat.START)) {
+			drawerLayout.closeDrawer(GravityCompat.START);
+			return;
+		}
+		super.onBackPressed();
+	}
+
+	@Override
+	protected void onPostCreate(Bundle savedInstanceState) {
+		super.onPostCreate(savedInstanceState);
+		drawerToggle.syncState();
+	}
+
+	@Override
+	public void onConfigurationChanged(Configuration newConfig) {
+		super.onConfigurationChanged(newConfig);
+		drawerToggle.onConfigurationChanged(newConfig);
+	}
+
+	@Override
+	protected void signOut() {
+		showLoadingScreen(true, R.string.progress_title_logout);
+		super.signOut();
+	}
+
+	@Override
+	public void showLoadingScreen(boolean isBlocking, int stringId) {
+		if (isBlocking) {
+			// Disable navigation drawer slide to open
+			drawerLayout
+					.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
+			CustomAnimations.animateHeight(toolbar, false, 250);
+		}
+		progressTitle.setText(stringId);
+		progressViewGroup.setVisibility(View.VISIBLE);
+	}
+
+	@Override
+	public void hideLoadingScreen() {
+		drawerLayout
+				.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
+		CustomAnimations.animateHeight(toolbar, true, 250);
+		progressViewGroup.setVisibility(View.INVISIBLE);
+	}
+
+	private void initializeTransports(final LayoutInflater inflater) {
+		transports = new ArrayList<Transport>(3);
+
+		Transport tor = new Transport();
+		tor.id = new TransportId("tor");
+		Plugin torPlugin = pluginManager.getPlugin(tor.id);
+		tor.enabled = torPlugin != null && torPlugin.isRunning();
+		tor.iconId = R.drawable.transport_tor;
+		tor.textId = R.string.transport_tor;
+		transports.add(tor);
+
+		Transport bt = new Transport();
+		bt.id = new TransportId("bt");
+		Plugin btPlugin = pluginManager.getPlugin(bt.id);
+		bt.enabled = btPlugin != null && btPlugin.isRunning();
+		bt.iconId = R.drawable.transport_bt;
+		bt.textId = R.string.transport_bt;
+		transports.add(bt);
+
+		Transport lan = new Transport();
+		lan.id = new TransportId("lan");
+		Plugin lanPlugin = pluginManager.getPlugin(lan.id);
+		lan.enabled = lanPlugin != null && lanPlugin.isRunning();
+		lan.iconId = R.drawable.transport_lan;
+		lan.textId = R.string.transport_lan;
+		transports.add(lan);
+
+		transportsAdapter = new BaseAdapter() {
+			@Override
+			public int getCount() {
+				return transports.size();
+			}
+
+			@Override
+			public Transport getItem(int position) {
+				return transports.get(position);
+			}
+
+			@Override
+			public long getItemId(int position) {
+				return 0;
+			}
+
+			@Override
+			public View getView(int position, View convertView,
+					ViewGroup parent) {
+				ViewGroup view = (ViewGroup) inflater
+						.inflate(R.layout.list_item_transport, parent, false);
+
+				Transport t = getItem(position);
+				Resources r = getResources();
+
+				int c;
+				if (t.enabled) {
+					c = r.getColor(R.color.briar_green_light);
+				} else {
+					c = r.getColor(android.R.color.tertiary_text_light);
+				}
+
+				ImageView icon = (ImageView) view.findViewById(R.id.imageView);
+				icon.setImageDrawable(r.getDrawable(t.iconId));
+				icon.setColorFilter(c);
+
+				TextView text = (TextView) view.findViewById(R.id.textView);
+				text.setText(getString(t.textId));
+
+				return view;
+			}
+		};
+	}
+
+	private void setTransport(final TransportId id, final boolean enabled) {
+		runOnUiThread(new Runnable() {
+			public void run() {
+				if (transports == null || transportsAdapter == null) return;
+				for (Transport t : transports) {
+					if (t.id.equals(id)) {
+						t.enabled = enabled;
+						transportsAdapter.notifyDataSetChanged();
+						break;
+					}
+				}
+			}
+		});
+	}
+
+	private void updateTransports() {
+		if (transports == null || transportsAdapter == null) return;
+		for (Transport t : transports) {
+			Plugin plugin = pluginManager.getPlugin(t.id);
+			t.enabled = plugin != null && plugin.isRunning();
+		}
+		transportsAdapter.notifyDataSetChanged();
+	}
+
+	@Override
+	public void eventOccurred(Event e) {
+		if (e instanceof TransportEnabledEvent) {
+			TransportId id = ((TransportEnabledEvent) e).getTransportId();
+			if (LOG.isLoggable(INFO)) {
+				LOG.info("TransportEnabledEvent: " + id.getString());
+			}
+			setTransport(id, true);
+		} else if (e instanceof TransportDisabledEvent) {
+			TransportId id = ((TransportDisabledEvent) e).getTransportId();
+			if (LOG.isLoggable(INFO)) {
+				LOG.info("TransportDisabledEvent: " + id.getString());
+			}
+			setTransport(id, false);
+		}
+	}
+
+	private static class Transport {
+		TransportId id;
+		boolean enabled;
+		int iconId;
+		int textId;
+	}
+}
diff --git a/briar-android/src/org/briarproject/android/SetupActivity.java b/briar-android/src/org/briarproject/android/SetupActivity.java
index 237dca1f8f5fc9b059838718caa56c6469b314b2..81e832d5f0da4e64b9c41fbfed3613885a894d54 100644
--- a/briar-android/src/org/briarproject/android/SetupActivity.java
+++ b/briar-android/src/org/briarproject/android/SetupActivity.java
@@ -176,8 +176,8 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
 		runOnUiThread(new Runnable() {
 			public void run() {
 				Intent i = new Intent(SetupActivity.this,
-						DashboardActivity.class);
-				i.putExtra("briar.LOCAL_AUTHOR_HANDLE", handle);
+						NavDrawerActivity.class);
+				i.putExtra(BriarActivity.KEY_LOCAL_AUTHOR_HANDLE, handle);
 				i.setFlags(FLAG_ACTIVITY_NEW_TASK);
 				startActivity(i);
 				finish();
diff --git a/briar-android/src/org/briarproject/android/SplashScreenActivity.java b/briar-android/src/org/briarproject/android/SplashScreenActivity.java
index ddf3dbc23fc2f6457703f0d2231118b5c11c3a3b..f35aea013901a85b15f59dbc53a1b6dcd78ce7d9 100644
--- a/briar-android/src/org/briarproject/android/SplashScreenActivity.java
+++ b/briar-android/src/org/briarproject/android/SplashScreenActivity.java
@@ -84,7 +84,7 @@ public class SplashScreenActivity extends RoboSplashActivity {
 			Injector i = RoboGuice.getBaseApplicationInjector(getApplication());
 			DatabaseConfig databaseConfig = i.getInstance(DatabaseConfig.class);
 			if (hex != null && databaseConfig.databaseExists()) {
-				startActivity(new Intent(this, DashboardActivity.class));
+				startActivity(new Intent(this, NavDrawerActivity.class));
 			} else {
 				prefs.edit().clear().apply();
 				FileUtils.deleteFileOrDir(
diff --git a/briar-android/src/org/briarproject/android/TestingConstants.java b/briar-android/src/org/briarproject/android/TestingConstants.java
index aa8dce68f7387ca2723907058590c18aee18873a..7c20594f6315e159e633ad5ec6400d6979d97fd7 100644
--- a/briar-android/src/org/briarproject/android/TestingConstants.java
+++ b/briar-android/src/org/briarproject/android/TestingConstants.java
@@ -5,7 +5,7 @@ import static java.util.logging.Level.OFF;
 
 import java.util.logging.Level;
 
-interface TestingConstants {
+public interface TestingConstants {
 
 	/**
 	 * Whether this is an alpha or beta build. This should be set to false for
@@ -25,7 +25,7 @@ interface TestingConstants {
 	boolean PREVENT_SCREENSHOTS = TESTING ? false : true;
 
 	/**
-	 * Whether to allow TestingActivity to be launched from SettingsActivity.
+	 * Whether to allow TestingActivity to be launched from SettingsFragment.
 	 */
 	boolean SHOW_TESTING_ACTIVITY = TESTING ? true : false;
 
diff --git a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
similarity index 77%
rename from briar-android/src/org/briarproject/android/contact/ContactListActivity.java
rename to briar-android/src/org/briarproject/android/contact/ContactListFragment.java
index 03e7595a7e1d82a5139cd6442b58cafae7ec2f04..d2bff01e582b45a40cb0c2bee5adbc1c897c9db8 100644
--- a/briar-android/src/org/briarproject/android/contact/ContactListActivity.java
+++ b/briar-android/src/org/briarproject/android/contact/ContactListFragment.java
@@ -2,12 +2,15 @@ package org.briarproject.android.contact;
 
 import android.content.Intent;
 import android.os.Bundle;
+import android.support.annotation.Nullable;
 import android.support.design.widget.FloatingActionButton;
 import android.support.v7.widget.LinearLayoutManager;
+import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 
 import org.briarproject.R;
-import org.briarproject.android.BriarActivity;
+import org.briarproject.android.fragment.BaseEventFragment;
 import org.briarproject.android.invitation.AddContactActivity;
 import org.briarproject.android.util.BriarRecyclerView;
 import org.briarproject.api.contact.Contact;
@@ -21,7 +24,6 @@ import org.briarproject.api.event.ContactDisconnectedEvent;
 import org.briarproject.api.event.ContactRemovedEvent;
 import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.MessageValidatedEvent;
 import org.briarproject.api.messaging.MessagingManager;
 import org.briarproject.api.messaging.PrivateMessageHeader;
@@ -39,63 +41,82 @@ import javax.inject.Inject;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 
-public class ContactListActivity extends BriarActivity
-		implements EventListener {
+public class ContactListFragment extends BaseEventFragment {
 
 	private static final Logger LOG =
-			Logger.getLogger(ContactListActivity.class.getName());
+			Logger.getLogger(ContactListFragment.class.getName());
 
-	@Inject private ConnectionRegistry connectionRegistry;
-	private ContactListAdapter adapter = null;
-	private BriarRecyclerView list = null;
+	public final static String TAG = "ContactListFragment";
 
-	// 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;
+	public static ContactListFragment newInstance() {
+
+		Bundle args = new Bundle();
+
+		ContactListFragment fragment = new ContactListFragment();
+		fragment.setArguments(args);
+		return fragment;
+	}
 
 	@Override
-	public void onCreate(Bundle state) {
-		super.onCreate(state);
+	public String getUniqueTag() {
+		return TAG;
+	}
 
-		setContentView(R.layout.activity_contact_list);
+	@Inject
+	private ConnectionRegistry connectionRegistry;
+	private ContactListAdapter adapter = null;
+	private BriarRecyclerView list = null;
 
-		adapter = new ContactListAdapter(this);
-		list = (BriarRecyclerView) findViewById(R.id.contactList);
-		list.setLayoutManager(new LinearLayoutManager(this));
+	// 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;
+
+	@Nullable
+	@Override
+	public View onCreateView(LayoutInflater inflater, ViewGroup container,
+			Bundle savedInstanceState) {
+		View contentView =
+				inflater.inflate(R.layout.activity_contact_list, container,
+						false);
+
+		adapter = new ContactListAdapter(getContext());
+		list = (BriarRecyclerView) contentView.findViewById(R.id.contactList);
+		list.setLayoutManager(new LinearLayoutManager(getContext()));
 		list.setAdapter(adapter);
 		list.setEmptyText(getString(R.string.no_contacts));
 
 		// Show a floating action button
-		FloatingActionButton fab = (FloatingActionButton) findViewById(
-				R.id.addContactFAB);
+		FloatingActionButton fab =
+				(FloatingActionButton) contentView.findViewById(
+						R.id.addContactFAB);
 
 		// handle FAB click
 		fab.setOnClickListener(new View.OnClickListener() {
 			@Override
 			public void onClick(View v) {
-				startActivity(new Intent(ContactListActivity.this,
+				startActivity(new Intent(getContext(),
 						AddContactActivity.class));
 			}
 		});
-	}
 
-	@Override
-	public void onPause() {
-		super.onPause();
-		eventBus.removeListener(this);
+		return contentView;
 	}
 
+
 	@Override
 	public void onResume() {
 		super.onResume();
-		eventBus.addListener(this);
+
 		loadContacts();
 	}
 
 
 	private void loadContacts() {
-		runOnDbThread(new Runnable() {
+		listener.runOnDbThread(new Runnable() {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
@@ -113,7 +134,7 @@ public class ContactListActivity extends BriarActivity
 							contacts.add(new ContactListItem(c, connected,
 									groupId, headers));
 						} catch (NoSuchContactException e) {
-							LOG.info("Contact removed");
+							// Continue
 						}
 					}
 					displayContacts(contacts);
@@ -129,7 +150,7 @@ public class ContactListActivity extends BriarActivity
 	}
 
 	private void displayContacts(final List<ContactListItem> contacts) {
-		runOnUiThread(new Runnable() {
+		listener.runOnUiThread(new Runnable() {
 			public void run() {
 				adapter.clear();
 				if (contacts.size() == 0) list.showData();
@@ -160,7 +181,7 @@ public class ContactListActivity extends BriarActivity
 	}
 
 	private void reloadConversation(final GroupId g) {
-		runOnDbThread(new Runnable() {
+		listener.runOnDbThread(new Runnable() {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
@@ -183,7 +204,7 @@ public class ContactListActivity extends BriarActivity
 
 	private void updateItem(final ContactId c,
 			final Collection<PrivateMessageHeader> headers) {
-		runOnUiThread(new Runnable() {
+		listener.runOnUiThread(new Runnable() {
 			public void run() {
 				int position = adapter.findItemPosition(c);
 				ContactListItem item = adapter.getItem(position);
@@ -196,7 +217,7 @@ public class ContactListActivity extends BriarActivity
 	}
 
 	private void removeItem(final ContactId c) {
-		runOnUiThread(new Runnable() {
+		listener.runOnUiThread(new Runnable() {
 			public void run() {
 				int position = adapter.findItemPosition(c);
 				ContactListItem item = adapter.getItem(position);
@@ -206,7 +227,7 @@ public class ContactListActivity extends BriarActivity
 	}
 
 	private void setConnected(final ContactId c, final boolean connected) {
-		runOnUiThread(new Runnable() {
+		listener.runOnUiThread(new Runnable() {
 			public void run() {
 				int position = adapter.findItemPosition(c);
 				ContactListItem item = adapter.getItem(position);
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java b/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java
index 17a7e2f2a4f847574c19e2dcb97c9582498f5477..0fb713a74d443b45c2a85f0461e8449ef65022c2 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumListAdapter.java
@@ -18,11 +18,11 @@ import static android.text.TextUtils.TruncateAt.END;
 import static android.widget.LinearLayout.HORIZONTAL;
 import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP_1;
 
-class ForumListAdapter extends ArrayAdapter<ForumListItem> {
+public class ForumListAdapter extends ArrayAdapter<ForumListItem> {
 
 	private final int pad;
 
-	ForumListAdapter(Context ctx) {
+	public ForumListAdapter(Context ctx) {
 		super(ctx, android.R.layout.simple_expandable_list_item_1,
 				new ArrayList<ForumListItem>());
 		pad = LayoutUtils.getPadding(ctx);
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListActivity.java b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
similarity index 83%
rename from briar-android/src/org/briarproject/android/forum/ForumListActivity.java
rename to briar-android/src/org/briarproject/android/forum/ForumListFragment.java
index fef329409a2b21c4c62bb4a0f2ba9d64fcf91c5c..55f34f75693021528fa1027914f591f6907489c6 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListActivity.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumListFragment.java
@@ -3,15 +3,15 @@ package org.briarproject.android.forum;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.os.Bundle;
+import android.support.annotation.Nullable;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnCreateContextMenuListener;
+import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.AdapterView.AdapterContextMenuInfo;
-import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ImageButton;
 import android.widget.LinearLayout;
 import android.widget.ListView;
@@ -19,15 +19,13 @@ import android.widget.TextView;
 import android.widget.Toast;
 
 import org.briarproject.R;
-import org.briarproject.android.BriarActivity;
+import org.briarproject.android.fragment.BaseEventFragment;
 import org.briarproject.android.util.HorizontalBorder;
 import org.briarproject.android.util.LayoutUtils;
 import org.briarproject.android.util.ListLoadingProgressBar;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.db.NoSuchSubscriptionException;
 import org.briarproject.api.event.Event;
-import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.MessageValidatedEvent;
 import org.briarproject.api.event.RemoteSubscriptionsUpdatedEvent;
 import org.briarproject.api.event.SubscriptionAddedEvent;
@@ -58,13 +56,24 @@ import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
 import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP;
 import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1;
 
-public class ForumListActivity extends BriarActivity
-		implements EventListener, OnClickListener, OnItemClickListener,
-		OnCreateContextMenuListener {
+public class ForumListFragment extends BaseEventFragment implements
+		AdapterView.OnItemClickListener, View.OnClickListener {
+
+	public final static String TAG = "ForumListFragment";
 
-	private static final int MENU_ITEM_UNSUBSCRIBE = 1;
 	private static final Logger LOG =
-			Logger.getLogger(ForumListActivity.class.getName());
+			Logger.getLogger(ForumListFragment.class.getName());
+
+	public static ForumListFragment newInstance() {
+
+		Bundle args = new Bundle();
+
+		ForumListFragment fragment = new ForumListFragment();
+		fragment.setArguments(args);
+		return fragment;
+	}
+
+	private static final int MENU_ITEM_UNSUBSCRIBE = 1;
 
 	private TextView empty = null;
 	private ForumListAdapter adapter = null;
@@ -74,20 +83,21 @@ public class ForumListActivity extends BriarActivity
 	private ImageButton newForumButton = null;
 
 	// Fields that are accessed from background threads must be volatile
-	@Inject private volatile ForumManager forumManager;
-	@Inject private volatile EventBus eventBus;
+	@Inject
+	private volatile ForumManager forumManager;
 
+	@Nullable
 	@Override
-	public void onCreate(Bundle state) {
-		super.onCreate(state);
-		LinearLayout layout = new LinearLayout(this);
+	public View onCreateView(LayoutInflater inflater, ViewGroup container,
+			Bundle savedInstanceState) {
+		LinearLayout layout = new LinearLayout(getContext());
 		layout.setLayoutParams(MATCH_MATCH);
 		layout.setOrientation(VERTICAL);
 		layout.setGravity(CENTER_HORIZONTAL);
 
-		int pad = LayoutUtils.getPadding(this);
+		int pad = LayoutUtils.getPadding(getContext());
 
-		empty = new TextView(this);
+		empty = new TextView(getContext());
 		empty.setLayoutParams(MATCH_WRAP_1);
 		empty.setGravity(CENTER);
 		empty.setTextSize(18);
@@ -95,8 +105,8 @@ public class ForumListActivity extends BriarActivity
 		empty.setVisibility(GONE);
 		layout.addView(empty);
 
-		adapter = new ForumListAdapter(this);
-		list = new ListView(this);
+		adapter = new ForumListAdapter(getContext());
+		list = new ListView(getContext());
 		list.setLayoutParams(MATCH_WRAP_1);
 		list.setAdapter(adapter);
 		list.setOnItemClickListener(this);
@@ -105,10 +115,10 @@ public class ForumListActivity extends BriarActivity
 		layout.addView(list);
 
 		// Show a progress bar while the list is loading
-		loading = new ListLoadingProgressBar(this);
+		loading = new ListLoadingProgressBar(getContext());
 		layout.addView(loading);
 
-		available = new TextView(this);
+		available = new TextView(getContext());
 		available.setLayoutParams(MATCH_WRAP);
 		available.setGravity(CENTER);
 		available.setTextSize(18);
@@ -120,33 +130,37 @@ public class ForumListActivity extends BriarActivity
 		available.setVisibility(GONE);
 		layout.addView(available);
 
-		layout.addView(new HorizontalBorder(this));
+		layout.addView(new HorizontalBorder(getContext()));
 
-		LinearLayout footer = new LinearLayout(this);
+		LinearLayout footer = new LinearLayout(getContext());
 		footer.setLayoutParams(MATCH_WRAP);
 		footer.setOrientation(HORIZONTAL);
 		footer.setGravity(CENTER);
 		footer.setBackgroundColor(res.getColor(R.color.button_bar_background));
-		newForumButton = new ImageButton(this);
+		newForumButton = new ImageButton(getContext());
 		newForumButton.setBackgroundResource(0);
 		newForumButton.setImageResource(R.drawable.social_new_chat);
 		newForumButton.setOnClickListener(this);
 		footer.addView(newForumButton);
 		layout.addView(footer);
 
-		setContentView(layout);
+		return layout;
+	}
+
+	@Override
+	public String getUniqueTag() {
+		return TAG;
 	}
 
 	@Override
 	public void onResume() {
 		super.onResume();
-		eventBus.addListener(this);
 		loadHeaders();
 	}
 
 	private void loadHeaders() {
 		clearHeaders();
-		runOnDbThread(new Runnable() {
+		listener.runOnDbThread(new Runnable() {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
@@ -173,7 +187,7 @@ public class ForumListActivity extends BriarActivity
 	}
 
 	private void clearHeaders() {
-		runOnUiThread(new Runnable() {
+		listener.runOnUiThread(new Runnable() {
 			public void run() {
 				empty.setVisibility(GONE);
 				list.setVisibility(GONE);
@@ -186,7 +200,7 @@ public class ForumListActivity extends BriarActivity
 
 	private void displayHeaders(final Forum f,
 			final Collection<ForumPostHeader> headers) {
-		runOnUiThread(new Runnable() {
+		listener.runOnUiThread(new Runnable() {
 			public void run() {
 				list.setVisibility(VISIBLE);
 				loading.setVisibility(GONE);
@@ -202,7 +216,7 @@ public class ForumListActivity extends BriarActivity
 	}
 
 	private void displayAvailable(final int availableCount) {
-		runOnUiThread(new Runnable() {
+		listener.runOnUiThread(new Runnable() {
 			public void run() {
 				if (adapter.isEmpty()) empty.setVisibility(VISIBLE);
 				loading.setVisibility(GONE);
@@ -239,12 +253,6 @@ public class ForumListActivity extends BriarActivity
 		else list.setSelection(firstUnread);
 	}
 
-	@Override
-	public void onPause() {
-		super.onPause();
-		eventBus.removeListener(this);
-	}
-
 	public void eventOccurred(Event e) {
 		if (e instanceof MessageValidatedEvent) {
 			MessageValidatedEvent m = (MessageValidatedEvent) e;
@@ -269,7 +277,7 @@ public class ForumListActivity extends BriarActivity
 	}
 
 	private void loadHeaders(final GroupId g) {
-		runOnDbThread(new Runnable() {
+		listener.runOnDbThread(new Runnable() {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
@@ -291,7 +299,7 @@ public class ForumListActivity extends BriarActivity
 	}
 
 	private void removeForum(final GroupId g) {
-		runOnUiThread(new Runnable() {
+		listener.runOnUiThread(new Runnable() {
 			public void run() {
 				ForumListItem item = findForum(g);
 				if (item != null) {
@@ -308,7 +316,7 @@ public class ForumListActivity extends BriarActivity
 	}
 
 	private void loadAvailable() {
-		runOnDbThread(new Runnable() {
+		listener.runOnDbThread(new Runnable() {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
@@ -327,15 +335,16 @@ public class ForumListActivity extends BriarActivity
 
 	public void onClick(View view) {
 		if (view == available) {
-			startActivity(new Intent(this, AvailableForumsActivity.class));
+			startActivity(new Intent(getContext(),
+					AvailableForumsActivity.class));
 		} else if (view == newForumButton) {
-			startActivity(new Intent(this, CreateForumActivity.class));
+			startActivity(new Intent(getContext(), CreateForumActivity.class));
 		}
 	}
 
 	public void onItemClick(AdapterView<?> parent, View view, int position,
 			long id) {
-		Intent i = new Intent(this, ForumActivity.class);
+		Intent i = new Intent(getContext(), ForumActivity.class);
 		Forum f = adapter.getItem(position).getForum();
 		i.putExtra("briar.GROUP_ID", f.getId().getBytes());
 		i.putExtra("briar.FORUM_NAME", f.getName());
@@ -344,7 +353,7 @@ public class ForumListActivity extends BriarActivity
 
 	@Override
 	public void onCreateContextMenu(ContextMenu menu, View view,
-			ContextMenu.ContextMenuInfo info) {
+			ContextMenuInfo info) {
 		String delete = getString(R.string.unsubscribe);
 		menu.add(NONE, MENU_ITEM_UNSUBSCRIBE, NONE, delete);
 	}
@@ -357,13 +366,13 @@ public class ForumListActivity extends BriarActivity
 			ForumListItem item = adapter.getItem(position);
 			removeSubscription(item.getForum());
 			String unsubscribed = getString(R.string.unsubscribed_toast);
-			Toast.makeText(this, unsubscribed, LENGTH_SHORT).show();
+			Toast.makeText(getContext(), unsubscribed, LENGTH_SHORT).show();
 		}
 		return true;
 	}
 
 	private void removeSubscription(final Forum f) {
-		runOnDbThread(new Runnable() {
+		listener.runOnDbThread(new Runnable() {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
@@ -378,4 +387,4 @@ public class ForumListActivity extends BriarActivity
 			}
 		});
 	}
-}
\ No newline at end of file
+}
diff --git a/briar-android/src/org/briarproject/android/forum/ForumListItemComparator.java b/briar-android/src/org/briarproject/android/forum/ForumListItemComparator.java
index 2c7ac144933d001922b2809dd7bc7875752cdb3a..bc50231c30d85a47d1baf68794a4832a3829dd11 100644
--- a/briar-android/src/org/briarproject/android/forum/ForumListItemComparator.java
+++ b/briar-android/src/org/briarproject/android/forum/ForumListItemComparator.java
@@ -2,9 +2,9 @@ package org.briarproject.android.forum;
 
 import java.util.Comparator;
 
-class ForumListItemComparator implements Comparator<ForumListItem> {
+public class ForumListItemComparator implements Comparator<ForumListItem> {
 
-	static final ForumListItemComparator INSTANCE =
+	public static final ForumListItemComparator INSTANCE =
 			new ForumListItemComparator();
 
 	public int compare(ForumListItem a, ForumListItem b) {
diff --git a/briar-android/src/org/briarproject/android/fragment/BaseEventFragment.java b/briar-android/src/org/briarproject/android/fragment/BaseEventFragment.java
new file mode 100644
index 0000000000000000000000000000000000000000..f353b6e08dddc6c4862fc21a531b0b591f14dcf1
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/fragment/BaseEventFragment.java
@@ -0,0 +1,28 @@
+package org.briarproject.android.fragment;
+
+import org.briarproject.api.event.EventBus;
+import org.briarproject.api.event.EventListener;
+
+import javax.inject.Inject;
+
+/**
+ * Created by Ernir Erlingsson (ernir@ymirmobile.com) on 8.1.2016.
+ */
+public abstract class BaseEventFragment extends BaseFragment implements
+		EventListener {
+
+	@Inject
+	protected volatile EventBus eventBus;
+
+	@Override
+	public void onResume() {
+		super.onResume();
+		eventBus.addListener(this);
+	}
+
+	@Override
+	public void onPause() {
+		super.onPause();
+		eventBus.removeListener(this);
+	}
+}
diff --git a/briar-android/src/org/briarproject/android/fragment/BaseFragment.java b/briar-android/src/org/briarproject/android/fragment/BaseFragment.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d69a5870edf9d45e7cc0986085f1101250f568a
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/fragment/BaseFragment.java
@@ -0,0 +1,35 @@
+package org.briarproject.android.fragment;
+
+import android.content.Context;
+
+import org.briarproject.android.BriarActivity;
+
+import roboguice.fragment.RoboFragment;
+
+public abstract class BaseFragment extends RoboFragment {
+
+	public abstract String getUniqueTag();
+
+	protected BaseFragmentListener listener;
+
+	protected BriarActivity briarActivity;
+
+	@Override
+	public void onAttach(Context context) {
+		super.onAttach(context);
+		try {
+			listener = (BaseFragmentListener) context;
+		} catch (ClassCastException e) {
+			throw new ClassCastException(
+					"Using class must implement BaseFragmentListener");
+		}
+	}
+
+	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
new file mode 100644
index 0000000000000000000000000000000000000000..b1eb92585bb10a5d7ef1135dae35ae09d6a2eb3f
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/fragment/DashboardFragment.java
@@ -0,0 +1,66 @@
+package org.briarproject.android.fragment;
+
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.GridView;
+
+import org.briarproject.R;
+import org.briarproject.api.event.Event;
+import org.briarproject.api.plugins.PluginManager;
+
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+import roboguice.inject.InjectView;
+
+public class DashboardFragment extends BaseEventFragment {
+
+	public final static String TAG = "DashboardFragment";
+
+	private static final Logger LOG =
+			Logger.getLogger(DashboardFragment.class.getName());
+
+	@Inject
+	private PluginManager pluginManager;
+
+	@InjectView(R.id.transportsView)
+	private GridView transportsView;
+
+	public static DashboardFragment newInstance() {
+
+		Bundle args = new Bundle();
+
+		DashboardFragment fragment = new DashboardFragment();
+		fragment.setArguments(args);
+		return fragment;
+	}
+
+	@Nullable
+	@Override
+	public View onCreateView(LayoutInflater inflater, ViewGroup container,
+			Bundle savedInstanceState) {
+		View contentView =
+				inflater.inflate(R.layout.fragment_dashboard, container, false);
+		return contentView;
+	}
+
+	@Override
+	public void onViewCreated(View view, Bundle savedInstanceState) {
+		super.onViewCreated(view, savedInstanceState);
+	}
+
+	@Override
+	public String getUniqueTag() {
+		return TAG;
+	}
+
+	@Override
+	public void eventOccurred(Event e) {
+
+	}
+}
diff --git a/briar-android/src/org/briarproject/android/SettingsActivity.java b/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java
similarity index 80%
rename from briar-android/src/org/briarproject/android/SettingsActivity.java
rename to briar-android/src/org/briarproject/android/fragment/SettingsFragment.java
index addccdc66bab944a325e198444a7cd07ebfb41bc..b3c5d946dad971797da44ad1c7dcbabc89a6369d 100644
--- a/briar-android/src/org/briarproject/android/SettingsActivity.java
+++ b/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.android.fragment;
 
 import android.bluetooth.BluetoothAdapter;
 import android.content.Intent;
@@ -7,8 +7,10 @@ import android.media.Ringtone;
 import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.LayoutInflater;
 import android.view.View;
-import android.view.View.OnClickListener;
+import android.view.ViewGroup;
 import android.widget.CheckBox;
 import android.widget.ImageButton;
 import android.widget.LinearLayout;
@@ -16,6 +18,7 @@ import android.widget.ScrollView;
 import android.widget.TextView;
 
 import org.briarproject.R;
+import org.briarproject.android.TestingActivity;
 import org.briarproject.android.panic.PanicPreferencesActivity;
 import org.briarproject.android.util.AndroidUtils;
 import org.briarproject.android.util.FixedVerticalSpace;
@@ -27,7 +30,6 @@ import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventBus;
-import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.SettingsUpdatedEvent;
 import org.briarproject.api.settings.SettingsManager;
 import org.briarproject.util.StringUtils;
@@ -53,16 +55,19 @@ import static android.widget.LinearLayout.VERTICAL;
 import static java.util.logging.Level.INFO;
 import static java.util.logging.Level.WARNING;
 import static org.briarproject.android.TestingConstants.SHOW_TESTING_ACTIVITY;
+import static android.app.Activity.RESULT_OK;
 import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP;
 import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1;
 
-public class SettingsActivity extends BriarActivity implements EventListener,
-OnClickListener {
+public class SettingsFragment extends BaseFragment implements
+		View.OnClickListener {
+
+	public final static String TAG = "SettingsFragment";
 
 	public static final int REQUEST_RINGTONE = 2;
 
 	private static final Logger LOG =
-			Logger.getLogger(SettingsActivity.class.getName());
+			Logger.getLogger(SettingsFragment.class.getName());
 
 	private ScrollView scroll = null;
 	private TextView enableBluetooth = null, enableBluetoothHint = null;
@@ -81,21 +86,36 @@ OnClickListener {
 	private volatile Settings settings;
 	private volatile boolean bluetoothSetting = true, torSetting = false;
 
+	public static SettingsFragment newInstance() {
+
+		Bundle args = new Bundle();
+
+		SettingsFragment fragment = new SettingsFragment();
+		fragment.setArguments(args);
+		return fragment;
+	}
+
 	@Override
-	public void onCreate(Bundle state) {
-		super.onCreate(state);
+	public String getUniqueTag() {
+		return TAG;
+	}
 
-		LinearLayout layout = new LinearLayout(this);
+	@Nullable
+	@Override
+	public View onCreateView(LayoutInflater inflater, ViewGroup container,
+			Bundle savedInstanceState) {
+
+		LinearLayout layout = new LinearLayout(getContext());
 		layout.setOrientation(VERTICAL);
 
-		scroll = new ScrollView(this);
+		scroll = new ScrollView(getContext());
 
-		LinearLayout settings = new LinearLayout(this);
+		LinearLayout settings = new LinearLayout(getContext());
 		settings.setOrientation(VERTICAL);
-		int pad = LayoutUtils.getPadding(this);
+		int pad = LayoutUtils.getPadding(getContext());
 		settings.setPadding(pad, pad, pad, pad);
 
-		TextView bluetoothTitle = new TextView(this);
+		TextView bluetoothTitle = new TextView(getContext());
 		bluetoothTitle.setPadding(pad, 0, pad, 0);
 		bluetoothTitle.setTypeface(DEFAULT_BOLD);
 		Resources res = getResources();
@@ -104,143 +124,143 @@ OnClickListener {
 		bluetoothTitle.setText(R.string.bluetooth_setting_title);
 		settings.addView(bluetoothTitle);
 
-		HorizontalBorder underline = new HorizontalBorder(this);
+		HorizontalBorder underline = new HorizontalBorder(getContext());
 		int titleUnderline = res.getColor(R.color.settings_title_underline);
 		underline.setBackgroundColor(titleUnderline);
 		settings.addView(underline);
 
-		enableBluetooth = new TextView(this);
+		enableBluetooth = new TextView(getContext());
 		enableBluetooth.setPadding(pad, pad, pad, 0);
 		enableBluetooth.setTextSize(18);
 		enableBluetooth.setText(R.string.bluetooth_setting);
 		enableBluetooth.setOnClickListener(this);
 		settings.addView(enableBluetooth);
 
-		enableBluetoothHint = new TextView(this);
+		enableBluetoothHint = new TextView(getContext());
 		enableBluetoothHint.setPadding(pad, 0, pad, pad);
 		enableBluetoothHint.setOnClickListener(this);
 		settings.addView(enableBluetoothHint);
 
-		TextView torTitle = new TextView(this);
+		TextView torTitle = new TextView(getContext());
 		torTitle.setPadding(pad, 0, pad, 0);
 		torTitle.setTypeface(DEFAULT_BOLD);
 		torTitle.setTextColor(titleText);
 		torTitle.setText(R.string.tor_wifi_setting_title);
 		settings.addView(torTitle);
 
-		underline = new HorizontalBorder(this);
+		underline = new HorizontalBorder(getContext());
 		underline.setBackgroundColor(titleUnderline);
 		settings.addView(underline);
 
-		torOverWifi = new TextView(this);
+		torOverWifi = new TextView(getContext());
 		torOverWifi.setPadding(pad, pad, pad, 0);
 		torOverWifi.setTextSize(18);
 		torOverWifi.setText(R.string.tor_wifi_setting);
 		torOverWifi.setOnClickListener(this);
 		settings.addView(torOverWifi);
 
-		torOverWifiHint = new TextView(this);
+		torOverWifiHint = new TextView(getContext());
 		torOverWifiHint.setPadding(pad, 0, pad, pad);
 		torOverWifiHint.setOnClickListener(this);
 		settings.addView(torOverWifiHint);
 
-		TextView panicTitle = new TextView(this);
+		TextView panicTitle = new TextView(getContext());
 		panicTitle.setPadding(pad, 0, pad, 0);
 		panicTitle.setTypeface(DEFAULT_BOLD);
 		panicTitle.setTextColor(titleText);
 		panicTitle.setText(R.string.panic_setting_title);
 		settings.addView(panicTitle);
 
-		underline = new HorizontalBorder(this);
+		underline = new HorizontalBorder(getContext());
 		underline.setBackgroundColor(titleUnderline);
 		settings.addView(underline);
 
-		panicSettings = new TextView(this);
+		panicSettings = new TextView(getContext());
 		panicSettings.setPadding(pad, pad, pad, 0);
 		panicSettings.setTextSize(18);
 		panicSettings.setText(R.string.panic_setting);
 		panicSettings.setOnClickListener(this);
 		settings.addView(panicSettings);
 
-		panicSettingsHint = new TextView(this);
+		panicSettingsHint = new TextView(getContext());
 		panicSettingsHint.setText(R.string.panic_setting_hint);
 		panicSettingsHint.setPadding(pad, 0, pad, pad);
 		panicSettingsHint.setOnClickListener(this);
 		settings.addView(panicSettingsHint);
 
-		TextView notificationsTitle = new TextView(this);
+		TextView notificationsTitle = new TextView(getContext());
 		notificationsTitle.setPadding(pad, 0, pad, 0);
 		notificationsTitle.setTypeface(DEFAULT_BOLD);
 		notificationsTitle.setTextColor(titleText);
 		notificationsTitle.setText(R.string.notification_settings_title);
 		settings.addView(notificationsTitle);
 
-		underline = new HorizontalBorder(this);
+		underline = new HorizontalBorder(getContext());
 		underline.setBackgroundColor(titleUnderline);
 		settings.addView(underline);
 
-		settings.addView(new FixedVerticalSpace(this));
+		settings.addView(new FixedVerticalSpace(getContext()));
 
-		notifyPrivateMessages = new CheckBox(this);
+		notifyPrivateMessages = new CheckBox(getContext());
 		notifyPrivateMessages.setTextSize(18);
 		notifyPrivateMessages.setText(R.string.notify_private_messages_setting);
 		notifyPrivateMessages.setOnClickListener(this);
 		settings.addView(notifyPrivateMessages);
 
-		settings.addView(new FixedVerticalSpace(this));
-		settings.addView(new HorizontalBorder(this));
-		settings.addView(new FixedVerticalSpace(this));
+		settings.addView(new FixedVerticalSpace(getContext()));
+		settings.addView(new HorizontalBorder(getContext()));
+		settings.addView(new FixedVerticalSpace(getContext()));
 
-		notifyForumPosts = new CheckBox(this);
+		notifyForumPosts = new CheckBox(getContext());
 		notifyForumPosts.setTextSize(18);
 		notifyForumPosts.setText(R.string.notify_forum_posts_setting);
 		notifyForumPosts.setOnClickListener(this);
 		settings.addView(notifyForumPosts);
 
-		settings.addView(new FixedVerticalSpace(this));
-		settings.addView(new HorizontalBorder(this));
-		settings.addView(new FixedVerticalSpace(this));
+		settings.addView(new FixedVerticalSpace(getContext()));
+		settings.addView(new HorizontalBorder(getContext()));
+		settings.addView(new FixedVerticalSpace(getContext()));
 
-		notifyVibration = new CheckBox(this);
+		notifyVibration = new CheckBox(getContext());
 		notifyVibration.setTextSize(18);
 		notifyVibration.setText(R.string.notify_vibration_setting);
 		notifyVibration.setOnClickListener(this);
 		settings.addView(notifyVibration);
 
-		settings.addView(new FixedVerticalSpace(this));
-		settings.addView(new HorizontalBorder(this));
+		settings.addView(new FixedVerticalSpace(getContext()));
+		settings.addView(new HorizontalBorder(getContext()));
 
-		notifySound = new TextView(this);
+		notifySound = new TextView(getContext());
 		notifySound.setPadding(pad, pad, pad, 0);
 		notifySound.setTextSize(18);
 		notifySound.setText(R.string.notify_sound_setting);
 		notifySound.setOnClickListener(this);
 		settings.addView(notifySound);
 
-		notifySoundHint = new TextView(this);
+		notifySoundHint = new TextView(getContext());
 		notifySoundHint.setPadding(pad, 0, pad, pad);
 		notifySoundHint.setOnClickListener(this);
 		settings.addView(notifySoundHint);
 
-		settings.addView(new HorizontalBorder(this));
+		settings.addView(new HorizontalBorder(getContext()));
 
 		scroll.addView(settings);
 		scroll.setLayoutParams(MATCH_WRAP_1);
 		scroll.setVisibility(GONE);
 		layout.addView(scroll);
 
-		progress = new ListLoadingProgressBar(this);
+		progress = new ListLoadingProgressBar(getContext());
 		layout.addView(progress);
 
-		layout.addView(new HorizontalBorder(this));
+		layout.addView(new HorizontalBorder(getContext()));
 
 		if (SHOW_TESTING_ACTIVITY) {
-			LinearLayout footer = new LinearLayout(this);
+			LinearLayout footer = new LinearLayout(getContext());
 			footer.setLayoutParams(MATCH_WRAP);
 			footer.setGravity(CENTER);
 			int background = res.getColor(R.color.button_bar_background);
 			footer.setBackgroundColor(background);
-			testingButton = new ImageButton(this);
+			testingButton = new ImageButton(getContext());
 			testingButton.setBackgroundResource(0);
 			testingButton.setImageResource(R.drawable.action_about);
 			testingButton.setOnClickListener(this);
@@ -248,18 +268,17 @@ OnClickListener {
 			layout.addView(footer);
 		}
 
-		setContentView(layout);
+		return layout;
 	}
 
 	@Override
 	public void onResume() {
 		super.onResume();
-		eventBus.addListener(this);
 		loadSettings();
 	}
 
 	private void loadSettings() {
-		runOnDbThread(new Runnable() {
+		listener.runOnDbThread(new Runnable() {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
@@ -281,13 +300,14 @@ OnClickListener {
 	}
 
 	private void displaySettings() {
-		runOnUiThread(new Runnable() {
+		listener.runOnUiThread(new Runnable() {
 			public void run() {
 				scroll.setVisibility(VISIBLE);
 				progress.setVisibility(GONE);
 
 				int resId;
-				if (bluetoothSetting) resId = R.string.bluetooth_setting_enabled;
+				if (bluetoothSetting)
+					resId = R.string.bluetooth_setting_enabled;
 				else resId = R.string.bluetooth_setting_disabled;
 				enableBluetoothHint.setText(resId);
 
@@ -318,16 +338,10 @@ OnClickListener {
 		});
 	}
 
-	@Override
-	public void onPause() {
-		super.onPause();
-		eventBus.removeListener(this);
-	}
-
 	public void onClick(View view) {
 		if (progress == null) return; // Not created yet
 		if (view == testingButton) {
-			startActivity(new Intent(this, TestingActivity.class));
+			startActivity(new Intent(getActivity(), TestingActivity.class));
 		} else if (view == enableBluetooth || view == enableBluetoothHint) {
 			bluetoothSetting = !bluetoothSetting;
 			BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -346,7 +360,7 @@ OnClickListener {
 					notifyPrivateMessages.isChecked());
 			storeSettings(s);
 		} else if (view == panicSettings || view == panicSettingsHint) {
-			startActivity(new Intent(this, PanicPreferencesActivity.class));
+			startActivity(new Intent(getActivity(), PanicPreferencesActivity.class));
 		} else if (view == notifyForumPosts) {
 			Settings s = new Settings();
 			s.putBoolean("notifyForumPosts", notifyForumPosts.isChecked());
@@ -375,7 +389,7 @@ OnClickListener {
 	}
 
 	private void storeTorSettings() {
-		runOnDbThread(new Runnable() {
+		listener.runOnDbThread(new Runnable() {
 			public void run() {
 				try {
 					Settings s = new Settings();
@@ -394,7 +408,7 @@ OnClickListener {
 	}
 
 	private void storeBluetoothSettings() {
-		runOnDbThread(new Runnable() {
+		listener.runOnDbThread(new Runnable() {
 			public void run() {
 				try {
 					Settings s = new Settings();
@@ -413,11 +427,12 @@ OnClickListener {
 	}
 
 	private void storeSettings(final Settings settings) {
-		runOnDbThread(new Runnable() {
+		listener.runOnDbThread(new Runnable() {
 			public void run() {
 				try {
 					long now = System.currentTimeMillis();
-					settingsManager.mergeSettings(settings, "settings-activity");
+					settingsManager
+							.mergeSettings(settings, "settings-activity");
 					long duration = System.currentTimeMillis() - now;
 					if (LOG.isLoggable(INFO))
 						LOG.info("Merging settings took " + duration + " ms");
@@ -449,8 +464,8 @@ OnClickListener {
 				s.put("notifyRingtoneUri", "");
 			} else {
 				// The user chose a ringtone other than the default
-				Ringtone r = RingtoneManager.getRingtone(this, uri);
-				String name = r.getTitle(this);
+				Ringtone r = RingtoneManager.getRingtone(getContext(), uri);
+				String name = r.getTitle(getContext());
 				notifySoundHint.setText(name);
 				s.putBoolean("notifySound", true);
 				s.put("notifyRingtoneName", name);
diff --git a/briar-android/src/org/briarproject/android/util/CustomAnimations.java b/briar-android/src/org/briarproject/android/util/CustomAnimations.java
new file mode 100644
index 0000000000000000000000000000000000000000..78987efe6de3addfa83f4acfa10fc0bf5e93bb77
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/util/CustomAnimations.java
@@ -0,0 +1,84 @@
+package org.briarproject.android.util;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+import android.annotation.SuppressLint;
+import android.os.Build;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class CustomAnimations {
+
+	public static void animateHeight(
+			final ViewGroup viewGroup, final boolean isExtending,
+			int duration) {
+		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+			animateHeightPostGingerbread(viewGroup, isExtending, duration);
+		} else {
+			animateHeightGingerbread(viewGroup, isExtending, duration);
+		}
+	}
+
+	private static void animateHeightGingerbread(final ViewGroup viewGroup,
+			final boolean isExtending, int duration) {
+		// No animations for Gingerbread
+		if (isExtending) {
+			viewGroup.setVisibility(View.VISIBLE);
+		} else {
+			viewGroup.setVisibility(View.GONE);
+		}
+	}
+
+
+	@SuppressLint("NewApi")
+	private static void animateHeightPostGingerbread(
+			final ViewGroup viewGroup,
+			final boolean isExtending,
+			int duration) {
+		ValueAnimator anim;
+		if (isExtending) {
+			viewGroup.setVisibility(View.VISIBLE);
+			viewGroup.measure(View.MeasureSpec.UNSPECIFIED,
+					View.MeasureSpec.UNSPECIFIED);
+			anim = ValueAnimator.ofInt(0, viewGroup.getMeasuredHeight());
+		} else {
+			anim = ValueAnimator.ofInt(viewGroup.getHeight(), 0);
+		}
+		anim.addListener(new Animator.AnimatorListener() {
+			@Override
+			public void onAnimationStart(Animator animation) {
+
+			}
+
+			@Override
+			public void onAnimationEnd(Animator animation) {
+				if (!isExtending) {
+					viewGroup.setVisibility(View.GONE);
+				}
+			}
+
+			@Override
+			public void onAnimationCancel(Animator animation) {
+
+			}
+
+			@Override
+			public void onAnimationRepeat(Animator animation) {
+
+			}
+		});
+		anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+			@Override
+			public void onAnimationUpdate(ValueAnimator valueAnimator) {
+				int val = (Integer) valueAnimator.getAnimatedValue();
+				ViewGroup.LayoutParams layoutParams =
+						viewGroup.getLayoutParams();
+				layoutParams.height = val;
+				viewGroup.setLayoutParams(layoutParams);
+			}
+
+		});
+		anim.setDuration(duration);
+		anim.start();
+	}
+}