mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 12:49:55 +01:00
Move Plugin related code from activity to ViewModel
This commit is contained in:
@@ -21,6 +21,11 @@ import org.briarproject.briar.android.blog.RssFeedImportActivity;
|
|||||||
import org.briarproject.briar.android.blog.RssFeedManageActivity;
|
import org.briarproject.briar.android.blog.RssFeedManageActivity;
|
||||||
import org.briarproject.briar.android.blog.WriteBlogPostActivity;
|
import org.briarproject.briar.android.blog.WriteBlogPostActivity;
|
||||||
import org.briarproject.briar.android.contact.ContactListFragment;
|
import org.briarproject.briar.android.contact.ContactListFragment;
|
||||||
|
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeActivity;
|
||||||
|
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeErrorFragment;
|
||||||
|
import org.briarproject.briar.android.contact.add.nearby.IntroFragment;
|
||||||
|
import org.briarproject.briar.android.contact.add.nearby.KeyAgreementActivity;
|
||||||
|
import org.briarproject.briar.android.contact.add.nearby.KeyAgreementFragment;
|
||||||
import org.briarproject.briar.android.contact.add.remote.AddContactActivity;
|
import org.briarproject.briar.android.contact.add.remote.AddContactActivity;
|
||||||
import org.briarproject.briar.android.contact.add.remote.LinkExchangeFragment;
|
import org.briarproject.briar.android.contact.add.remote.LinkExchangeFragment;
|
||||||
import org.briarproject.briar.android.contact.add.remote.NicknameFragment;
|
import org.briarproject.briar.android.contact.add.remote.NicknameFragment;
|
||||||
@@ -36,10 +41,6 @@ import org.briarproject.briar.android.fragment.ScreenFilterDialogFragment;
|
|||||||
import org.briarproject.briar.android.introduction.ContactChooserFragment;
|
import org.briarproject.briar.android.introduction.ContactChooserFragment;
|
||||||
import org.briarproject.briar.android.introduction.IntroductionActivity;
|
import org.briarproject.briar.android.introduction.IntroductionActivity;
|
||||||
import org.briarproject.briar.android.introduction.IntroductionMessageFragment;
|
import org.briarproject.briar.android.introduction.IntroductionMessageFragment;
|
||||||
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeActivity;
|
|
||||||
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeErrorFragment;
|
|
||||||
import org.briarproject.briar.android.contact.add.nearby.KeyAgreementActivity;
|
|
||||||
import org.briarproject.briar.android.contact.add.nearby.KeyAgreementFragment;
|
|
||||||
import org.briarproject.briar.android.login.ChangePasswordActivity;
|
import org.briarproject.briar.android.login.ChangePasswordActivity;
|
||||||
import org.briarproject.briar.android.login.OpenDatabaseFragment;
|
import org.briarproject.briar.android.login.OpenDatabaseFragment;
|
||||||
import org.briarproject.briar.android.login.PasswordFragment;
|
import org.briarproject.briar.android.login.PasswordFragment;
|
||||||
@@ -208,6 +209,8 @@ public interface ActivityComponent {
|
|||||||
|
|
||||||
void inject(FeedFragment fragment);
|
void inject(FeedFragment fragment);
|
||||||
|
|
||||||
|
void inject(IntroFragment fragment);
|
||||||
|
|
||||||
void inject(KeyAgreementFragment fragment);
|
void inject(KeyAgreementFragment fragment);
|
||||||
|
|
||||||
void inject(LinkExchangeFragment fragment);
|
void inject(LinkExchangeFragment fragment);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.briarproject.briar.android.contact.add.nearby;
|
package org.briarproject.briar.android.contact.add.nearby;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
@@ -30,8 +31,14 @@ import org.briarproject.bramble.api.keyagreement.event.KeyAgreementStartedEvent;
|
|||||||
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementWaitingEvent;
|
import org.briarproject.bramble.api.keyagreement.event.KeyAgreementWaitingEvent;
|
||||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||||
|
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||||
|
import org.briarproject.bramble.api.plugin.Plugin;
|
||||||
|
import org.briarproject.bramble.api.plugin.Plugin.State;
|
||||||
|
import org.briarproject.bramble.api.plugin.PluginManager;
|
||||||
import org.briarproject.bramble.api.plugin.TransportId;
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||||
|
import org.briarproject.bramble.api.plugin.event.TransportStateEvent;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.ContactExchangeFinished;
|
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.ContactExchangeFinished;
|
||||||
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.ContactExchangeStarted;
|
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.ContactExchangeStarted;
|
||||||
@@ -40,6 +47,8 @@ import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.KeyA
|
|||||||
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.KeyAgreementWaiting;
|
import org.briarproject.briar.android.contact.add.nearby.ContactAddingState.KeyAgreementWaiting;
|
||||||
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeResult.Error;
|
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeResult.Error;
|
||||||
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeResult.Success;
|
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeResult.Success;
|
||||||
|
import org.briarproject.briar.android.viewmodel.LiveEvent;
|
||||||
|
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
@@ -55,12 +64,19 @@ import androidx.lifecycle.AndroidViewModel;
|
|||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
||||||
import static android.widget.Toast.LENGTH_LONG;
|
import static android.widget.Toast.LENGTH_LONG;
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
|
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
||||||
|
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.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.briar.android.contact.add.nearby.ContactExchangeViewModel.BluetoothDecision.REFUSED;
|
||||||
|
import static org.briarproject.briar.android.contact.add.nearby.ContactExchangeViewModel.BluetoothDecision.UNKNOWN;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class ContactExchangeViewModel extends AndroidViewModel
|
class ContactExchangeViewModel extends AndroidViewModel
|
||||||
@@ -69,22 +85,80 @@ class ContactExchangeViewModel extends AndroidViewModel
|
|||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
getLogger(ContactExchangeViewModel.class.getName());
|
getLogger(ContactExchangeViewModel.class.getName());
|
||||||
|
|
||||||
|
enum BluetoothDecision {
|
||||||
|
/**
|
||||||
|
* We haven't asked the user about Bluetooth discoverability.
|
||||||
|
*/
|
||||||
|
UNKNOWN,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The device doesn't have a Bluetooth adapter.
|
||||||
|
*/
|
||||||
|
NO_ADAPTER,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We're waiting for the user to accept or refuse discoverability.
|
||||||
|
*/
|
||||||
|
WAITING,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user has accepted discoverability.
|
||||||
|
*/
|
||||||
|
ACCEPTED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user has refused discoverability.
|
||||||
|
*/
|
||||||
|
REFUSED
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("CharsetObjectCanBeUsed") // Requires minSdkVersion >= 19
|
@SuppressWarnings("CharsetObjectCanBeUsed") // Requires minSdkVersion >= 19
|
||||||
private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
|
private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
|
||||||
|
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
private final Executor ioExecutor;
|
private final Executor ioExecutor;
|
||||||
|
private final PluginManager pluginManager;
|
||||||
private final PayloadEncoder payloadEncoder;
|
private final PayloadEncoder payloadEncoder;
|
||||||
private final PayloadParser payloadParser;
|
private final PayloadParser payloadParser;
|
||||||
private final Provider<KeyAgreementTask> keyAgreementTaskProvider;
|
private final Provider<KeyAgreementTask> keyAgreementTaskProvider;
|
||||||
private final ContactExchangeManager contactExchangeManager;
|
private final ContactExchangeManager contactExchangeManager;
|
||||||
private final ConnectionManager connectionManager;
|
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 =
|
||||||
|
new MutableLiveEvent<>();
|
||||||
|
private final MutableLiveEvent<TransportId> transportStateChanged =
|
||||||
|
new MutableLiveEvent<>();
|
||||||
private final MutableLiveData<ContactAddingState> state =
|
private final MutableLiveData<ContactAddingState> state =
|
||||||
new MutableLiveData<>();
|
new MutableLiveData<>();
|
||||||
|
|
||||||
final QrCodeDecoder qrCodeDecoder;
|
final QrCodeDecoder qrCodeDecoder;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final BluetoothAdapter bt;
|
||||||
|
@Nullable
|
||||||
|
private final Plugin wifiPlugin, bluetoothPlugin;
|
||||||
|
// UiThread
|
||||||
|
BluetoothDecision bluetoothDecision = BluetoothDecision.UNKNOWN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records whether we've enabled the wifi plugin so we don't enable it more
|
||||||
|
* than once.
|
||||||
|
*/
|
||||||
|
private boolean hasEnabledWifi = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records whether we've enabled the Bluetooth plugin so we don't enable it
|
||||||
|
* more than once.
|
||||||
|
*/
|
||||||
|
private boolean hasEnabledBluetooth = false;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private KeyAgreementTask task;
|
private KeyAgreementTask task;
|
||||||
private volatile boolean gotLocalPayload = false, gotRemotePayload = false;
|
private volatile boolean gotLocalPayload = false, gotRemotePayload = false;
|
||||||
@@ -93,6 +167,7 @@ class ContactExchangeViewModel extends AndroidViewModel
|
|||||||
ContactExchangeViewModel(Application app,
|
ContactExchangeViewModel(Application app,
|
||||||
EventBus eventBus,
|
EventBus eventBus,
|
||||||
@IoExecutor Executor ioExecutor,
|
@IoExecutor Executor ioExecutor,
|
||||||
|
PluginManager pluginManager,
|
||||||
PayloadEncoder payloadEncoder,
|
PayloadEncoder payloadEncoder,
|
||||||
PayloadParser payloadParser,
|
PayloadParser payloadParser,
|
||||||
Provider<KeyAgreementTask> keyAgreementTaskProvider,
|
Provider<KeyAgreementTask> keyAgreementTaskProvider,
|
||||||
@@ -101,11 +176,15 @@ class ContactExchangeViewModel extends AndroidViewModel
|
|||||||
super(app);
|
super(app);
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
|
this.pluginManager = pluginManager;
|
||||||
this.payloadEncoder = payloadEncoder;
|
this.payloadEncoder = payloadEncoder;
|
||||||
this.payloadParser = payloadParser;
|
this.payloadParser = payloadParser;
|
||||||
this.keyAgreementTaskProvider = keyAgreementTaskProvider;
|
this.keyAgreementTaskProvider = keyAgreementTaskProvider;
|
||||||
this.contactExchangeManager = contactExchangeManager;
|
this.contactExchangeManager = contactExchangeManager;
|
||||||
this.connectionManager = connectionManager;
|
this.connectionManager = connectionManager;
|
||||||
|
bt = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
wifiPlugin = pluginManager.getPlugin(LanTcpConstants.ID);
|
||||||
|
bluetoothPlugin = pluginManager.getPlugin(BluetoothConstants.ID);
|
||||||
qrCodeDecoder = new QrCodeDecoder(ioExecutor, this);
|
qrCodeDecoder = new QrCodeDecoder(ioExecutor, this);
|
||||||
eventBus.addListener(this);
|
eventBus.addListener(this);
|
||||||
}
|
}
|
||||||
@@ -117,12 +196,95 @@ class ContactExchangeViewModel extends AndroidViewModel
|
|||||||
stopListening();
|
stopListening();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
void onContinueClicked() {
|
||||||
|
if (bluetoothDecision == REFUSED) {
|
||||||
|
bluetoothDecision = UNKNOWN; // Ask again
|
||||||
|
}
|
||||||
|
wasContinueClicked.setValue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
boolean isBluetoothSupported() {
|
||||||
|
return bt != null && bluetoothPlugin != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
boolean isWifiReady() {
|
||||||
|
if (wifiPlugin == null) return true; // Continue without wifi
|
||||||
|
State state = wifiPlugin.getState();
|
||||||
|
// Wait for plugin to become enabled
|
||||||
|
return state == ACTIVE || state == INACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
boolean isBluetoothReady() {
|
||||||
|
if (bt == null || bluetoothPlugin == null) {
|
||||||
|
// Continue without Bluetooth
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (bluetoothDecision == BluetoothDecision.UNKNOWN ||
|
||||||
|
bluetoothDecision == BluetoothDecision.WAITING ||
|
||||||
|
bluetoothDecision == BluetoothDecision.REFUSED) {
|
||||||
|
// Wait for user to accept
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bt.getScanMode() != SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
|
||||||
|
// Wait for adapter to become discoverable
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Wait for plugin to become active
|
||||||
|
return bluetoothPlugin.getState() == ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
void enableWifiIfWeShould() {
|
||||||
|
if (hasEnabledWifi) return;
|
||||||
|
if (wifiPlugin == null) return;
|
||||||
|
State state = wifiPlugin.getState();
|
||||||
|
if (state == STARTING_STOPPING || state == DISABLED) {
|
||||||
|
LOG.info("Enabling wifi plugin");
|
||||||
|
hasEnabledWifi = true;
|
||||||
|
pluginManager.setPluginEnabled(LanTcpConstants.ID, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
void enableBluetoothIfWeShould() {
|
||||||
|
if (bluetoothDecision != BluetoothDecision.ACCEPTED) return;
|
||||||
|
if (hasEnabledBluetooth) return;
|
||||||
|
if (bluetoothPlugin == null || !isBluetoothSupported()) return;
|
||||||
|
State state = bluetoothPlugin.getState();
|
||||||
|
if (state == STARTING_STOPPING || state == DISABLED) {
|
||||||
|
LOG.info("Enabling Bluetooth plugin");
|
||||||
|
hasEnabledBluetooth = true;
|
||||||
|
pluginManager.setPluginEnabled(BluetoothConstants.ID, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
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);
|
||||||
|
// If we return to the intro fragment, ask for Bluetooth
|
||||||
|
// discoverability again before showing the QR code fragment
|
||||||
|
bluetoothDecision = UNKNOWN;
|
||||||
|
// If we return to the intro fragment, we may need to enable wifi and
|
||||||
|
// Bluetooth again
|
||||||
|
hasEnabledWifi = false;
|
||||||
|
hasEnabledBluetooth = false;
|
||||||
|
// start to listen with a KeyAgreementTask
|
||||||
|
startListening();
|
||||||
|
showQrCodeFragment.setEvent(true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this once Bluetooth and Wi-Fi are ready to be used.
|
* Call this once Bluetooth and Wi-Fi are ready to be used.
|
||||||
* It is possible to call this more than once over the ViewModel's lifetime.
|
* It is possible to call this more than once over the ViewModel's lifetime.
|
||||||
*/
|
*/
|
||||||
@UiThread
|
@UiThread
|
||||||
void startListening() {
|
private void startListening() {
|
||||||
KeyAgreementTask oldTask = task;
|
KeyAgreementTask oldTask = task;
|
||||||
KeyAgreementTask newTask = keyAgreementTaskProvider.get();
|
KeyAgreementTask newTask = keyAgreementTaskProvider.get();
|
||||||
task = newTask;
|
task = newTask;
|
||||||
@@ -142,7 +304,20 @@ class ContactExchangeViewModel extends AndroidViewModel
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void eventOccurred(Event e) {
|
public void eventOccurred(Event e) {
|
||||||
if (e instanceof KeyAgreementListeningEvent) {
|
if (e instanceof TransportStateEvent) {
|
||||||
|
TransportStateEvent t = (TransportStateEvent) e;
|
||||||
|
if (t.getTransportId().equals(BluetoothConstants.ID)) {
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("Bluetooth state changed to " + t.getState());
|
||||||
|
}
|
||||||
|
transportStateChanged.setEvent(t.getTransportId());
|
||||||
|
} else if (t.getTransportId().equals(LanTcpConstants.ID)) {
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("Wifi state changed to " + t.getState());
|
||||||
|
}
|
||||||
|
transportStateChanged.setEvent(t.getTransportId());
|
||||||
|
}
|
||||||
|
} else if (e instanceof KeyAgreementListeningEvent) {
|
||||||
LOG.info("KeyAgreementListeningEvent received");
|
LOG.info("KeyAgreementListeningEvent received");
|
||||||
KeyAgreementListeningEvent event = (KeyAgreementListeningEvent) e;
|
KeyAgreementListeningEvent event = (KeyAgreementListeningEvent) e;
|
||||||
onLocalPayloadReceived(event.getLocalPayload());
|
onLocalPayloadReceived(event.getLocalPayload());
|
||||||
@@ -257,6 +432,22 @@ class ContactExchangeViewModel extends AndroidViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LiveData<Boolean> getWasContinueClicked() {
|
||||||
|
return wasContinueClicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives an event when the transport state of the WiFi or Bluetooth
|
||||||
|
* plugins changes.
|
||||||
|
*/
|
||||||
|
LiveEvent<TransportId> getTransportStateChanged() {
|
||||||
|
return transportStateChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveEvent<Boolean> getShowQrCodeFragment() {
|
||||||
|
return showQrCodeFragment;
|
||||||
|
}
|
||||||
|
|
||||||
LiveData<ContactAddingState> getState() {
|
LiveData<ContactAddingState> getState() {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.briar.android.contact.add.nearby;
|
package org.briarproject.briar.android.contact.add.nearby;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -10,9 +9,13 @@ import android.widget.ScrollView;
|
|||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
import static android.view.View.FOCUS_DOWN;
|
import static android.view.View.FOCUS_DOWN;
|
||||||
|
|
||||||
@@ -20,33 +23,27 @@ import static android.view.View.FOCUS_DOWN;
|
|||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class IntroFragment extends BaseFragment {
|
public class IntroFragment extends BaseFragment {
|
||||||
|
|
||||||
interface IntroScreenSeenListener {
|
|
||||||
void showNextScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String TAG = IntroFragment.class.getName();
|
public static final String TAG = IntroFragment.class.getName();
|
||||||
|
|
||||||
private IntroScreenSeenListener screenSeenListener;
|
@Inject
|
||||||
|
ViewModelProvider.Factory viewModelFactory;
|
||||||
|
|
||||||
|
private ContactExchangeViewModel viewModel;
|
||||||
|
|
||||||
private ScrollView scrollView;
|
private ScrollView scrollView;
|
||||||
|
|
||||||
public static IntroFragment newInstance() {
|
public static IntroFragment newInstance() {
|
||||||
|
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
|
|
||||||
IntroFragment fragment = new IntroFragment();
|
IntroFragment fragment = new IntroFragment();
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(Context context) {
|
public void injectFragment(ActivityComponent component) {
|
||||||
super.onAttach(context);
|
component.inject(this);
|
||||||
screenSeenListener = (IntroScreenSeenListener) context;
|
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
|
||||||
}
|
.get(ContactExchangeViewModel.class);
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUniqueTag() {
|
|
||||||
return TAG;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -59,7 +56,7 @@ public class IntroFragment extends BaseFragment {
|
|||||||
false);
|
false);
|
||||||
scrollView = v.findViewById(R.id.scrollView);
|
scrollView = v.findViewById(R.id.scrollView);
|
||||||
View button = v.findViewById(R.id.continueButton);
|
View button = v.findViewById(R.id.continueButton);
|
||||||
button.setOnClickListener(view -> screenSeenListener.showNextScreen());
|
button.setOnClickListener(view -> viewModel.onContinueClicked());
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,4 +66,9 @@ public class IntroFragment extends BaseFragment {
|
|||||||
scrollView.post(() -> scrollView.fullScroll(FOCUS_DOWN));
|
scrollView.post(() -> scrollView.fullScroll(FOCUS_DOWN));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUniqueTag() {
|
||||||
|
return TAG;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.briar.android.contact.add.nearby;
|
package org.briarproject.briar.android.contact.add.nearby;
|
||||||
|
|
||||||
import android.bluetooth.BluetoothAdapter;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -8,21 +7,12 @@ import android.content.IntentFilter;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.event.Event;
|
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
|
||||||
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
|
||||||
import org.briarproject.bramble.api.plugin.Plugin;
|
|
||||||
import org.briarproject.bramble.api.plugin.Plugin.State;
|
|
||||||
import org.briarproject.bramble.api.plugin.PluginManager;
|
|
||||||
import org.briarproject.bramble.api.plugin.event.TransportStateEvent;
|
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
import org.briarproject.briar.android.contact.add.nearby.IntroFragment.IntroScreenSeenListener;
|
import org.briarproject.briar.android.contact.add.nearby.ContactExchangeViewModel.BluetoothDecision;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
|
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
|
||||||
|
|
||||||
@@ -43,51 +33,21 @@ import static android.Manifest.permission.ACCESS_FINE_LOCATION;
|
|||||||
import static android.Manifest.permission.CAMERA;
|
import static android.Manifest.permission.CAMERA;
|
||||||
import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
|
import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
|
||||||
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
|
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
|
||||||
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
|
||||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
import static java.util.logging.Level.INFO;
|
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
|
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
|
||||||
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
|
|
||||||
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.briar.android.activity.RequestCodes.REQUEST_BLUETOOTH_DISCOVERABLE;
|
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_BLUETOOTH_DISCOVERABLE;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA_LOCATION;
|
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA_LOCATION;
|
||||||
|
import static org.briarproject.briar.android.contact.add.nearby.ContactExchangeViewModel.BluetoothDecision.ACCEPTED;
|
||||||
|
import static org.briarproject.briar.android.contact.add.nearby.ContactExchangeViewModel.BluetoothDecision.REFUSED;
|
||||||
|
import static org.briarproject.briar.android.contact.add.nearby.ContactExchangeViewModel.BluetoothDecision.UNKNOWN;
|
||||||
import static org.briarproject.briar.android.util.UiUtils.getGoToSettingsListener;
|
import static org.briarproject.briar.android.util.UiUtils.getGoToSettingsListener;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public abstract class KeyAgreementActivity extends BriarActivity implements
|
public abstract class KeyAgreementActivity extends BriarActivity
|
||||||
BaseFragmentListener, IntroScreenSeenListener, EventListener {
|
implements BaseFragmentListener {
|
||||||
|
|
||||||
private enum BluetoothDecision {
|
|
||||||
/**
|
|
||||||
* We haven't asked the user about Bluetooth discoverability.
|
|
||||||
*/
|
|
||||||
UNKNOWN,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The device doesn't have a Bluetooth adapter.
|
|
||||||
*/
|
|
||||||
NO_ADAPTER,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We're waiting for the user to accept or refuse discoverability.
|
|
||||||
*/
|
|
||||||
WAITING,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user has accepted discoverability.
|
|
||||||
*/
|
|
||||||
ACCEPTED,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user has refused discoverability.
|
|
||||||
*/
|
|
||||||
REFUSED
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum Permission {
|
private enum Permission {
|
||||||
UNKNOWN, GRANTED, SHOW_RATIONALE, PERMANENTLY_DENIED
|
UNKNOWN, GRANTED, SHOW_RATIONALE, PERMANENTLY_DENIED
|
||||||
@@ -96,16 +56,9 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
getLogger(KeyAgreementActivity.class.getName());
|
getLogger(KeyAgreementActivity.class.getName());
|
||||||
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ViewModelProvider.Factory viewModelFactory;
|
ViewModelProvider.Factory viewModelFactory;
|
||||||
|
|
||||||
@Inject
|
|
||||||
EventBus eventBus;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
PluginManager pluginManager;
|
|
||||||
|
|
||||||
protected ContactExchangeViewModel viewModel;
|
protected ContactExchangeViewModel viewModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -116,31 +69,9 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
*/
|
*/
|
||||||
private boolean isResumed = false;
|
private boolean isResumed = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 boolean continueClicked = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Records whether we've enabled the wifi plugin so we don't enable it more
|
|
||||||
* than once.
|
|
||||||
*/
|
|
||||||
private boolean hasEnabledWifi = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Records whether we've enabled the Bluetooth plugin so we don't enable it
|
|
||||||
* more than once.
|
|
||||||
*/
|
|
||||||
private boolean hasEnabledBluetooth = false;
|
|
||||||
|
|
||||||
private Permission cameraPermission = Permission.UNKNOWN;
|
private Permission cameraPermission = Permission.UNKNOWN;
|
||||||
private Permission locationPermission = Permission.UNKNOWN;
|
private Permission locationPermission = Permission.UNKNOWN;
|
||||||
private BluetoothDecision bluetoothDecision = BluetoothDecision.UNKNOWN;
|
|
||||||
private BroadcastReceiver bluetoothReceiver = null;
|
private BroadcastReceiver bluetoothReceiver = null;
|
||||||
private Plugin wifiPlugin = null, bluetoothPlugin = null;
|
|
||||||
private BluetoothAdapter bt = null;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectActivity(ActivityComponent component) {
|
public void injectActivity(ActivityComponent component) {
|
||||||
@@ -162,9 +93,42 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED);
|
IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED);
|
||||||
bluetoothReceiver = new BluetoothStateReceiver();
|
bluetoothReceiver = new BluetoothStateReceiver();
|
||||||
registerReceiver(bluetoothReceiver, filter);
|
registerReceiver(bluetoothReceiver, filter);
|
||||||
wifiPlugin = pluginManager.getPlugin(LanTcpConstants.ID);
|
viewModel.getWasContinueClicked().observe(this, clicked -> {
|
||||||
bluetoothPlugin = pluginManager.getPlugin(BluetoothConstants.ID);
|
if (clicked && checkPermissions()) showQrCodeFragmentIfAllowed();
|
||||||
bt = BluetoothAdapter.getDefaultAdapter();
|
});
|
||||||
|
viewModel.getTransportStateChanged().observeEvent(this,
|
||||||
|
t -> showQrCodeFragmentIfAllowed());
|
||||||
|
viewModel.getShowQrCodeFragment().observeEvent(this, show -> {
|
||||||
|
if (show) showQrCodeFragment();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
// Permissions may have been granted manually while we were stopped
|
||||||
|
cameraPermission = Permission.UNKNOWN;
|
||||||
|
locationPermission = Permission.UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostResume() {
|
||||||
|
super.onPostResume();
|
||||||
|
isResumed = true;
|
||||||
|
// Workaround for
|
||||||
|
// https://code.google.com/p/android/issues/detail?id=190966
|
||||||
|
showQrCodeFragmentIfAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
isResumed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
super.onStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -182,45 +146,22 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStart() {
|
|
||||||
super.onStart();
|
|
||||||
eventBus.addListener(this);
|
|
||||||
// Permissions may have been granted manually while we were stopped
|
|
||||||
cameraPermission = Permission.UNKNOWN;
|
|
||||||
locationPermission = Permission.UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostResume() {
|
|
||||||
super.onPostResume();
|
|
||||||
isResumed = true;
|
|
||||||
// Workaround for
|
|
||||||
// https://code.google.com/p/android/issues/detail?id=190966
|
|
||||||
showQrCodeFragmentIfAllowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("StatementWithEmptyBody")
|
@SuppressWarnings("StatementWithEmptyBody")
|
||||||
private void showQrCodeFragmentIfAllowed() {
|
private void showQrCodeFragmentIfAllowed() {
|
||||||
|
boolean continueClicked = // never set to null
|
||||||
|
requireNonNull(viewModel.getWasContinueClicked().getValue());
|
||||||
if (isResumed && continueClicked && areEssentialPermissionsGranted()) {
|
if (isResumed && continueClicked && areEssentialPermissionsGranted()) {
|
||||||
if (isWifiReady() && isBluetoothReady()) {
|
if (viewModel.isWifiReady() && viewModel.isBluetoothReady()) {
|
||||||
LOG.info("Wifi and Bluetooth are ready");
|
LOG.info("Wifi and Bluetooth are ready");
|
||||||
viewModel.startListening();
|
viewModel.startAddingContact();
|
||||||
showQrCodeFragment();
|
|
||||||
} else {
|
} else {
|
||||||
if (shouldEnableWifi()) {
|
viewModel.enableWifiIfWeShould();
|
||||||
LOG.info("Enabling wifi plugin");
|
if (viewModel.bluetoothDecision == UNKNOWN) {
|
||||||
hasEnabledWifi = true;
|
|
||||||
pluginManager.setPluginEnabled(LanTcpConstants.ID, true);
|
|
||||||
}
|
|
||||||
if (bluetoothDecision == BluetoothDecision.UNKNOWN) {
|
|
||||||
requestBluetoothDiscoverable();
|
requestBluetoothDiscoverable();
|
||||||
} else if (bluetoothDecision == BluetoothDecision.REFUSED) {
|
} else if (viewModel.bluetoothDecision == REFUSED) {
|
||||||
// Ask again when the user clicks "continue"
|
// Ask again when the user clicks "continue"
|
||||||
} else if (shouldEnableBluetooth()) {
|
} else {
|
||||||
LOG.info("Enabling Bluetooth plugin");
|
viewModel.enableBluetoothIfWeShould();
|
||||||
hasEnabledBluetooth = true;
|
|
||||||
pluginManager.setPluginEnabled(BluetoothConstants.ID, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -229,119 +170,42 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
private boolean areEssentialPermissionsGranted() {
|
private boolean areEssentialPermissionsGranted() {
|
||||||
return cameraPermission == Permission.GRANTED &&
|
return cameraPermission == Permission.GRANTED &&
|
||||||
(SDK_INT < 23 || locationPermission == Permission.GRANTED ||
|
(SDK_INT < 23 || locationPermission == Permission.GRANTED ||
|
||||||
!isBluetoothSupported());
|
!viewModel.isBluetoothSupported());
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isBluetoothSupported() {
|
|
||||||
return bt != null && bluetoothPlugin != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isWifiReady() {
|
|
||||||
if (wifiPlugin == null) return true; // Continue without wifi
|
|
||||||
State state = wifiPlugin.getState();
|
|
||||||
// Wait for plugin to become enabled
|
|
||||||
return state == ACTIVE || state == INACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isBluetoothReady() {
|
|
||||||
if (!isBluetoothSupported()) {
|
|
||||||
// Continue without Bluetooth
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (bluetoothDecision == BluetoothDecision.UNKNOWN ||
|
|
||||||
bluetoothDecision == BluetoothDecision.WAITING ||
|
|
||||||
bluetoothDecision == BluetoothDecision.REFUSED) {
|
|
||||||
// Wait for user to accept
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (bt.getScanMode() != SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
|
|
||||||
// Wait for adapter to become discoverable
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Wait for plugin to become active
|
|
||||||
return bluetoothPlugin.getState() == ACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean shouldEnableWifi() {
|
|
||||||
if (hasEnabledWifi) return false;
|
|
||||||
if (wifiPlugin == null) return false;
|
|
||||||
State state = wifiPlugin.getState();
|
|
||||||
return state == STARTING_STOPPING || state == DISABLED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requestBluetoothDiscoverable() {
|
private void requestBluetoothDiscoverable() {
|
||||||
if (!isBluetoothSupported()) {
|
if (!viewModel.isBluetoothSupported()) {
|
||||||
bluetoothDecision = BluetoothDecision.NO_ADAPTER;
|
viewModel.bluetoothDecision = BluetoothDecision.NO_ADAPTER;
|
||||||
showQrCodeFragmentIfAllowed();
|
showQrCodeFragmentIfAllowed();
|
||||||
} else {
|
} else {
|
||||||
Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
|
Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
|
||||||
if (i.resolveActivity(getPackageManager()) != null) {
|
if (i.resolveActivity(getPackageManager()) != null) {
|
||||||
LOG.info("Asking for Bluetooth discoverability");
|
LOG.info("Asking for Bluetooth discoverability");
|
||||||
bluetoothDecision = BluetoothDecision.WAITING;
|
viewModel.bluetoothDecision = BluetoothDecision.WAITING;
|
||||||
startActivityForResult(i, REQUEST_BLUETOOTH_DISCOVERABLE);
|
startActivityForResult(i, REQUEST_BLUETOOTH_DISCOVERABLE);
|
||||||
} else {
|
} else {
|
||||||
bluetoothDecision = BluetoothDecision.NO_ADAPTER;
|
viewModel.bluetoothDecision = BluetoothDecision.NO_ADAPTER;
|
||||||
showQrCodeFragmentIfAllowed();
|
showQrCodeFragmentIfAllowed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldEnableBluetooth() {
|
|
||||||
if (bluetoothDecision != BluetoothDecision.ACCEPTED) return false;
|
|
||||||
if (hasEnabledBluetooth) return false;
|
|
||||||
if (!isBluetoothSupported()) return false;
|
|
||||||
State state = bluetoothPlugin.getState();
|
|
||||||
return state == STARTING_STOPPING || state == DISABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
isResumed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onStop() {
|
|
||||||
super.onStop();
|
|
||||||
eventBus.removeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showNextScreen() {
|
|
||||||
continueClicked = true;
|
|
||||||
if (bluetoothDecision == BluetoothDecision.REFUSED) {
|
|
||||||
bluetoothDecision = BluetoothDecision.UNKNOWN; // Ask again
|
|
||||||
}
|
|
||||||
if (checkPermissions()) showQrCodeFragmentIfAllowed();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int request, int result,
|
public void onActivityResult(int request, int result,
|
||||||
@Nullable Intent data) {
|
@Nullable Intent data) {
|
||||||
if (request == REQUEST_BLUETOOTH_DISCOVERABLE) {
|
if (request == REQUEST_BLUETOOTH_DISCOVERABLE) {
|
||||||
if (result == RESULT_CANCELED) {
|
if (result == RESULT_CANCELED) {
|
||||||
LOG.info("Bluetooth discoverability was refused");
|
LOG.info("Bluetooth discoverability was refused");
|
||||||
bluetoothDecision = BluetoothDecision.REFUSED;
|
viewModel.bluetoothDecision = REFUSED;
|
||||||
} else {
|
} else {
|
||||||
LOG.info("Bluetooth discoverability was accepted");
|
LOG.info("Bluetooth discoverability was accepted");
|
||||||
bluetoothDecision = BluetoothDecision.ACCEPTED;
|
viewModel.bluetoothDecision = ACCEPTED;
|
||||||
}
|
}
|
||||||
showQrCodeFragmentIfAllowed();
|
showQrCodeFragmentIfAllowed();
|
||||||
} else super.onActivityResult(request, result, data);
|
} else super.onActivityResult(request, result, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showQrCodeFragment() {
|
private void showQrCodeFragment() {
|
||||||
// If we return to the intro fragment, the continue button needs to be
|
|
||||||
// clicked again before showing the QR code fragment
|
|
||||||
continueClicked = false;
|
|
||||||
// If we return to the intro fragment, ask for Bluetooth
|
|
||||||
// discoverability again before showing the QR code fragment
|
|
||||||
bluetoothDecision = BluetoothDecision.UNKNOWN;
|
|
||||||
// If we return to the intro fragment, we may need to enable wifi and
|
|
||||||
// Bluetooth again
|
|
||||||
hasEnabledWifi = false;
|
|
||||||
hasEnabledBluetooth = false;
|
|
||||||
|
|
||||||
// FIXME #824
|
// FIXME #824
|
||||||
FragmentManager fm = getSupportFragmentManager();
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
if (fm.findFragmentByTag(KeyAgreementFragment.TAG) == null) {
|
if (fm.findFragmentByTag(KeyAgreementFragment.TAG) == null) {
|
||||||
@@ -362,7 +226,7 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
R.string.permission_camera_denied_body);
|
R.string.permission_camera_denied_body);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (isBluetoothSupported() &&
|
if (viewModel.isBluetoothSupported() &&
|
||||||
locationPermission == Permission.PERMANENTLY_DENIED) {
|
locationPermission == Permission.PERMANENTLY_DENIED) {
|
||||||
showDenialDialog(R.string.permission_location_title,
|
showDenialDialog(R.string.permission_location_title,
|
||||||
R.string.permission_location_denied_body);
|
R.string.permission_location_denied_body);
|
||||||
@@ -406,7 +270,7 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
|
|
||||||
private void requestPermissions() {
|
private void requestPermissions() {
|
||||||
String[] permissions;
|
String[] permissions;
|
||||||
if (isBluetoothSupported()) {
|
if (viewModel.isBluetoothSupported()) {
|
||||||
permissions = new String[] {CAMERA, ACCESS_FINE_LOCATION};
|
permissions = new String[] {CAMERA, ACCESS_FINE_LOCATION};
|
||||||
} else {
|
} else {
|
||||||
permissions = new String[] {CAMERA};
|
permissions = new String[] {CAMERA};
|
||||||
@@ -430,7 +294,7 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
} else {
|
} else {
|
||||||
cameraPermission = Permission.PERMANENTLY_DENIED;
|
cameraPermission = Permission.PERMANENTLY_DENIED;
|
||||||
}
|
}
|
||||||
if (isBluetoothSupported()) {
|
if (viewModel.isBluetoothSupported()) {
|
||||||
if (gotPermission(ACCESS_FINE_LOCATION, permissions,
|
if (gotPermission(ACCESS_FINE_LOCATION, permissions,
|
||||||
grantResults)) {
|
grantResults)) {
|
||||||
locationPermission = Permission.GRANTED;
|
locationPermission = Permission.GRANTED;
|
||||||
@@ -463,24 +327,6 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
|
|||||||
permission);
|
permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void eventOccurred(Event e) {
|
|
||||||
if (e instanceof TransportStateEvent) {
|
|
||||||
TransportStateEvent t = (TransportStateEvent) e;
|
|
||||||
if (t.getTransportId().equals(BluetoothConstants.ID)) {
|
|
||||||
if (LOG.isLoggable(INFO)) {
|
|
||||||
LOG.info("Bluetooth state changed to " + t.getState());
|
|
||||||
}
|
|
||||||
showQrCodeFragmentIfAllowed();
|
|
||||||
} else if (t.getTransportId().equals(LanTcpConstants.ID)) {
|
|
||||||
if (LOG.isLoggable(INFO)) {
|
|
||||||
LOG.info("Wifi state changed to " + t.getState());
|
|
||||||
}
|
|
||||||
showQrCodeFragmentIfAllowed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class BluetoothStateReceiver extends BroadcastReceiver {
|
private class BluetoothStateReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user