diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml
index 99ad3cfada95848bac44c53f9f195fdc71032623..774f1c7f966d7bdb6bb90307e4e8f17e1fa452ca 100644
--- a/briar-android/AndroidManifest.xml
+++ b/briar-android/AndroidManifest.xml
@@ -142,6 +142,17 @@
 				/>
 		</activity>
 
+		<activity
+			android:name=".android.privategroup.creation.GroupInviteActivity"
+			android:label="@string/groups_invite_members"
+			android:parentActivityName=".android.NavDrawerActivity"
+			android:windowSoftInputMode="adjustResize|stateHidden">
+			<meta-data
+				android:name="android.support.PARENT_ACTIVITY"
+				android:value=".android.privategroup.conversation.GroupActivity"
+				/>
+		</activity>
+
 		<activity
 			android:name=".android.sharing.ForumInvitationActivity"
 			android:label="@string/forum_invitations_title"
diff --git a/briar-android/res/menu/group_actions.xml b/briar-android/res/menu/group_actions.xml
index d7901bdfa01f01fa4a172bbfe71af68006350664..0c1fd68fa75fb566dca4e7126b9137e16443c298 100644
--- a/briar-android/res/menu/group_actions.xml
+++ b/briar-android/res/menu/group_actions.xml
@@ -17,7 +17,6 @@
 
 	<item
 		android:id="@+id/action_group_invite"
-		android:enabled="false"
 		android:icon="@drawable/ic_add_white"
 		android:title="@string/groups_invite_members"
 		app:showAsAction="ifRoom"/>
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 6acd446ffbb73ef2b934f543b9394a7bfd6462a4..73046ee630fb995bd0a89a99a84abdee0301a15b 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -157,6 +157,7 @@
 	<string name="groups_create_group_button">Create Group</string>
 	<string name="groups_create_group_invitation_button">Send Invitation</string>
 	<string name="groups_create_group_hint">Add a name for your private group</string>
+	<string name="groups_invitation_sent">Group invitation has been sent</string>
 	<string name="groups_compose_message">Compose Message</string>
 	<string name="groups_message_sent">Message sent</string>
 	<string name="groups_message_received">Message received</string>
diff --git a/briar-android/src/org/briarproject/android/ActivityComponent.java b/briar-android/src/org/briarproject/android/ActivityComponent.java
index d2902428d660773b153a557f07cb303113046d0b..ee1ee02d592f8b47987b4d04e50202530dde7d27 100644
--- a/briar-android/src/org/briarproject/android/ActivityComponent.java
+++ b/briar-android/src/org/briarproject/android/ActivityComponent.java
@@ -32,6 +32,7 @@ import org.briarproject.android.privategroup.conversation.GroupActivity;
 import org.briarproject.android.privategroup.creation.CreateGroupActivity;
 import org.briarproject.android.privategroup.creation.CreateGroupFragment;
 import org.briarproject.android.privategroup.creation.CreateGroupMessageFragment;
+import org.briarproject.android.privategroup.creation.GroupInviteActivity;
 import org.briarproject.android.privategroup.invitation.GroupInvitationActivity;
 import org.briarproject.android.privategroup.list.GroupListFragment;
 import org.briarproject.android.privategroup.memberlist.GroupMemberListActivity;
