diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index d1c7834abbc38b4955155c973d30184fbd5fb682..42c7979248d15ffbece6ea6d82cb05f79f8953b4 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -52,6 +52,10 @@
 		<item quantity="one">New private message.</item>
 		<item quantity="other">%d new private messages.</item>
 	</plurals>
+	<plurals name="group_message_notification_text">
+		<item quantity="one">New group message.</item>
+		<item quantity="other">%d new group messages.</item>
+	</plurals>
 	<plurals name="forum_post_notification_text">
 		<item quantity="one">New forum post.</item>
 		<item quantity="other">%d new forum posts.</item>
@@ -328,6 +332,7 @@
 	<!-- Settings Notifications -->
 	<string name="notification_settings_title">Notifications</string>
 	<string name="notify_private_messages_setting">Show alerts for private messages</string>
+	<string name="notify_group_messages_setting">Show alerts for group messages</string>
 	<string name="notify_forum_posts_setting">Show alerts for forum posts</string>
 	<string name="notify_blog_posts_setting">Show alerts for blog posts</string>
 	<string name="notify_vibration_setting">Vibrate</string>
diff --git a/briar-android/res/xml/settings.xml b/briar-android/res/xml/settings.xml
index 92048e8cf510d015465a48d5cd154ad9a4e74e34..32519425808d4c3947b1f18c955b23ea6d9c92e6 100644
--- a/briar-android/res/xml/settings.xml
+++ b/briar-android/res/xml/settings.xml
@@ -63,6 +63,12 @@
 			android:persistent="false"
 			android:title="@string/notify_private_messages_setting"/>
 
+		<CheckBoxPreference
+			android:defaultValue="true"
+			android:key="pref_key_notify_group_messages"
+			android:persistent="false"
+			android:title="@string/notify_group_messages_setting"/>
+
 		<CheckBoxPreference
 			android:defaultValue="true"
 			android:key="pref_key_notify_forum_posts"
diff --git a/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java b/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
index 973dc01307c1a0f64ee122fe64645df1f8fe967e..88ad43032d078e7f35ced8d48677d8faedfe55ad 100644
--- a/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
+++ b/briar-android/src/org/briarproject/android/AndroidNotificationManagerImpl.java
@@ -18,6 +18,7 @@ import org.briarproject.android.api.AndroidExecutor;
 import org.briarproject.android.api.AndroidNotificationManager;
 import org.briarproject.android.contact.ConversationActivity;
 import org.briarproject.android.forum.ForumActivity;
+import org.briarproject.android.privategroup.conversation.GroupActivity;
 import org.briarproject.api.contact.ContactId;
 import org.briarproject.api.db.DatabaseExecutor;
 import org.briarproject.api.db.DbException;
@@ -25,6 +26,7 @@ import org.briarproject.api.event.BlogPostAddedEvent;
 import org.briarproject.api.event.Event;
 import org.briarproject.api.event.EventListener;
 import org.briarproject.api.event.ForumPostReceivedEvent;
+import org.briarproject.api.event.GroupMessageAddedEvent;
 import org.briarproject.api.event.IntroductionRequestReceivedEvent;
 import org.briarproject.api.event.IntroductionResponseReceivedEvent;
 import org.briarproject.api.event.IntroductionSucceededEvent;
@@ -64,8 +66,10 @@ import static org.briarproject.android.BriarActivity.GROUP_ID;
 import static org.briarproject.android.NavDrawerActivity.INTENT_BLOGS;
 import static org.briarproject.android.NavDrawerActivity.INTENT_CONTACTS;
 import static org.briarproject.android.NavDrawerActivity.INTENT_FORUMS;
+import static org.briarproject.android.NavDrawerActivity.INTENT_GROUPS;
 import static org.briarproject.android.contact.ConversationActivity.CONTACT_ID;
 import static org.briarproject.android.fragment.SettingsFragment.PREF_NOTIFY_BLOG;
+import static org.briarproject.android.fragment.SettingsFragment.PREF_NOTIFY_GROUP;
 import static org.briarproject.android.fragment.SettingsFragment.SETTINGS_NAMESPACE;
 
 class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@@ -73,13 +77,16 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 
 	// Notification IDs
 	private static final int PRIVATE_MESSAGE_NOTIFICATION_ID = 3;
