diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/BaseActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/BaseActivity.java
index 0c4761ada..30c518dbc 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/activity/BaseActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/BaseActivity.java
@@ -181,12 +181,6 @@ public abstract class BaseActivity extends AppCompatActivity
showFragment(getSupportFragmentManager(), f, f.getUniqueTag());
}
- protected boolean isFragmentAdded(String fragmentTag) {
- FragmentManager fm = getSupportFragmentManager();
- Fragment f = fm.findFragmentByTag(fragmentTag);
- return f != null && f.isAdded();
- }
-
private boolean showScreenFilterWarning() {
if (((BriarApplication) getApplication()).isInstrumentationTest()) {
return false;
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotActivity.java
index 359b86f2d..edbe226b7 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/hotspot/HotspotActivity.java
@@ -56,13 +56,9 @@ public class HotspotActivity extends BriarActivity
if (hotspotState instanceof HotspotStarted) {
HotspotStarted started = (HotspotStarted) hotspotState;
String tag = HotspotFragment.TAG;
- // check if fragment is already added
- // to not lose state on configuration changes
- if (fm.findFragmentByTag(tag) == null) {
- if (started.wasNotYetConsumed()) {
- started.consume();
- showFragment(fm, new HotspotFragment(), tag);
- }
+ if (started.wasNotYetConsumed()) {
+ started.consume();
+ showFragment(fm, new HotspotFragment(), tag);
}
} else if (hotspotState instanceof HotspotError) {
HotspotError error = (HotspotError) hotspotState;
@@ -116,10 +112,8 @@ public class HotspotActivity extends BriarActivity
private void showErrorFragment(String error) {
FragmentManager fm = getSupportFragmentManager();
String tag = HotspotErrorFragment.TAG;
- if (fm.findFragmentByTag(tag) == null) {
- Fragment f = HotspotErrorFragment.newInstance(error);
- showFragment(fm, f, tag, false);
- }
+ Fragment f = HotspotErrorFragment.newInstance(error);
+ showFragment(fm, f, tag, false);
}
@Override
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/StartupActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/login/StartupActivity.java
index c65a06cc7..6c43e0126 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/login/StartupActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/StartupActivity.java
@@ -85,16 +85,10 @@ public class StartupActivity extends BaseActivity implements
if (state == SIGNED_OUT) {
// Configuration changes such as screen rotation
// can cause this to get called again.
- // Don't replace the fragment in that case to not lose view state.
- if (!isFragmentAdded(PasswordFragment.TAG)) {
- showInitialFragment(new PasswordFragment());
- }
+ showInitialFragment(new PasswordFragment());
} else if (state == SIGNED_IN || state == STARTING) {
startService(new Intent(this, BriarService.class));
- // Only show OpenDatabaseFragment if not already visible.
- if (!isFragmentAdded(OpenDatabaseFragment.TAG)) {
- showNextFragment(new OpenDatabaseFragment());
- }
+ showNextFragment(new OpenDatabaseFragment());
} else if (state == STARTED) {
setResult(RESULT_OK);
supportFinishAfterTransition();
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/ErrorFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/ErrorFragment.java
new file mode 100644
index 000000000..e2be4c001
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/ErrorFragment.java
@@ -0,0 +1,47 @@
+package org.briarproject.briar.android.mailbox;
+
+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.fragment.FinalFragment;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+
+@MethodsNotNullByDefault
+@ParametersNotNullByDefault
+public class ErrorFragment extends FinalFragment {
+
+ public static ErrorFragment newInstance(@StringRes int title,
+ @StringRes int text) {
+ ErrorFragment f = new ErrorFragment();
+ Bundle args = new Bundle();
+ args.putInt(ARG_TITLE, title);
+ args.putInt(ARG_ICON, R.drawable.alerts_and_states_error);
+ args.putInt(ARG_ICON_TINT, R.color.briar_red_500);
+ args.putInt(ARG_TEXT, text);
+ f.setArguments(args);
+ return f;
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ View v = super.onCreateView(inflater, container, savedInstanceState);
+ buttonView.setText(R.string.try_again_button);
+ return v;
+ }
+
+ @Override
+ protected void onBackButtonPressed() {
+ requireActivity().getSupportFragmentManager().popBackStack();
+ }
+
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxActivity.java
index e8056dad2..53a2aebde 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxActivity.java
@@ -13,6 +13,7 @@ import org.briarproject.briar.android.activity.BriarActivity;
import javax.inject.Inject;
import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import static android.view.View.INVISIBLE;
@@ -49,9 +50,11 @@ public class MailboxActivity extends BriarActivity {
viewModel.getState().observe(this, state -> {
if (state instanceof MailboxState.NotSetup) {
- if (savedInstanceState == null) onNotSetup();
+ onNotSetup();
} else if (state instanceof MailboxState.SettingUp) {
onCodeScanned();
+ } else if (state instanceof MailboxState.QrCodeWrong) {
+ onQrCodeWrong();
}
});
}
@@ -90,4 +93,11 @@ public class MailboxActivity extends BriarActivity {
MailboxConnectingFragment.TAG, false);
}
+ private void onQrCodeWrong() {
+ Fragment f = ErrorFragment.newInstance(
+ R.string.mailbox_setup_qr_code_wrong_title,
+ R.string.mailbox_setup_qr_code_wrong_description);
+ showFragment(getSupportFragmentManager(), f, ErrorFragment.TAG);
+ }
+
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxState.java b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxState.java
index 2b9f32596..e8deb1df2 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxState.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxState.java
@@ -8,6 +8,9 @@ class MailboxState {
static class SettingUp extends MailboxState {
}
+ static class QrCodeWrong extends MailboxState {
+ }
+
// TODO add other states
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxViewModel.java
index 7a009ad69..1f4c657ff 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxViewModel.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxViewModel.java
@@ -4,6 +4,7 @@ import android.app.Application;
import com.google.zxing.Result;
+import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.TransactionManager;
@@ -28,7 +29,7 @@ import androidx.annotation.UiThread;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
-import static java.util.logging.Level.INFO;
+import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
@NotNullByDefault
@@ -79,31 +80,39 @@ class MailboxViewModel extends DbViewModel
@IoExecutor
public void onQrCodeDecoded(Result result) {
LOG.info("Got result from decoder");
- byte[] bytes = result.getText().getBytes(ISO_8859_1);
+ try {
+ // TODO pass props to core (maybe even do payload parsing there)
+ MailboxProperties properties = decodeQrCode(result.getText());
+ } catch (FormatException e) {
+ state.postValue(new MailboxState.QrCodeWrong());
+ return;
+ }
+ state.postValue(new MailboxState.SettingUp());
+ }
- if (LOG.isLoggable(INFO))
- LOG.info("QR code length in bytes: " + bytes.length);
+ private MailboxProperties decodeQrCode(String payload)
+ throws FormatException {
+ byte[] bytes = payload.getBytes(ISO_8859_1);
if (bytes.length != 65) {
- LOG.info("QR code has wrong length");
- return;
+ if (LOG.isLoggable(WARNING)) {
+ LOG.warning("QR code length is not 65: " + bytes.length);
+ }
+ throw new FormatException();
}
-
- if (LOG.isLoggable(INFO))
- LOG.info("QR code version: " + bytes[0]);
- if (bytes[0] != VERSION_REQUIRED) {
- LOG.info("QR code has wrong version");
- return;
+ int version = bytes[0] & 0xFF;
+ if (version != VERSION_REQUIRED) {
+ if (LOG.isLoggable(WARNING)) {
+ LOG.warning("QR code has not version " + VERSION_REQUIRED +
+ ": " + version);
+ }
+ throw new FormatException();
}
-
LOG.info("QR code is valid");
byte[] onionPubKey = Arrays.copyOfRange(bytes, 1, 33);
String onionAddress = crypto.encodeOnionAddress(onionPubKey);
byte[] tokenBytes = Arrays.copyOfRange(bytes, 33, 65);
MailboxAuthToken setupToken = new MailboxAuthToken(tokenBytes);
- MailboxProperties props =
- new MailboxProperties(onionAddress, setupToken, true);
- // TODO pass props to core (maybe even do payload parsing there)
- state.postValue(new MailboxState.SettingUp());
+ return new MailboxProperties(onionAddress, setupToken, true);
}
@UiThread
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
index 3c43564ae..ea6272b71 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
@@ -147,6 +147,10 @@ public class UiUtils {
public static void showFragment(FragmentManager fm, Fragment f,
@Nullable String tag, boolean addToBackStack) {
+ // don't re-add same (already added/visible) fragment again
+ Fragment fragment = fm.findFragmentByTag(tag);
+ if (fragment != null && fragment.isAdded()) return;
+
FragmentTransaction ta = fm.beginTransaction()
.setCustomAnimations(R.anim.step_next_in,
R.anim.step_previous_out, R.anim.step_previous_in,
diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml
index 6010f7a55..4f809233b 100644
--- a/briar-android/src/main/res/values/strings.xml
+++ b/briar-android/src/main/res/values/strings.xml
@@ -630,6 +630,8 @@
https://briarproject.org/apk
You have denied access to the camera, but scanning a QR code requires using the camera.\n\nPlease consider granting access.
Connecting…
+ Wrong QR code
+ The scanned code is invalid. Please open the Briar Mailbox app and scan the QR code it presents.
Disappearing messages