mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Refactor more code into AddNearbyContactViewModel
thus concentrating the logic there needing less back and forth with the activity
This commit is contained in:
@@ -11,7 +11,6 @@ public interface RequestCodes {
|
||||
int REQUEST_RINGTONE = 7;
|
||||
int REQUEST_PERMISSION_CAMERA_LOCATION = 8;
|
||||
int REQUEST_DOZE_WHITELISTING = 9;
|
||||
int REQUEST_BLUETOOTH_DISCOVERABLE = 10;
|
||||
int REQUEST_UNLOCK = 11;
|
||||
int REQUEST_KEYGUARD_UNLOCK = 12;
|
||||
int REQUEST_ATTACH_IMAGE = 13;
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
package org.briarproject.briar.android.contact.add.nearby;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.NullSafety;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
@@ -21,25 +17,25 @@ import org.briarproject.briar.android.contact.add.nearby.AddContactState.Failed;
|
||||
import org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
|
||||
import org.briarproject.briar.android.util.RequestBluetoothDiscoverable;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
|
||||
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||
import static android.widget.Toast.LENGTH_LONG;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_BLUETOOTH_DISCOVERABLE;
|
||||
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.ACCEPTED;
|
||||
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.REFUSED;
|
||||
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.UNKNOWN;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -55,14 +51,9 @@ public class AddNearbyContactActivity extends BriarActivity
|
||||
private AddNearbyContactViewModel viewModel;
|
||||
private AddNearbyContactPermissionManager permissionManager;
|
||||
|
||||
/**
|
||||
* Set to true in onPostResume() and false in onPause(). This prevents the
|
||||
* QR code fragment from being shown if onRequestPermissionsResult() is
|
||||
* called while the activity is paused, which could cause a crash due to
|
||||
* https://issuetracker.google.com/issues/37067655.
|
||||
*/
|
||||
private boolean isResumed = false;
|
||||
private BroadcastReceiver bluetoothReceiver = null;
|
||||
private final ActivityResultLauncher<Integer> bluetoothLauncher =
|
||||
registerForActivityResult(new RequestBluetoothDiscoverable(),
|
||||
this::onBluetoothDiscoverableResult);
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
@@ -79,21 +70,14 @@ public class AddNearbyContactActivity extends BriarActivity
|
||||
setContentView(R.layout.activity_fragment_container_toolbar);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
NullSafety.requireNonNull(getSupportActionBar())
|
||||
.setDisplayHomeAsUpEnabled(true);
|
||||
requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
|
||||
if (state == null) {
|
||||
showInitialFragment(AddNearbyContactIntroFragment.newInstance());
|
||||
}
|
||||
IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED);
|
||||
bluetoothReceiver = new BluetoothStateReceiver();
|
||||
registerReceiver(bluetoothReceiver, filter);
|
||||
viewModel.getWasContinueClicked().observe(this, clicked -> {
|
||||
if (clicked && permissionManager.checkPermissions()) {
|
||||
showQrCodeFragmentIfAllowed();
|
||||
}
|
||||
});
|
||||
viewModel.getTransportStateChanged().observeEvent(this,
|
||||
t -> showQrCodeFragmentIfAllowed());
|
||||
viewModel.getCheckPermissions().observeEvent(this, check ->
|
||||
permissionManager.checkPermissions()); // never false
|
||||
viewModel.getRequestBluetoothDiscoverable().observeEvent(this, r ->
|
||||
requestBluetoothDiscoverable()); // never false
|
||||
viewModel.getShowQrCodeFragment().observeEvent(this, show -> {
|
||||
if (show) showQrCodeFragment();
|
||||
});
|
||||
@@ -113,37 +97,23 @@ public class AddNearbyContactActivity extends BriarActivity
|
||||
@Override
|
||||
protected void onPostResume() {
|
||||
super.onPostResume();
|
||||
isResumed = true;
|
||||
// Workaround for
|
||||
// https://code.google.com/p/android/issues/detail?id=190966
|
||||
showQrCodeFragmentIfAllowed();
|
||||
viewModel.setIsActivityResumed(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
isResumed = false;
|
||||
viewModel.setIsActivityResumed(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (bluetoothReceiver != null) unregisterReceiver(bluetoothReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int request, int result,
|
||||
@Nullable Intent data) {
|
||||
if (request == REQUEST_BLUETOOTH_DISCOVERABLE) {
|
||||
if (result == RESULT_CANCELED) {
|
||||
LOG.info("Bluetooth discoverability was refused");
|
||||
viewModel.bluetoothDecision = REFUSED;
|
||||
} else {
|
||||
LOG.info("Bluetooth discoverability was accepted");
|
||||
viewModel.bluetoothDecision = ACCEPTED;
|
||||
}
|
||||
showQrCodeFragmentIfAllowed();
|
||||
} else super.onActivityResult(request, result, data);
|
||||
private void onBluetoothDiscoverableResult(boolean discoverable) {
|
||||
if (discoverable) {
|
||||
LOG.info("Bluetooth discoverability was accepted");
|
||||
viewModel.setBluetoothDecision(ACCEPTED);
|
||||
} else {
|
||||
LOG.info("Bluetooth discoverability was refused");
|
||||
viewModel.setBluetoothDecision(REFUSED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,14 +131,16 @@ public class AddNearbyContactActivity extends BriarActivity
|
||||
super.onRequestPermissionsResult(requestCode, permissions,
|
||||
grantResults);
|
||||
permissionManager.onRequestPermissionsResult(requestCode, permissions,
|
||||
grantResults, this::showQrCodeFragmentIfAllowed);
|
||||
grantResults, viewModel::showQrCodeFragmentIfAllowed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (viewModel.getState().getValue() instanceof Failed) {
|
||||
// finish this activity when going back in failed state
|
||||
supportFinishAfterTransition();
|
||||
// re-create this activity when going back in failed state
|
||||
Intent i = new Intent(this, AddNearbyContactActivity.class);
|
||||
i.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(i);
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
@@ -176,41 +148,15 @@ public class AddNearbyContactActivity extends BriarActivity
|
||||
|
||||
private void requestBluetoothDiscoverable() {
|
||||
if (!viewModel.isBluetoothSupported()) {
|
||||
viewModel.bluetoothDecision = BluetoothDecision.NO_ADAPTER;
|
||||
showQrCodeFragmentIfAllowed();
|
||||
viewModel.setBluetoothDecision(BluetoothDecision.NO_ADAPTER);
|
||||
} else {
|
||||
Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
|
||||
if (i.resolveActivity(getPackageManager()) != null) {
|
||||
LOG.info("Asking for Bluetooth discoverability");
|
||||
viewModel.bluetoothDecision = BluetoothDecision.WAITING;
|
||||
startActivityForResult(i, REQUEST_BLUETOOTH_DISCOVERABLE);
|
||||
viewModel.setBluetoothDecision(BluetoothDecision.WAITING);
|
||||
bluetoothLauncher.launch(120); // 2min discoverable
|
||||
} else {
|
||||
viewModel.bluetoothDecision = BluetoothDecision.NO_ADAPTER;
|
||||
showQrCodeFragmentIfAllowed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("StatementWithEmptyBody")
|
||||
private void showQrCodeFragmentIfAllowed() {
|
||||
boolean continueClicked = // never set to null
|
||||
NullSafety.requireNonNull(
|
||||
viewModel.getWasContinueClicked().getValue());
|
||||
boolean permissionsGranted =
|
||||
permissionManager.areEssentialPermissionsGranted();
|
||||
if (isResumed && continueClicked && permissionsGranted) {
|
||||
if (viewModel.isWifiReady() && viewModel.isBluetoothReady()) {
|
||||
LOG.info("Wifi and Bluetooth are ready");
|
||||
viewModel.startAddingContact();
|
||||
} else {
|
||||
viewModel.enableWifiIfWeShould();
|
||||
if (viewModel.bluetoothDecision == UNKNOWN) {
|
||||
requestBluetoothDiscoverable();
|
||||
} else if (viewModel.bluetoothDecision == REFUSED) {
|
||||
// Ask again when the user clicks "continue"
|
||||
} else {
|
||||
viewModel.enableBluetoothIfWeShould();
|
||||
}
|
||||
viewModel.setBluetoothDecision(BluetoothDecision.NO_ADAPTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,11 +179,6 @@ public class AddNearbyContactActivity extends BriarActivity
|
||||
((ContactExchangeFinished) state).result;
|
||||
onContactExchangeResult(result);
|
||||
} else if (state instanceof Failed) {
|
||||
// Remove navigation icon, so user can't go back when failed
|
||||
// ErrorFragment will finish or relaunch this activity
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
toolbar.setNavigationIcon(null);
|
||||
|
||||
Boolean qrCodeTooOld = ((Failed) state).qrCodeTooOld;
|
||||
onAddingContactFailed(qrCodeTooOld);
|
||||
}
|
||||
@@ -286,11 +227,4 @@ public class AddNearbyContactActivity extends BriarActivity
|
||||
showNextFragment(new AddNearbyContactErrorFragment());
|
||||
}
|
||||
|
||||
private class BluetoothStateReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
LOG.info("Bluetooth scan mode changed");
|
||||
showQrCodeFragmentIfAllowed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,10 +171,8 @@ public class AddNearbyContactFragment extends BaseFragment
|
||||
status.setText(R.string.waiting_for_contact_to_scan);
|
||||
} else if (state instanceof KeyAgreementStarted) {
|
||||
qrCodeView.setVisibility(INVISIBLE);
|
||||
statusView.setVisibility(VISIBLE);
|
||||
status.setText(R.string.authenticating_with_device);
|
||||
} else if (state instanceof ContactExchangeStarted) {
|
||||
statusView.setVisibility(VISIBLE);
|
||||
status.setText(R.string.exchanging_contact_details);
|
||||
} else if (state instanceof Failed) {
|
||||
// the activity will replace this fragment with an error fragment
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.briarproject.briar.android.contact.add.nearby;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.BaseActivity;
|
||||
|
||||
@@ -11,6 +13,8 @@ import static android.Manifest.permission.ACCESS_FINE_LOCATION;
|
||||
import static android.Manifest.permission.CAMERA;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale;
|
||||
import static androidx.core.content.ContextCompat.checkSelfPermission;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA_LOCATION;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getGoToSettingsListener;
|
||||
|
||||
@@ -37,6 +41,15 @@ class AddNearbyContactPermissionManager {
|
||||
locationPermission = Permission.UNKNOWN;
|
||||
}
|
||||
|
||||
static boolean areEssentialPermissionsGranted(Context ctx,
|
||||
boolean isBluetoothSupported) {
|
||||
int ok = PERMISSION_GRANTED;
|
||||
return checkSelfPermission(ctx, CAMERA) == ok &&
|
||||
(SDK_INT < 23 ||
|
||||
checkSelfPermission(ctx, ACCESS_FINE_LOCATION) == ok ||
|
||||
!isBluetoothSupported);
|
||||
}
|
||||
|
||||
boolean areEssentialPermissionsGranted() {
|
||||
return cameraPermission == Permission.GRANTED &&
|
||||
(SDK_INT < 23 || locationPermission == Permission.GRANTED ||
|
||||
@@ -147,8 +160,7 @@ class AddNearbyContactPermissionManager {
|
||||
}
|
||||
|
||||
private boolean shouldShowRationale(String permission) {
|
||||
return ActivityCompat
|
||||
.shouldShowRequestPermissionRationale(ctx, permission);
|
||||
return shouldShowRequestPermissionRationale(ctx, permission);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@ package org.briarproject.briar.android.contact.add.nearby;
|
||||
|
||||
import android.app.Application;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.widget.Toast;
|
||||
@@ -39,6 +43,7 @@ import org.briarproject.bramble.api.plugin.PluginManager;
|
||||
import org.briarproject.bramble.api.plugin.TransportId;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.bramble.api.plugin.event.TransportStateEvent;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.contact.add.nearby.AddContactState.ContactExchangeFinished;
|
||||
import org.briarproject.briar.android.contact.add.nearby.AddContactState.ContactExchangeResult.Error;
|
||||
@@ -64,6 +69,7 @@ import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
|
||||
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
||||
import static android.widget.Toast.LENGTH_LONG;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
@@ -75,6 +81,7 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
|
||||
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
|
||||
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactPermissionManager.areEssentialPermissionsGranted;
|
||||
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.REFUSED;
|
||||
import static org.briarproject.briar.android.contact.add.nearby.AddNearbyContactViewModel.BluetoothDecision.UNKNOWN;
|
||||
|
||||
@@ -116,6 +123,7 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
||||
private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
|
||||
|
||||
private final EventBus eventBus;
|
||||
private final AndroidExecutor androidExecutor;
|
||||
private final Executor ioExecutor;
|
||||
private final PluginManager pluginManager;
|
||||
private final PayloadEncoder payloadEncoder;
|
||||
@@ -124,28 +132,28 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
||||
private final ContactExchangeManager contactExchangeManager;
|
||||
private final ConnectionManager connectionManager;
|
||||
|
||||
/**
|
||||
* Set to true when the continue button is clicked, and false when the QR
|
||||
* code fragment is shown. This prevents the QR code fragment from being
|
||||
* shown automatically before the continue button has been clicked.
|
||||
*/
|
||||
private final MutableLiveData<Boolean> wasContinueClicked =
|
||||
new MutableLiveData<>(false);
|
||||
private final MutableLiveEvent<Boolean> showQrCodeFragment =
|
||||
private final MutableLiveEvent<Boolean> checkPermissions =
|
||||
new MutableLiveEvent<>();
|
||||
private final MutableLiveEvent<TransportId> transportStateChanged =
|
||||
private final MutableLiveEvent<Boolean> requestBluetoothDiscoverable =
|
||||
new MutableLiveEvent<>();
|
||||
private final MutableLiveEvent<Boolean> showQrCodeFragment =
|
||||
new MutableLiveEvent<>();
|
||||
private final MutableLiveData<AddContactState> state =
|
||||
new MutableLiveData<>();
|
||||
|
||||
final QrCodeDecoder qrCodeDecoder;
|
||||
final BroadcastReceiver bluetoothReceiver = new BluetoothStateReceiver();
|
||||
|
||||
@Nullable
|
||||
private final BluetoothAdapter bt;
|
||||
@Nullable
|
||||
private final Plugin wifiPlugin, bluetoothPlugin;
|
||||
|
||||
// UiThread
|
||||
BluetoothDecision bluetoothDecision = BluetoothDecision.UNKNOWN;
|
||||
private BluetoothDecision bluetoothDecision = BluetoothDecision.UNKNOWN;
|
||||
|
||||
private boolean wasContinueClicked = false;
|
||||
private boolean isActivityResumed = false;
|
||||
|
||||
/**
|
||||
* Records whether we've enabled the wifi plugin so we don't enable it more
|
||||
@@ -166,6 +174,7 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
||||
@Inject
|
||||
AddNearbyContactViewModel(Application app,
|
||||
EventBus eventBus,
|
||||
AndroidExecutor androidExecutor,
|
||||
@IoExecutor Executor ioExecutor,
|
||||
PluginManager pluginManager,
|
||||
PayloadEncoder payloadEncoder,
|
||||
@@ -175,6 +184,7 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
||||
ConnectionManager connectionManager) {
|
||||
super(app);
|
||||
this.eventBus = eventBus;
|
||||
this.androidExecutor = androidExecutor;
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.pluginManager = pluginManager;
|
||||
this.payloadEncoder = payloadEncoder;
|
||||
@@ -185,13 +195,16 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
||||
bt = BluetoothAdapter.getDefaultAdapter();
|
||||
wifiPlugin = pluginManager.getPlugin(LanTcpConstants.ID);
|
||||
bluetoothPlugin = pluginManager.getPlugin(BluetoothConstants.ID);
|
||||
qrCodeDecoder = new QrCodeDecoder(ioExecutor, this);
|
||||
qrCodeDecoder = new QrCodeDecoder(androidExecutor, ioExecutor, this);
|
||||
eventBus.addListener(this);
|
||||
IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED);
|
||||
getApplication().registerReceiver(bluetoothReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCleared() {
|
||||
super.onCleared();
|
||||
getApplication().unregisterReceiver(bluetoothReceiver);
|
||||
eventBus.removeListener(this);
|
||||
stopListening();
|
||||
}
|
||||
@@ -201,7 +214,9 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
||||
if (bluetoothDecision == REFUSED) {
|
||||
bluetoothDecision = UNKNOWN; // Ask again
|
||||
}
|
||||
wasContinueClicked.setValue(true);
|
||||
wasContinueClicked = true;
|
||||
checkPermissions.setEvent(true);
|
||||
showQrCodeFragmentIfAllowed();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@@ -266,7 +281,7 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
||||
void startAddingContact() {
|
||||
// If we return to the intro fragment, the continue button needs to be
|
||||
// clicked again before showing the QR code fragment
|
||||
wasContinueClicked.setValue(false);
|
||||
wasContinueClicked = false;
|
||||
// If we return to the intro fragment, ask for Bluetooth
|
||||
// discoverability again before showing the QR code fragment
|
||||
bluetoothDecision = UNKNOWN;
|
||||
@@ -310,12 +325,12 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Bluetooth state changed to " + t.getState());
|
||||
}
|
||||
transportStateChanged.setEvent(t.getTransportId());
|
||||
showQrCodeFragmentIfAllowed();
|
||||
} else if (t.getTransportId().equals(LanTcpConstants.ID)) {
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info("Wifi state changed to " + t.getState());
|
||||
}
|
||||
transportStateChanged.setEvent(t.getTransportId());
|
||||
showQrCodeFragmentIfAllowed();
|
||||
}
|
||||
} else if (e instanceof KeyAgreementListeningEvent) {
|
||||
LOG.info("KeyAgreementListeningEvent received");
|
||||
@@ -344,6 +359,28 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("StatementWithEmptyBody")
|
||||
@UiThread
|
||||
void showQrCodeFragmentIfAllowed() {
|
||||
boolean permissionsGranted = areEssentialPermissionsGranted(
|
||||
getApplication(), isBluetoothSupported());
|
||||
if (isActivityResumed && wasContinueClicked && permissionsGranted) {
|
||||
if (isWifiReady() && isBluetoothReady()) {
|
||||
LOG.info("Wifi and Bluetooth are ready");
|
||||
startAddingContact();
|
||||
} else {
|
||||
enableWifiIfWeShould();
|
||||
if (bluetoothDecision == UNKNOWN) {
|
||||
requestBluetoothDiscoverable.setEvent(true);
|
||||
} else if (bluetoothDecision == REFUSED) {
|
||||
// Ask again when the user clicks "continue"
|
||||
} else {
|
||||
enableBluetoothIfWeShould();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This sets the QR code by setting the state to KeyAgreementListening.
|
||||
*/
|
||||
@@ -383,8 +420,8 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
||||
state.postValue(new AddContactState.Failed(e.isTooOld()));
|
||||
} catch (IOException | IllegalArgumentException e) {
|
||||
LOG.log(WARNING, "QR Code Invalid", e);
|
||||
Toast.makeText(getApplication(), R.string.qr_code_invalid,
|
||||
LENGTH_LONG).show();
|
||||
androidExecutor.runOnUiThread(() -> Toast.makeText(getApplication(),
|
||||
R.string.qr_code_invalid, LENGTH_LONG).show());
|
||||
resetPayloadFlags();
|
||||
state.postValue(new AddContactState.Failed());
|
||||
}
|
||||
@@ -423,6 +460,15 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
||||
});
|
||||
}
|
||||
|
||||
private class BluetoothStateReceiver extends BroadcastReceiver {
|
||||
@UiThread
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
LOG.info("Bluetooth scan mode changed");
|
||||
showQrCodeFragmentIfAllowed();
|
||||
}
|
||||
}
|
||||
|
||||
private void tryToClose(DuplexTransportConnection conn) {
|
||||
try {
|
||||
conn.getReader().dispose(true, true);
|
||||
@@ -432,16 +478,33 @@ class AddNearbyContactViewModel extends AndroidViewModel
|
||||
}
|
||||
}
|
||||
|
||||
LiveData<Boolean> getWasContinueClicked() {
|
||||
return wasContinueClicked;
|
||||
/**
|
||||
* Set to true in onPostResume() and false in onPause(). This prevents the
|
||||
* QR code fragment from being shown if onRequestPermissionsResult() is
|
||||
* called while the activity is paused, which could cause a crash due to
|
||||
* https://issuetracker.google.com/issues/37067655.
|
||||
* TODO check if this is still happening when using new permission requesting
|
||||
*/
|
||||
@UiThread
|
||||
void setIsActivityResumed(boolean resumed) {
|
||||
isActivityResumed = resumed;
|
||||
// Workaround for
|
||||
// https://code.google.com/p/android/issues/detail?id=190966
|
||||
showQrCodeFragmentIfAllowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives an event when the transport state of the WiFi or Bluetooth
|
||||
* plugins changes.
|
||||
*/
|
||||
LiveEvent<TransportId> getTransportStateChanged() {
|
||||
return transportStateChanged;
|
||||
@UiThread
|
||||
void setBluetoothDecision(BluetoothDecision decision) {
|
||||
bluetoothDecision = decision;
|
||||
showQrCodeFragmentIfAllowed();
|
||||
}
|
||||
|
||||
LiveEvent<Boolean> getCheckPermissions() {
|
||||
return checkPermissions;
|
||||
}
|
||||
|
||||
LiveEvent<Boolean> getRequestBluetoothDiscoverable() {
|
||||
return requestBluetoothDiscoverable;
|
||||
}
|
||||
|
||||
LiveEvent<Boolean> getShowQrCodeFragment() {
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
@@ -35,6 +36,7 @@ class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
|
||||
|
||||
private static final Logger LOG = getLogger(QrCodeDecoder.class.getName());
|
||||
|
||||
private final AndroidExecutor androidExecutor;
|
||||
private final Executor ioExecutor;
|
||||
private final Reader reader = new QRCodeReader();
|
||||
private final ResultCallback callback;
|
||||
@@ -42,7 +44,9 @@ class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
|
||||
private Camera camera = null;
|
||||
private int cameraIndex = 0;
|
||||
|
||||
QrCodeDecoder(@IoExecutor Executor ioExecutor, ResultCallback callback) {
|
||||
QrCodeDecoder(AndroidExecutor androidExecutor,
|
||||
@IoExecutor Executor ioExecutor, ResultCallback callback) {
|
||||
this.androidExecutor = androidExecutor;
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.callback = callback;
|
||||
}
|
||||
@@ -104,9 +108,9 @@ class QrCodeDecoder implements PreviewConsumer, PreviewCallback {
|
||||
LOG.warning("Invalid preview frame");
|
||||
} finally {
|
||||
reader.reset();
|
||||
androidExecutor.runOnUiThread(this::askForPreviewFrame);
|
||||
}
|
||||
});
|
||||
askForPreviewFrame();
|
||||
}
|
||||
|
||||
private static BinaryBitmap binarize(byte[] data, int width, int height,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.briarproject.briar.android.util;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import androidx.activity.result.contract.ActivityResultContract;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import static android.app.Activity.RESULT_CANCELED;
|
||||
import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
|
||||
import static android.bluetooth.BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION;
|
||||
|
||||
@NotNullByDefault
|
||||
public class RequestBluetoothDiscoverable
|
||||
extends ActivityResultContract<Integer, Boolean> {
|
||||
|
||||
@Override
|
||||
public Intent createIntent(Context context, Integer duration) {
|
||||
Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
|
||||
i.putExtra(EXTRA_DISCOVERABLE_DURATION, duration);
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean parseResult(int resultCode, @Nullable Intent intent) {
|
||||
return resultCode != RESULT_CANCELED;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".android.contact.add.nearby.KeyAgreementActivity">
|
||||
tools:context=".android.contact.add.nearby.AddNearbyContactActivity">
|
||||
|
||||
<include layout="@layout/toolbar" />
|
||||
|
||||
|
||||
Reference in New Issue
Block a user