-	private static final int FORUM_POST_NOTIFICATION_ID = 4;
-	private static final int BLOG_POST_NOTIFICATION_ID = 5;
-	private static final int INTRODUCTION_SUCCESS_NOTIFICATION_ID = 6;
+	private static final int GROUP_MESSAGE_NOTIFICATION_ID = 4;
+	private static final int FORUM_POST_NOTIFICATION_ID = 5;
+	private static final int BLOG_POST_NOTIFICATION_ID = 6;
+	private static final int INTRODUCTION_SUCCESS_NOTIFICATION_ID = 7;
 
 	// Content URIs to differentiate between pending intents
 	private static final String CONTACT_URI =
 			"content://org.briarproject/contact";
+	private static final String GROUP_URI =
+			"content://org.briarproject/group";
 	private static final String FORUM_URI =
 			"content://org.briarproject/forum";
 	private static final String BLOG_URI =
@@ -88,6 +95,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 	// Actions for intents that are broadcast when notifications are dismissed
 	private static final String CLEAR_PRIVATE_MESSAGE_ACTION =
 			"org.briarproject.briar.CLEAR_PRIVATE_MESSAGE_NOTIFICATION";
+	private static final String CLEAR_GROUP_ACTION =
+			"org.briarproject.briar.CLEAR_GROUP_NOTIFICATION";
 	private static final String CLEAR_FORUM_ACTION =
 			"org.briarproject.briar.CLEAR_FORUM_NOTIFICATION";
 	private static final String CLEAR_BLOG_ACTION =
@@ -107,15 +116,17 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 
 	// The following must only be accessed on the main UI thread
 	private final Map<ContactId, Integer> contactCounts = new HashMap<>();
+	private final Map<GroupId, Integer> groupCounts = new HashMap<>();
 	private final Map<GroupId, Integer> forumCounts = new HashMap<>();
 	private final Map<GroupId, Integer> blogCounts = new HashMap<>();
-	private int contactTotal = 0, forumTotal = 0, blogTotal = 0;
+	private int contactTotal = 0, groupTotal = 0, forumTotal = 0, blogTotal = 0;
 	private int introductionTotal = 0;
 	private int nextRequestId = 0;
 	private ContactId blockedContact = null;
 	private GroupId blockedGroup = null;
-	private boolean blockContacts = false, blockForums = false;
-	private boolean blockBlogs = false, blockIntroductions = false;
+	private boolean blockContacts = false, blockGroups = false;
+	private boolean blockForums = false, blockBlogs = false;
+	private boolean blockIntroductions = false;
 
 	private volatile Settings settings = new Settings();
 
@@ -144,6 +155,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 			public Void call() {
 				IntentFilter filter = new IntentFilter();
 				filter.addAction(CLEAR_PRIVATE_MESSAGE_ACTION);
+				filter.addAction(CLEAR_GROUP_ACTION);
 				filter.addAction(CLEAR_FORUM_ACTION);
 				filter.addAction(CLEAR_BLOG_ACTION);
 				filter.addAction(CLEAR_INTRODUCTION_ACTION);
@@ -165,6 +177,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 			@Override
 			public Void call() {
 				clearContactNotification();
+				clearGroupMessageNotification();
 				clearForumPostNotification();
 				clearBlogPostNotification();
 				clearIntroductionSuccessNotification();
@@ -188,6 +201,15 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		nm.cancel(PRIVATE_MESSAGE_NOTIFICATION_ID);
 	}
 
+	@UiThread
+	private void clearGroupMessageNotification() {
+		groupCounts.clear();
+		groupTotal = 0;
+		Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
+		NotificationManager nm = (NotificationManager) o;
+		nm.cancel(GROUP_MESSAGE_NOTIFICATION_ID);
+	}
+
 	@UiThread
 	private void clearForumPostNotification() {
 		forumCounts.clear();
@@ -222,6 +244,9 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		} else if (e instanceof PrivateMessageReceivedEvent) {
 			PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e;
 			showContactNotification(p.getContactId());
+		} else if (e instanceof GroupMessageAddedEvent) {
+			GroupMessageAddedEvent g = (GroupMessageAddedEvent) e;
+			showGroupMessageNotification(g.getGroupId());
 		} else if (e instanceof ForumPostReceivedEvent) {
 			ForumPostReceivedEvent f = (ForumPostReceivedEvent) e;
 			showForumPostNotification(f.getGroupId());
@@ -367,6 +392,101 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		});
 	}
 
