diff --git a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/ReceiveFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/ReceiveFragment.java index 76db99280..f56a3184c 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/ReceiveFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/ReceiveFragment.java @@ -47,6 +47,8 @@ public class ReceiveFragment extends Fragment { private Button button; private ProgressBar progressBar; + private boolean checkForStateLoss = false; + @Override public void onAttach(Context context) { super.onAttach(context); @@ -73,6 +75,10 @@ public class ReceiveFragment extends Fragment { .observeEvent(getViewLifecycleOwner(), this::onOldTaskResumed); viewModel.getState() .observe(getViewLifecycleOwner(), this::onStateChanged); + + // need to check for lost ViewModel state when creating with prior state + if (savedInstanceState != null) checkForStateLoss = true; + return v; } @@ -84,6 +90,23 @@ public class ReceiveFragment extends Fragment { scrollView.post(() -> scrollView.fullScroll(FOCUS_DOWN)); } + @Override + public void onResume() { + super.onResume(); + // This code gets called *after* launcher had a chance + // to return the activity result. + if (checkForStateLoss && viewModel.hasNoState()) { + // We were recreated, but have lost the ViewModel state, + // because our activity was destroyed. + // + // Remove the current fragment from the stack + // to prevent duplicates on the back stack. + getParentFragmentManager().popBackStack(); + // Start again (picks up existing task or allows to start a new one) + viewModel.startReceiveData(); + } + } + private void onOldTaskResumed(boolean resumed) { if (resumed) { Toast.makeText(requireContext(), @@ -104,6 +127,8 @@ public class ReceiveFragment extends Fragment { private void onDocumentChosen(@Nullable Uri uri) { if (uri == null) return; + // we just got our document, so don't treat this as a state loss + checkForStateLoss = false; viewModel.importData(uri); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/RemovableDriveViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/RemovableDriveViewModel.java index cd64932fb..525d199a8 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/RemovableDriveViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/RemovableDriveViewModel.java @@ -75,6 +75,12 @@ class RemovableDriveViewModel extends DbViewModel { } } + @UiThread + boolean hasNoState() { + return action.getLastValue() == null && state.getValue() == null && + task == null; + } + /** * Set this as soon as it becomes available. */ diff --git a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/SendFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/SendFragment.java index 1d8b872cb..d1235ff17 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/SendFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/removabledrive/SendFragment.java @@ -51,6 +51,8 @@ public class SendFragment extends Fragment { private Button button; private ProgressBar progressBar; + private boolean checkForStateLoss = false; + @Override public void onAttach(Context context) { super.onAttach(context); @@ -80,6 +82,9 @@ public class SendFragment extends Fragment { viewModel.getState() .observe(getViewLifecycleOwner(), this::onStateChanged); + // need to check for lost ViewModel state when creating with prior state + if (savedInstanceState != null) checkForStateLoss = true; + return v; } @@ -91,6 +96,23 @@ public class SendFragment extends Fragment { scrollView.post(() -> scrollView.fullScroll(FOCUS_DOWN)); } + @Override + public void onResume() { + super.onResume(); + // This code gets called *after* launcher had a chance + // to return the activity result. + if (checkForStateLoss && viewModel.hasNoState()) { + // We were recreated, but have lost the ViewModel state, + // because our activity was destroyed. + // + // Remove the current fragment from the stack + // to prevent duplicates on the back stack. + getParentFragmentManager().popBackStack(); + // Start again (picks up existing task or allows to start a new one) + viewModel.startSendData(); + } + } + private void onOldTaskResumed(boolean resumed) { if (resumed) { Toast.makeText(requireContext(), @@ -127,6 +149,8 @@ public class SendFragment extends Fragment { private void onDocumentCreated(@Nullable Uri uri) { if (uri == null) return; + // we just got our document, so don't treat this as a state loss + checkForStateLoss = false; viewModel.exportData(uri); }