@@ -80,6 +81,7 @@ public interface ActivityComponent {
 
 	void inject(CreateGroupActivity activity);
 	void inject(GroupActivity activity);
+	void inject(GroupInviteActivity activity);
 	void inject(GroupInvitationActivity activity);
 	void inject(GroupMemberListActivity activity);
 
diff --git a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
index a6a8066047e6696cc355b62682b05a447751593a..1dad3b51a36d7fd1b3426997bb270a63b5cc40e3 100644
--- a/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
+++ b/briar-android/src/org/briarproject/android/privategroup/conversation/GroupActivity.java
@@ -19,6 +19,7 @@ import org.briarproject.R;
 import org.briarproject.android.ActivityComponent;
 import org.briarproject.android.controller.handler.UiResultExceptionHandler;
 import org.briarproject.android.privategroup.memberlist.GroupMemberListActivity;
+import org.briarproject.android.privategroup.creation.GroupInviteActivity;
 import org.briarproject.android.threaded.ThreadListActivity;
 import org.briarproject.android.threaded.ThreadListController;
 import org.briarproject.api.db.DbException;
@@ -34,6 +35,8 @@ public class GroupActivity extends
 		ThreadListActivity<PrivateGroup, GroupMessageItem, GroupMessageHeader>
 		implements OnClickListener {
 
+	private final static int REQUEST_INVITE = 1;
+
 	@Inject
 	GroupController controller;
 
@@ -133,17 +136,23 @@ public class GroupActivity extends
 
 	@Override
 	public boolean onOptionsItemSelected(final MenuItem item) {
+		ActivityOptionsCompat options =
+				makeCustomAnimation(this, android.R.anim.slide_in_left,
+						android.R.anim.slide_out_right);
 		switch (item.getItemId()) {
 			case R.id.action_group_compose_message:
 				showTextInput(null);
 				return true;
 			case R.id.action_group_member_list:
-				Intent i = new Intent(this, GroupMemberListActivity.class);
-				i.putExtra(GROUP_ID, groupId.getBytes());
-				ActivityOptionsCompat options =
-						makeCustomAnimation(this, android.R.anim.slide_in_left,
-								android.R.anim.slide_out_right);
-				ActivityCompat.startActivity(this, i, options.toBundle());
+				Intent i1 = new Intent(this, GroupMemberListActivity.class);
+				i1.putExtra(GROUP_ID, groupId.getBytes());
+				ActivityCompat.startActivity(this, i1, options.toBundle());
+				return true;
+			case R.id.action_group_invite:
+				Intent i2 = new Intent(this, GroupInviteActivity.class);
+				i2.putExtra(GROUP_ID, groupId.getBytes());
+				ActivityCompat.startActivityForResult(this, i2, REQUEST_INVITE,
+						options.toBundle());
 				return true;
 			case R.id.action_group_leave:
 				showLeaveGroupDialog();
@@ -155,6 +164,13 @@ public class GroupActivity extends
 		}
 	}
 
+	@Override
+	protected void onActivityResult(int request, int result, Intent data) {
+		if (request == REQUEST_INVITE && result == RESULT_OK) {
+			displaySnackbarShort(R.string.groups_invitation_sent);
+		} else super.onActivityResult(request, result, data);
+	}
+
 	@Override
 	protected int getMaxBodyLength() {
 		return MAX_GROUP_POST_BODY_LENGTH;
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/BaseGroupInviteActivity.java b/briar-android/src/org/briarproject/android/privategroup/creation/BaseGroupInviteActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d29ce89d968c65f879fee2703381ac70fc1bdcd
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/privategroup/creation/BaseGroupInviteActivity.java
@@ -0,0 +1,95 @@
+package org.briarproject.android.privategroup.creation;
+
+import android.os.Bundle;
+import android.widget.Toast;
+
+import org.briarproject.R;
+import org.briarproject.android.controller.handler.UiResultExceptionHandler;
+import org.briarproject.android.sharing.BaseMessageFragment.MessageFragmentListener;
+import org.briarproject.android.sharing.ContactSelectorActivity;
+import org.briarproject.api.contact.Contact;
+import org.briarproject.api.contact.ContactId;
+import org.briarproject.api.db.DatabaseExecutor;
+import org.briarproject.api.db.DbException;
+import org.briarproject.api.sync.GroupId;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+import javax.inject.Inject;
+
+import static android.widget.Toast.LENGTH_SHORT;
+import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
+
+public abstract class BaseGroupInviteActivity
+		extends ContactSelectorActivity
+		implements MessageFragmentListener {
+
+	@Inject
+	CreateGroupController controller;
+
+	@Override
+	public void onCreate(Bundle bundle) {
+		super.onCreate(bundle);
+
+		// Subclasses may initialise the group ID in different places,
+		// restore it if it was saved
+		if (bundle != null) {
+			byte[] groupBytes = bundle.getByteArray(GROUP_ID);
+			if (groupBytes != null) groupId = new GroupId(groupBytes);
+		}
+	}
+
+	@Override
+	public void onSaveInstanceState(Bundle outState) {
+		super.onSaveInstanceState(outState);
+		if (groupId != null) {
+			outState.putByteArray(GROUP_ID, groupId.getBytes());
+		}
+	}
+
+	@Override
+	public void contactsSelected(GroupId groupId,
+			Collection<ContactId> contacts) {
+		super.contactsSelected(groupId, contacts);
+
+		CreateGroupMessageFragment fragment = new CreateGroupMessageFragment();
+		getSupportFragmentManager().beginTransaction()
+				.setCustomAnimations(android.R.anim.fade_in,
+						android.R.anim.fade_out,
+						android.R.anim.slide_in_left,
+						android.R.anim.slide_out_right)
+				.replace(R.id.fragmentContainer, fragment)
+				.addToBackStack(fragment.getUniqueTag())
+				.commit();
+	}
+
+	@Override
+	public boolean onButtonClick(@NotNull String message) {
+		controller.sendInvitation(groupId, contacts, message,
+				new UiResultExceptionHandler<Void, DbException>(this) {
+					@Override
+					public void onResultUi(Void result) {
+						Toast.makeText(BaseGroupInviteActivity.this,
+								"Inviting members is not yet implemented",
+								LENGTH_SHORT).show();
+						setResult(RESULT_OK);
+						supportFinishAfterTransition();
+					}
+
+					@Override
+					public void onExceptionUi(DbException exception) {
+						// TODO proper error handling
+						setResult(RESULT_CANCELED);
+						finish();
+					}
+				});
+		return true;
+	}
+
+	@Override
+	public int getMaximumMessageLength() {
+		return MAX_GROUP_INVITATION_MSG_LENGTH;
+	}
+
+}
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupActivity.java b/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupActivity.java
index d92759820b98a92c86404f8b8ca7f1de6103619a..a82b4cc1deeacd409f0c28c1c1e2552d75cf5ace 100644
--- a/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupActivity.java
+++ b/briar-android/src/org/briarproject/android/privategroup/creation/CreateGroupActivity.java
@@ -4,35 +4,23 @@ import android.content.Intent;
 import android.os.Bundle;
 import android.support.v4.app.ActivityCompat;
 import android.support.v4.app.ActivityOptionsCompat;
-import android.widget.Toast;
 
 import org.briarproject.R;
 import org.briarproject.android.ActivityComponent;
 import org.briarproject.android.controller.handler.UiResultExceptionHandler;
 import org.briarproject.android.privategroup.conversation.GroupActivity;
 import org.briarproject.android.sharing.BaseMessageFragment.MessageFragmentListener;
-import org.briarproject.android.sharing.ContactSelectorActivity;
 import org.briarproject.android.sharing.ContactSelectorFragment;
 import org.briarproject.api.contact.Contact;
-import org.briarproject.api.contact.ContactId;
+import org.briarproject.api.db.DatabaseExecutor;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.sync.GroupId;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collection;
-
-import javax.inject.Inject;
 
 import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
-import static android.widget.Toast.LENGTH_SHORT;
-import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
 
-public class CreateGroupActivity extends ContactSelectorActivity implements
+public class CreateGroupActivity extends BaseGroupInviteActivity implements
 		CreateGroupListener, MessageFragmentListener {
 
-	@Inject
-	CreateGroupController controller;
-
 	@Override
 	public void injectActivity(ActivityComponent component) {
 		component.inject(this);
@@ -42,19 +30,21 @@ public class CreateGroupActivity extends ContactSelectorActivity implements
 	public void onCreate(Bundle bundle) {
 		super.onCreate(bundle);
 
-		setContentView(R.layout.activity_fragment_container);
-
 		if (bundle == null) {
 			CreateGroupFragment fragment = new CreateGroupFragment();
 			getSupportFragmentManager().beginTransaction()
 					.add(R.id.fragmentContainer, fragment)
 					.commit();
-		} else {
-			byte[] groupBytes = bundle.getByteArray(GROUP_ID);
-			if (groupBytes != null) groupId = new GroupId(groupBytes);
 		}
 	}
 
+	@Override
+	@DatabaseExecutor
+	public boolean isDisabled(GroupId groupId, Contact c) throws DbException {
+		// contacts can always be invited into a new group
+		return false;
+	}
+
 	@Override
 	public void onBackPressed() {
 		if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
@@ -66,14 +56,6 @@ public class CreateGroupActivity extends ContactSelectorActivity implements
 		}
 	}
 
-	@Override
-	public void onSaveInstanceState(Bundle outState) {
-		super.onSaveInstanceState(outState);
-		if (groupId != null) {
-			outState.putByteArray(GROUP_ID, groupId.getBytes());
-		}
-	}
-
 	@Override
 	public void onGroupNameChosen(String name) {
 		controller.createGroup(name,
@@ -106,53 +88,6 @@ public class CreateGroupActivity extends ContactSelectorActivity implements
 				.commit();
 	}
 
-	@Override
-	public boolean isDisabled(GroupId groupId, Contact c) throws DbException {
-		return false;
-	}
-
-	@Override
-	public void contactsSelected(GroupId groupId,
-			Collection<ContactId> contacts) {
-		super.contactsSelected(groupId, contacts);
-
-		CreateGroupMessageFragment fragment = new CreateGroupMessageFragment();
-		getSupportFragmentManager().beginTransaction()
-				.setCustomAnimations(android.R.anim.fade_in,
-						android.R.anim.fade_out,
-						android.R.anim.slide_in_left,
-						android.R.anim.slide_out_right)
-				.replace(R.id.fragmentContainer, fragment)
-				.addToBackStack(fragment.getUniqueTag())
-				.commit();
-	}
-
-	@Override
-	public boolean onButtonClick(@NotNull String message) {
-		controller.sendInvitation(groupId, contacts, message,
-				new UiResultExceptionHandler<Void, DbException>(this) {
-					@Override
-					public void onResultUi(Void result) {
-						Toast.makeText(CreateGroupActivity.this,
-								"Inviting members is not yet implemented",
-								LENGTH_SHORT).show();
-						openNewGroup();
-					}
-
-					@Override
-					public void onExceptionUi(DbException exception) {
-						// TODO proper error handling
-						finish();
-					}
-				});
-		return true;
-	}
-
-	@Override
-	public int getMaximumMessageLength() {
-		return MAX_GROUP_INVITATION_MSG_LENGTH;
-	}
-
 	private void openNewGroup() {
 		Intent i = new Intent(this, GroupActivity.class);
 		i.putExtra(GROUP_ID, groupId.getBytes());
diff --git a/briar-android/src/org/briarproject/android/privategroup/creation/GroupInviteActivity.java b/briar-android/src/org/briarproject/android/privategroup/creation/GroupInviteActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..7872c34cb72acc5abe01615d2f5d234ae7a85da6
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/privategroup/creation/GroupInviteActivity.java
@@ -0,0 +1,50 @@
+package org.briarproject.android.privategroup.creation;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+import org.briarproject.R;
+import org.briarproject.android.ActivityComponent;
+import org.briarproject.android.sharing.BaseMessageFragment.MessageFragmentListener;
+import org.briarproject.android.sharing.ContactSelectorFragment;
+import org.briarproject.api.contact.Contact;
+import org.briarproject.api.db.DatabaseExecutor;
+import org.briarproject.api.db.DbException;
+import org.briarproject.api.sync.GroupId;
+
+public class GroupInviteActivity extends BaseGroupInviteActivity
+		implements MessageFragmentListener {
+
+	@Override
+	public void injectActivity(ActivityComponent component) {
+		component.inject(this);
+	}
+
+	@Override
+	public void onCreate(Bundle bundle) {
+		super.onCreate(bundle);
+
+		// Initialise the group ID,
+		// it will be saved and restored by the superclass
+		Intent i = getIntent();
+		byte[] g = i.getByteArrayExtra(GROUP_ID);
+		if (g == null) throw new IllegalStateException("No GroupId in intent.");
+		groupId = new GroupId(g);
+
+		if (bundle == null) {
+			ContactSelectorFragment fragment =
+					ContactSelectorFragment.newInstance(groupId);
+			getSupportFragmentManager().beginTransaction()
+					.replace(R.id.fragmentContainer, fragment)
+					.commit();
+		}
+	}
+
+	@Override
+	@DatabaseExecutor
+	public boolean isDisabled(GroupId groupId, Contact c) throws DbException {
+		// TODO disable contacts that can not be invited
+		return false;
+	}
+
+}