+	@UiThread
+	private void showGroupMessageNotification(final GroupId g) {
+		androidExecutor.runOnUiThread(new Runnable() {
+			@Override
+			public void run() {
+				if (blockGroups) return;
+				if (g.equals(blockedGroup)) return;
+				Integer count = groupCounts.get(g);
+				if (count == null) groupCounts.put(g, 1);
+				else groupCounts.put(g, count + 1);
+				groupTotal++;
+				updateGroupMessageNotification();
+			}
+		});
+	}
+
+	@Override
+	public void clearGroupMessageNotification(final GroupId g) {
+		androidExecutor.runOnUiThread(new Runnable() {
+			@Override
+			public void run() {
+				Integer count = groupCounts.remove(g);
+				if (count == null) return; // Already cleared
+				groupTotal -= count;
+				updateGroupMessageNotification();
+			}
+		});
+	}
+
+	@UiThread
+	private void updateGroupMessageNotification() {
+		if (groupTotal == 0) {
+			clearGroupMessageNotification();
+		} else if (settings.getBoolean(PREF_NOTIFY_GROUP, true)) {
+			NotificationCompat.Builder b =
+					new NotificationCompat.Builder(appContext);
+			b.setSmallIcon(R.drawable.message_notification_icon);
+			b.setContentTitle(appContext.getText(R.string.app_name));
+			b.setContentText(appContext.getResources().getQuantityString(
+					R.plurals.group_message_notification_text, groupTotal,
+					groupTotal));
+			String ringtoneUri = settings.get("notifyRingtoneUri");
+			if (!StringUtils.isNullOrEmpty(ringtoneUri))
+				b.setSound(Uri.parse(ringtoneUri));
+			b.setDefaults(getDefaults());
+			b.setOnlyAlertOnce(true);
+			b.setAutoCancel(true);
+			// Clear the counters if the notification is dismissed
+			Intent clear = new Intent(CLEAR_GROUP_ACTION);
+			PendingIntent delete = PendingIntent.getBroadcast(appContext, 0,
+					clear, 0);
+			b.setDeleteIntent(delete);
+			if (groupCounts.size() == 1) {
+				// Touching the notification shows the relevant group
+				Intent i = new Intent(appContext, GroupActivity.class);
+				GroupId g = groupCounts.keySet().iterator().next();
+				i.putExtra(GROUP_ID, g.getBytes());
+				String idHex = StringUtils.toHexString(g.getBytes());
+				i.setData(Uri.parse(GROUP_URI + "/" + idHex));
+				i.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
+				TaskStackBuilder t = TaskStackBuilder.create(appContext);
+				t.addParentStack(GroupActivity.class);
+				t.addNextIntent(i);
+				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
+			} else {
+				// Touching the notification shows the group list
+				Intent i = new Intent(appContext, NavDrawerActivity.class);
+				i.putExtra(INTENT_GROUPS, true);
+				i.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_SINGLE_TOP);
+				i.setData(Uri.parse(GROUP_URI));
+				TaskStackBuilder t = TaskStackBuilder.create(appContext);
+				t.addParentStack(NavDrawerActivity.class);
+				t.addNextIntent(i);
+				b.setContentIntent(t.getPendingIntent(nextRequestId++, 0));
+			}
+			if (Build.VERSION.SDK_INT >= 21) {
+				b.setCategory(CATEGORY_SOCIAL);
+				b.setVisibility(VISIBILITY_SECRET);
+			}
+			Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
+			NotificationManager nm = (NotificationManager) o;
+			nm.notify(GROUP_MESSAGE_NOTIFICATION_ID, b.build());
+		}
+	}
+
+	@Override
+	public void clearAllGroupMessageNotifications() {
+		androidExecutor.runOnUiThread(new Runnable() {
+			@Override
+			public void run() {
+				clearGroupMessageNotification();
+			}
+		});
+	}
+
 	@UiThread
 	private void showForumPostNotification(final GroupId g) {
 		androidExecutor.runOnUiThread(new Runnable() {
@@ -654,6 +774,26 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 		});
 	}
 
