diff --git a/briar-android/src/main/AndroidManifest.xml b/briar-android/src/main/AndroidManifest.xml
index b590e7acf..957285d85 100644
--- a/briar-android/src/main/AndroidManifest.xml
+++ b/briar-android/src/main/AndroidManifest.xml
@@ -448,6 +448,12 @@
android:label="@string/pending_contact_requests"
android:theme="@style/BriarTheme" />
+
+
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java
index f1904fdab..51d5f3807 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java
@@ -30,14 +30,15 @@ import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.android.account.DozeHelperModule;
import org.briarproject.briar.android.account.LockManagerImpl;
import org.briarproject.briar.android.account.SetupModule;
+import org.briarproject.briar.android.bluetoothsetup.BluetoothSetupModule;
import org.briarproject.briar.android.contact.ContactListModule;
import org.briarproject.briar.android.forum.ForumModule;
import org.briarproject.briar.android.keyagreement.ContactExchangeModule;
import org.briarproject.briar.android.login.LoginModule;
import org.briarproject.briar.android.navdrawer.NavDrawerModule;
-import org.briarproject.briar.android.settings.SettingsModule;
import org.briarproject.briar.android.privategroup.list.GroupListModule;
import org.briarproject.briar.android.reporting.DevReportModule;
+import org.briarproject.briar.android.settings.SettingsModule;
import org.briarproject.briar.android.test.TestAvatarCreatorImpl;
import org.briarproject.briar.android.viewmodel.ViewModelModule;
import org.briarproject.briar.api.android.AndroidNotificationManager;
@@ -78,6 +79,7 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
SettingsModule.class,
DevReportModule.class,
ContactListModule.class,
+ BluetoothSetupModule.class,
// below need to be within same scope as ViewModelProvider.Factory
ForumModule.BindsModule.class,
GroupListModule.class,
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
index 3835a7aaa..d7d18d798 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
@@ -20,6 +20,10 @@ import org.briarproject.briar.android.blog.ReblogFragment;
import org.briarproject.briar.android.blog.RssFeedImportActivity;
import org.briarproject.briar.android.blog.RssFeedManageActivity;
import org.briarproject.briar.android.blog.WriteBlogPostActivity;
+import org.briarproject.briar.android.bluetoothsetup.BluetoothSetupActivity;
+import org.briarproject.briar.android.bluetoothsetup.BluetoothSetupDiscoveryFragment;
+import org.briarproject.briar.android.bluetoothsetup.BluetoothSetupPendingFragment;
+import org.briarproject.briar.android.bluetoothsetup.BluetoothSetupStartFragment;
import org.briarproject.briar.android.contact.ContactListFragment;
import org.briarproject.briar.android.contact.add.remote.AddContactActivity;
import org.briarproject.briar.android.contact.add.remote.LinkExchangeFragment;
@@ -186,6 +190,8 @@ public interface ActivityComponent {
void inject(CrashReportActivity crashReportActivity);
+ void inject(BluetoothSetupActivity activity);
+
// Fragments
void inject(AuthorNameFragment fragment);
@@ -242,4 +248,10 @@ public interface ActivityComponent {
void inject(ConfirmAvatarDialogFragment fragment);
+ void inject(BluetoothSetupStartFragment fragment);
+
+ void inject(BluetoothSetupDiscoveryFragment fragment);
+
+ void inject(BluetoothSetupPendingFragment fragment);
+
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupActivity.java
new file mode 100644
index 000000000..603e2decc
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupActivity.java
@@ -0,0 +1,60 @@
+package org.briarproject.briar.android.bluetoothsetup;
+
+import android.os.Bundle;
+import android.view.MenuItem;
+
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.activity.BriarActivity;
+import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
+
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+
+import androidx.appcompat.app.ActionBar;
+import androidx.lifecycle.ViewModelProvider;
+
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
+public class BluetoothSetupActivity extends BriarActivity implements
+ BaseFragmentListener {
+
+ @Inject
+ ViewModelProvider.Factory viewModelFactory;
+ private BluetoothSetupViewModel viewModel;
+
+ @Override
+ public void injectActivity(ActivityComponent component) {
+ component.inject(this);
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle state) {
+ super.onCreate(state);
+ setContentView(R.layout.activity_fragment_container);
+
+ ActionBar ab = getSupportActionBar();
+ if (ab != null) {
+ ab.setDisplayHomeAsUpEnabled(true);
+ }
+
+ viewModel = new ViewModelProvider(this, viewModelFactory)
+ .get(BluetoothSetupViewModel.class);
+
+ if (state == null) {
+ showInitialFragment(new BluetoothSetupStartFragment());
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupDiscoveryFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupDiscoveryFragment.java
new file mode 100644
index 000000000..68cb685fc
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupDiscoveryFragment.java
@@ -0,0 +1,65 @@
+package org.briarproject.briar.android.bluetoothsetup;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.fragment.BaseFragment;
+
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+
+import androidx.lifecycle.ViewModelProvider;
+
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
+public class BluetoothSetupDiscoveryFragment extends BaseFragment {
+ private static final String TAG =
+ BluetoothSetupDiscoveryFragment.class.getName();
+
+ @Inject
+ ViewModelProvider.Factory viewModelFactory;
+
+ private BluetoothSetupViewModel viewModel;
+
+ @Override
+ public String getUniqueTag() {
+ return TAG;
+ }
+
+ @Override
+ public void injectFragment(ActivityComponent component) {
+ component.inject(this);
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ if (getActivity() == null || getContext() == null) return null;
+
+ viewModel = new ViewModelProvider(requireActivity())
+ .get(BluetoothSetupViewModel.class);
+
+ View v =
+ inflater.inflate(R.layout.fragment_bluetooth_setup_discovery,
+ container, false);
+
+ // TODO to enable when user picks a device from list
+
+ Button continueButton = v.findViewById(R.id.continueButton);
+ continueButton.setOnClickListener(view -> {
+ showNextFragment(new BluetoothSetupPendingFragment());
+ });
+ continueButton.setEnabled(true);
+
+ return v;
+ }
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupModule.java b/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupModule.java
new file mode 100644
index 000000000..e2a5fcc05
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupModule.java
@@ -0,0 +1,18 @@
+package org.briarproject.briar.android.bluetoothsetup;
+
+import org.briarproject.briar.android.viewmodel.ViewModelKey;
+
+import androidx.lifecycle.ViewModel;
+import dagger.Binds;
+import dagger.Module;
+import dagger.multibindings.IntoMap;
+
+@Module
+public abstract class BluetoothSetupModule {
+
+ @Binds
+ @IntoMap
+ @ViewModelKey(BluetoothSetupViewModel.class)
+ abstract ViewModel bindBluetoothSetupViewModel(
+ BluetoothSetupViewModel bluetoothSetupViewModel);
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupPendingFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupPendingFragment.java
new file mode 100644
index 000000000..a8b595e90
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupPendingFragment.java
@@ -0,0 +1,60 @@
+package org.briarproject.briar.android.bluetoothsetup;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.fragment.BaseFragment;
+
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+
+import androidx.lifecycle.ViewModelProvider;
+
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
+public class BluetoothSetupPendingFragment extends BaseFragment {
+ private static final String TAG =
+ BluetoothSetupPendingFragment.class.getName();
+
+ @Inject
+ ViewModelProvider.Factory viewModelFactory;
+
+ private BluetoothSetupViewModel viewModel;
+
+ @Override
+ public String getUniqueTag() {
+ return TAG;
+ }
+
+ @Override
+ public void injectFragment(ActivityComponent component) {
+ component.inject(this);
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ if (getActivity() == null || getContext() == null) return null;
+
+ viewModel = new ViewModelProvider(requireActivity())
+ .get(BluetoothSetupViewModel.class);
+
+ View v = inflater.inflate(R.layout.fragment_bluetooth_setup_pending,
+ container, false);
+
+ return v;
+ }
+
+ private void onContinueButtonClicked() {
+ // showNextFragment(BluetoothSetupDiscoveryFragment.newInstance());
+ }
+
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupStartFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupStartFragment.java
new file mode 100644
index 000000000..98c67c34c
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupStartFragment.java
@@ -0,0 +1,65 @@
+package org.briarproject.briar.android.bluetoothsetup;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
+import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.fragment.BaseFragment;
+
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+
+import androidx.lifecycle.ViewModelProvider;
+
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
+public class BluetoothSetupStartFragment extends BaseFragment {
+ private static final String TAG =
+ BluetoothSetupStartFragment.class.getName();
+
+ @Inject
+ ViewModelProvider.Factory viewModelFactory;
+
+ private BluetoothSetupViewModel viewModel;
+
+ @Override
+ public String getUniqueTag() {
+ return TAG;
+ }
+
+ @Override
+ public void injectFragment(ActivityComponent component) {
+ component.inject(this);
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ if (getActivity() == null || getContext() == null) return null;
+
+ viewModel = new ViewModelProvider(requireActivity())
+ .get(BluetoothSetupViewModel.class);
+
+ View v = inflater.inflate(R.layout.fragment_bluetooth_setup_start,
+ container, false);
+
+ // TODO device-BT and BT-plugin needs to be enabled at this point
+
+ Button startButton = v.findViewById(R.id.startButton);
+ startButton.setOnClickListener(view -> {
+ showNextFragment(new BluetoothSetupDiscoveryFragment());
+ });
+ startButton.setEnabled(true);
+
+ return v;
+ }
+
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupViewModel.java
new file mode 100644
index 000000000..2230eed80
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/bluetoothsetup/BluetoothSetupViewModel.java
@@ -0,0 +1,33 @@
+package org.briarproject.briar.android.bluetoothsetup;
+
+import android.app.Application;
+
+import org.briarproject.bramble.api.db.DatabaseExecutor;
+import org.briarproject.bramble.api.db.TransactionManager;
+import org.briarproject.bramble.api.lifecycle.LifecycleManager;
+import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
+import org.briarproject.bramble.api.system.AndroidExecutor;
+import org.briarproject.briar.android.viewmodel.DbViewModel;
+
+import java.util.concurrent.Executor;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+
+import static java.util.logging.Logger.getLogger;
+
+@NotNullByDefault
+public class BluetoothSetupViewModel extends DbViewModel {
+
+ private final static Logger LOG =
+ getLogger(BluetoothSetupViewModel.class.getName());
+
+ @Inject
+ BluetoothSetupViewModel(Application application,
+ @DatabaseExecutor Executor dbExecutor,
+ LifecycleManager lifecycleManager,
+ TransactionManager db,
+ AndroidExecutor androidExecutor) {
+ super(application, dbExecutor, lifecycleManager, db, androidExecutor);
+ }
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java
index 1a803c9a6..f05fa04fa 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactListFragment.java
@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.bluetoothsetup.BluetoothSetupActivity;
import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
import org.briarproject.briar.android.contact.add.remote.AddContactActivity;
import org.briarproject.briar.android.contact.add.remote.PendingContactListActivity;
@@ -134,6 +135,10 @@ public class ContactListFragment extends BaseFragment
case R.id.action_add_contact_remotely:
startActivity(
new Intent(getContext(), AddContactActivity.class));
+ case R.id.action_bluetooth_setup:
+ startActivity(
+ new Intent(getContext(),
+ BluetoothSetupActivity.class));
}
}
diff --git a/briar-android/src/main/res/layout/fragment_bluetooth_setup_discovery.xml b/briar-android/src/main/res/layout/fragment_bluetooth_setup_discovery.xml
new file mode 100644
index 000000000..76d253b46
--- /dev/null
+++ b/briar-android/src/main/res/layout/fragment_bluetooth_setup_discovery.xml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/src/main/res/layout/fragment_bluetooth_setup_pending.xml b/briar-android/src/main/res/layout/fragment_bluetooth_setup_pending.xml
new file mode 100644
index 000000000..692f88a77
--- /dev/null
+++ b/briar-android/src/main/res/layout/fragment_bluetooth_setup_pending.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/src/main/res/layout/fragment_bluetooth_setup_start.xml b/briar-android/src/main/res/layout/fragment_bluetooth_setup_start.xml
new file mode 100644
index 000000000..357640118
--- /dev/null
+++ b/briar-android/src/main/res/layout/fragment_bluetooth_setup_start.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/src/main/res/menu/contact_list_actions.xml b/briar-android/src/main/res/menu/contact_list_actions.xml
index 738b1dea2..c66f4328d 100644
--- a/briar-android/src/main/res/menu/contact_list_actions.xml
+++ b/briar-android/src/main/res/menu/contact_list_actions.xml
@@ -1,6 +1,5 @@
-