+	@Override
+	public void blockAllGroupMessageNotifications() {
+		androidExecutor.runOnUiThread(new Runnable() {
+			@Override
+			public void run() {
+				blockGroups = true;
+			}
+		});
+	}
+
+	@Override
+	public void unblockAllGroupMessageNotifications() {
+		androidExecutor.runOnUiThread(new Runnable() {
+			@Override
+			public void run() {
+				blockGroups = false;
+			}
+		});
+	}
+
 	@Override
 	public void blockAllForumPostNotifications() {
 		androidExecutor.runOnUiThread(new Runnable() {
@@ -704,6 +844,8 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
 				public void run() {
 					if (CLEAR_PRIVATE_MESSAGE_ACTION.equals(action)) {
 						clearContactNotification();
+					} else if (CLEAR_GROUP_ACTION.equals(action)) {
+						clearGroupMessageNotification();
 					} else if (CLEAR_FORUM_ACTION.equals(action)) {
 						clearForumPostNotification();
 					} else if (CLEAR_BLOG_ACTION.equals(action)) {
diff --git a/briar-android/src/org/briarproject/android/NavDrawerActivity.java b/briar-android/src/org/briarproject/android/NavDrawerActivity.java
index 16b3700cdaded5fa6e3e66781ca5b03554614eb2..cc2fbbcbfbfec5a7602137308b052a6966591843 100644
--- a/briar-android/src/org/briarproject/android/NavDrawerActivity.java
+++ b/briar-android/src/org/briarproject/android/NavDrawerActivity.java
@@ -46,6 +46,7 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
 		OnNavigationItemSelectedListener {
 
 	static final String INTENT_CONTACTS = "intent_contacts";
+	static final String INTENT_GROUPS = "intent_groups";
 	static final String INTENT_FORUMS = "intent_forums";
 	static final String INTENT_BLOGS = "intent_blogs";
 
@@ -70,10 +71,10 @@ public class NavDrawerActivity extends BriarFragmentActivity implements
 	protected void onNewIntent(Intent intent) {
 		super.onNewIntent(intent);
 		exitIfStartupFailed(intent);
-		// FIXME why was the stack cleared here?
-		// This prevents state from being restored properly
-//		clearBackStack();
-		if (intent.getBooleanExtra(INTENT_FORUMS, false)) {
+		// TODO don't create new instances if they are on the stack (#606)
+		if (intent.getBooleanExtra(INTENT_GROUPS, false)) {
+			startFragment(GroupListFragment.newInstance());
+		} else if (intent.getBooleanExtra(INTENT_FORUMS, false)) {
 			startFragment(ForumListFragment.newInstance());
 		} else if (intent.getBooleanExtra(INTENT_CONTACTS, false)) {
 			startFragment(ContactListFragment.newInstance());
diff --git a/briar-android/src/org/briarproject/android/api/AndroidNotificationManager.java b/briar-android/src/org/briarproject/android/api/AndroidNotificationManager.java
index 1140ff5730dab87122eeae36fac7469347da51da..6a199a0feb5c13c5620b62ecdd702bb9c7b6338f 100644
--- a/briar-android/src/org/briarproject/android/api/AndroidNotificationManager.java
+++ b/briar-android/src/org/briarproject/android/api/AndroidNotificationManager.java
@@ -13,6 +13,10 @@ public interface AndroidNotificationManager {
 
 	void clearAllContactNotifications();
 
+	void clearGroupMessageNotification(GroupId g);
+
+	void clearAllGroupMessageNotifications();
+
 	void clearForumPostNotification(GroupId g);
 
 	void clearAllForumPostNotifications();
@@ -33,6 +37,10 @@ public interface AndroidNotificationManager {
 
 	void unblockAllContactNotifications();
 
+	void blockAllGroupMessageNotifications();
+
+	void unblockAllGroupMessageNotifications();
+
 	void blockAllForumPostNotifications();
 
 	void unblockAllForumPostNotifications();
diff --git a/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java b/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java
index a3d6551267d1cd6fca14e571e2ebeea12236c011..60fab261fa399c11d9893fd0a197bba367a958d3 100644
--- a/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java
+++ b/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java
@@ -50,6 +50,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
 
 	private static final int REQUEST_RINGTONE = 2;
 	public static final String SETTINGS_NAMESPACE = "android-ui";
+	public static final String PREF_NOTIFY_GROUP = "notifyGroupMessages";
 	public static final String PREF_NOTIFY_BLOG = "notifyBlogPosts";
 
 	private static final Logger LOG =
@@ -60,6 +61,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
 	private ListPreference enableBluetooth;
 	private ListPreference torOverMobile;
 	private CheckBoxPreference notifyPrivateMessages;
+	private CheckBoxPreference notifyGroupMessages;
 	private CheckBoxPreference notifyForumPosts;
 	private CheckBoxPreference notifyBlogPosts;
 	private CheckBoxPreference notifyVibration;
@@ -91,6 +93,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
 				(ListPreference) findPreference("pref_key_tor_mobile");
 		notifyPrivateMessages = (CheckBoxPreference) findPreference(
 				"pref_key_notify_private_messages");
+		notifyGroupMessages = (CheckBoxPreference) findPreference(
+				"pref_key_notify_group_messages");
 		notifyForumPosts = (CheckBoxPreference) findPreference(
 				"pref_key_notify_forum_posts");
 		notifyBlogPosts = (CheckBoxPreference) findPreference(
@@ -102,6 +106,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
 		enableBluetooth.setOnPreferenceChangeListener(this);
 		torOverMobile.setOnPreferenceChangeListener(this);
 		notifyPrivateMessages.setOnPreferenceChangeListener(this);
+		notifyGroupMessages.setOnPreferenceChangeListener(this);
 		notifyForumPosts.setOnPreferenceChangeListener(this);
 		notifyBlogPosts.setOnPreferenceChangeListener(this);
 		notifyVibration.setOnPreferenceChangeListener(this);
@@ -199,6 +204,9 @@ public class SettingsFragment extends PreferenceFragmentCompat
 				notifyPrivateMessages.setChecked(settings.getBoolean(
 						"notifyPrivateMessages", true));
 
+				notifyGroupMessages.setChecked(settings.getBoolean(
+						PREF_NOTIFY_GROUP, true));
+
 				notifyForumPosts.setChecked(settings.getBoolean(
 						"notifyForumPosts", true));
 
@@ -247,6 +255,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
 			Settings s = new Settings();
 			s.putBoolean("notifyPrivateMessages", (Boolean) o);
 			storeSettings(s);
+		} else if (preference == notifyGroupMessages) {
+			Settings s = new Settings();
+			s.putBoolean(PREF_NOTIFY_GROUP, (Boolean) o);
+			storeSettings(s);
 		} else if (preference == notifyForumPosts) {
 			Settings s = new Settings();
 			s.putBoolean("notifyForumPosts", (Boolean) o);
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java
index 34ce9768f93d5f87067fb030e6b3f0a8bb830475..8146f200aaaa99b8eb2a94229940c23523fe4557 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupControllerImpl.java
@@ -59,7 +59,7 @@ public class GroupControllerImpl extends
 	@Override
 	public void onActivityStart() {
 		super.onActivityStart();
-		// TODO: Add new notification manager methods for private groups
+		notificationManager.clearGroupMessageNotification(getGroupId());
 	}
 
 	@Override
diff --git a/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java b/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java
index 8be76289fe1ad638388d4526f2286a2a8f40165c..4524e484b399b3cbcdcb91a2edd0f38d508615b6 100644
--- a/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java
+++ b/briar-android/src/org/briarproject/android/privategroup/list/GroupListControllerImpl.java
@@ -2,6 +2,7 @@ package org.briarproject.android.privategroup.list;
 
 import android.support.annotation.CallSuper;
 
+import org.briarproject.android.api.AndroidNotificationManager;
 import org.briarproject.android.controller.DbControllerImpl;
 import org.briarproject.android.controller.handler.ResultExceptionHandler;
 import org.briarproject.api.clients.MessageTracker.GroupCount;
@@ -41,6 +42,7 @@ public class GroupListControllerImpl extends DbControllerImpl
 
 	private final PrivateGroupManager groupManager;
 	private final GroupInvitationManager groupInvitationManager;
+	private final AndroidNotificationManager notificationManager;
 	private final EventBus eventBus;
 
 	protected volatile GroupListListener listener;
@@ -48,10 +50,12 @@ public class GroupListControllerImpl extends DbControllerImpl
 	@Inject
 	GroupListControllerImpl(@DatabaseExecutor Executor dbExecutor,
 			LifecycleManager lifecycleManager, PrivateGroupManager groupManager,
-			GroupInvitationManager groupInvitationManager, EventBus eventBus) {
+			GroupInvitationManager groupInvitationManager,
+			AndroidNotificationManager notificationManager, EventBus eventBus) {
 		super(dbExecutor, lifecycleManager);
 		this.groupManager = groupManager;
 		this.groupInvitationManager = groupInvitationManager;
+		this.notificationManager = notificationManager;
 		this.eventBus = eventBus;
 	}
 
@@ -67,13 +71,15 @@ public class GroupListControllerImpl extends DbControllerImpl
 			throw new IllegalStateException(
 					"GroupListListener needs to be attached");
 		eventBus.addListener(this);
-		// TODO: Add new notification manager methods for private groups
+		notificationManager.blockAllGroupMessageNotifications();
+		notificationManager.clearAllGroupMessageNotifications();
 	}
 
 	@Override
 	@CallSuper
 	public void onStop() {
 		eventBus.removeListener(this);
+		notificationManager.unblockAllGroupMessageNotifications();
 	}
 
 	@Override