Merge branch 'plugin-toggle-settings' into 'plugin-toggles'

Add toggle settings for transport plugins

See merge request briar/briar!1211
This commit is contained in:
Torsten Grote
2020-01-23 15:09:19 +00:00
18 changed files with 521 additions and 202 deletions

View File

@@ -9,6 +9,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.fragment.BaseFragment;
import javax.annotation.Nullable;
import javax.inject.Inject;
@@ -79,13 +80,13 @@ public class ContactExchangeActivity extends KeyAgreementActivity {
@UiThread
private void contactExchangeFailed() {
showErrorFragment(R.string.connection_error_explanation);
showErrorFragment();
}
@UiThread
@Override
public void keyAgreementFailed() {
showErrorFragment(R.string.connection_error_explanation);
showErrorFragment();
}
@UiThread
@@ -103,7 +104,7 @@ public class ContactExchangeActivity extends KeyAgreementActivity {
@UiThread
@Override
public void keyAgreementAborted(boolean remoteAborted) {
showErrorFragment(R.string.connection_error_explanation);
showErrorFragment();
}
@UiThread
@@ -112,4 +113,10 @@ public class ContactExchangeActivity extends KeyAgreementActivity {
startContactExchange(result);
return getString(R.string.exchanging_contact_details);
}
protected void showErrorFragment() {
String errorMsg = getString(R.string.connection_error_explanation);
BaseFragment f = ContactExchangeErrorFragment.newInstance(errorMsg);
showNextFragment(f);
}
}

View File

@@ -8,10 +8,23 @@ import android.content.IntentFilter;
import android.os.Bundle;
import android.view.MenuItem;
import org.briarproject.bramble.api.db.DbException;
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.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
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.TransportId;
import org.briarproject.bramble.api.plugin.event.BluetoothEnabledEvent;
import org.briarproject.bramble.api.plugin.event.TransportStateEvent;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
@@ -21,6 +34,7 @@ import org.briarproject.briar.android.keyagreement.IntroFragment.IntroScreenSeen
import org.briarproject.briar.android.keyagreement.KeyAgreementFragment.KeyAgreementEventListener;
import org.briarproject.briar.android.util.UiUtils;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.Nullable;
@@ -37,13 +51,18 @@ import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.CAMERA;
import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.EXTRA_SCAN_MODE;
import static android.bluetooth.BluetoothAdapter.EXTRA_STATE;
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE;
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE;
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.TcpConstants.PREF_TCP_ENABLE;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_BLUETOOTH_DISCOVERABLE;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMISSION_CAMERA_LOCATION;
@@ -51,10 +70,33 @@ import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PERMI
@ParametersNotNullByDefault
public abstract class KeyAgreementActivity extends BriarActivity implements
BaseFragmentListener, IntroScreenSeenListener,
KeyAgreementEventListener {
KeyAgreementEventListener, EventListener {
private enum BluetoothState {
UNKNOWN, NO_ADAPTER, WAITING, REFUSED, ENABLED, DISCOVERABLE
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 {
@@ -62,11 +104,21 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
}
private static final Logger LOG =
Logger.getLogger(KeyAgreementActivity.class.getName());
getLogger(KeyAgreementActivity.class.getName());
@Inject
EventBus eventBus;
@Inject
PluginManager pluginManager;
@Inject
@IoExecutor
Executor ioExecutor;
@Inject
SettingsManager settingsManager;
/**
* Set to true in onPostResume() and false in onPause(). This prevents the
* QR code fragment from being shown if onRequestPermissionsResult() is
@@ -74,21 +126,36 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
* https://issuetracker.google.com/issues/37067655.
*/
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 the Bluetooth adapter was already enabled before we
* asked for Bluetooth discoverability, so we know whether to broadcast a
* {@link BluetoothEnabledEvent}.
*/
private boolean wasAdapterEnabled = 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 locationPermission = Permission.UNKNOWN;
private BluetoothState bluetoothState = BluetoothState.UNKNOWN;
private BluetoothDecision bluetoothDecision = BluetoothDecision.UNKNOWN;
private BroadcastReceiver bluetoothReceiver = null;
@Override
@@ -96,20 +163,17 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
component.inject(this);
}
@SuppressWarnings("ConstantConditions")
@Override
public void onCreate(@Nullable Bundle state) {
super.onCreate(state);
setContentView(R.layout.activity_fragment_container_toolbar);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
if (state == null) {
showInitialFragment(IntroFragment.newInstance());
}
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_STATE_CHANGED);
filter.addAction(ACTION_SCAN_MODE_CHANGED);
IntentFilter filter = new IntentFilter(ACTION_SCAN_MODE_CHANGED);
bluetoothReceiver = new BluetoothStateReceiver();
registerReceiver(bluetoothReceiver, filter);
}
@@ -122,18 +186,17 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
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;
@@ -150,11 +213,22 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
private void showQrCodeFragmentIfAllowed() {
if (isResumed && continueClicked && areEssentialPermissionsGranted()) {
if (bluetoothState == BluetoothState.UNKNOWN ||
bluetoothState == BluetoothState.ENABLED) {
requestBluetoothDiscoverable();
} else if (bluetoothState != BluetoothState.WAITING) {
if (isWifiReady() && isBluetoothReady()) {
LOG.info("Wifi and Bluetooth are ready");
showQrCodeFragment();
} else {
if (shouldEnableWifi()) {
LOG.info("Enabling wifi plugin");
hasEnabledWifi = true;
enablePlugin(LanTcpConstants.ID, PREF_TCP_ENABLE);
}
if (bluetoothDecision == BluetoothDecision.UNKNOWN) {
requestBluetoothDiscoverable();
} else if (shouldEnableBluetooth()) {
LOG.info("Enabling Bluetooth plugin");
hasEnabledBluetooth = true;
enablePlugin(BluetoothConstants.ID, PREF_BT_ENABLE);
}
}
}
}
@@ -167,57 +241,116 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
locationPermission == Permission.PERMANENTLY_DENIED);
}
private boolean isWifiReady() {
Plugin p = pluginManager.getPlugin(LanTcpConstants.ID);
if (p == null) return true; // Continue without wifi
State state = p.getState();
// Wait for plugin to become enabled
return state == ACTIVE || state == INACTIVE;
}
private boolean isBluetoothReady() {
if (bluetoothDecision == BluetoothDecision.UNKNOWN ||
bluetoothDecision == BluetoothDecision.WAITING) {
// Wait for decision
return false;
}
if (bluetoothDecision == BluetoothDecision.NO_ADAPTER
|| bluetoothDecision == BluetoothDecision.REFUSED) {
// Continue without Bluetooth
return true;
}
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
if (bt == null) return true; // Continue without Bluetooth
if (bt.getScanMode() != SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
// Wait for adapter to become discoverable
return false;
}
Plugin p = pluginManager.getPlugin(BluetoothConstants.ID);
if (p == null) return true; // Continue without Bluetooth
// Wait for plugin to become active
return p.getState() == ACTIVE;
}
private boolean shouldEnableWifi() {
if (hasEnabledWifi) return false;
Plugin p = pluginManager.getPlugin(LanTcpConstants.ID);
return p != null && p.getState() == DISABLED;
}
private void enablePlugin(TransportId t, String settingKey) {
ioExecutor.execute(() -> {
try {
Settings s = new Settings();
s.putBoolean(settingKey, true);
settingsManager.mergeSettings(s, t.getString());
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
}
private void requestBluetoothDiscoverable() {
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
if (bt == null) {
bluetoothDecision = BluetoothDecision.NO_ADAPTER;
showQrCodeFragmentIfAllowed();
} else {
Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
if (i.resolveActivity(getPackageManager()) != null) {
LOG.info("Asking for Bluetooth discoverability");
bluetoothDecision = BluetoothDecision.WAITING;
wasAdapterEnabled = bt.isEnabled();
startActivityForResult(i, REQUEST_BLUETOOTH_DISCOVERABLE);
} else {
bluetoothDecision = BluetoothDecision.NO_ADAPTER;
showQrCodeFragmentIfAllowed();
}
}
}
private boolean shouldEnableBluetooth() {
if (bluetoothDecision != BluetoothDecision.ACCEPTED) return false;
if (hasEnabledBluetooth) return false;
Plugin p = pluginManager.getPlugin(BluetoothConstants.ID);
return p != null && p.getState() == 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 (checkPermissions()) showQrCodeFragmentIfAllowed();
}
private void requestBluetoothDiscoverable() {
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
if (bt == null) {
setBluetoothState(BluetoothState.NO_ADAPTER);
} else {
Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
if (i.resolveActivity(getPackageManager()) != null) {
setBluetoothState(BluetoothState.WAITING);
wasAdapterEnabled = bt.isEnabled();
startActivityForResult(i, REQUEST_BLUETOOTH_DISCOVERABLE);
} else {
setBluetoothState(BluetoothState.NO_ADAPTER);
}
}
}
private void setBluetoothState(BluetoothState bluetoothState) {
LOG.info("Setting Bluetooth state to " + bluetoothState);
this.bluetoothState = bluetoothState;
if (!wasAdapterEnabled && bluetoothState == BluetoothState.ENABLED) {
eventBus.broadcast(new BluetoothEnabledEvent());
wasAdapterEnabled = true;
}
showQrCodeFragmentIfAllowed();
}
@Override
public void onActivityResult(int request, int result, Intent data) {
public void onActivityResult(int request, int result,
@Nullable Intent data) {
if (request == REQUEST_BLUETOOTH_DISCOVERABLE) {
if (result == RESULT_CANCELED) {
setBluetoothState(BluetoothState.REFUSED);
LOG.info("Bluetooth discoverability was refused");
bluetoothDecision = BluetoothDecision.REFUSED;
} else {
// If Bluetooth is already discoverable, show the QR code -
// otherwise wait for the state or scan mode to change
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
if (bt == null) throw new AssertionError();
if (bt.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE)
setBluetoothState(BluetoothState.DISCOVERABLE);
LOG.info("Bluetooth discoverability was accepted");
bluetoothDecision = BluetoothDecision.ACCEPTED;
if (!wasAdapterEnabled) {
LOG.info("Bluetooth adapter was enabled by us");
eventBus.broadcast(new BluetoothEnabledEvent());
wasAdapterEnabled = true;
}
}
showQrCodeFragmentIfAllowed();
} else super.onActivityResult(request, result, data);
}
@@ -227,7 +360,12 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
continueClicked = false;
// If we return to the intro fragment, ask for Bluetooth
// discoverability again before showing the QR code fragment
bluetoothState = BluetoothState.UNKNOWN;
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
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentByTag(KeyAgreementFragment.TAG) == null) {
@@ -239,12 +377,6 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
}
}
protected void showErrorFragment(@StringRes int errorResId) {
String errorMsg = getString(errorResId);
BaseFragment f = ContactExchangeErrorFragment.newInstance(errorMsg);
showNextFragment(f);
}
private boolean checkPermissions() {
if (areEssentialPermissionsGranted()) return true;
// If the camera permission has been permanently denied, ask the
@@ -335,24 +467,30 @@ public abstract class KeyAgreementActivity extends BriarActivity implements
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 {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_STATE_CHANGED.equals(action)) {
int state = intent.getIntExtra(EXTRA_STATE, 0);
if (state == STATE_ON)
setBluetoothState(BluetoothState.ENABLED);
else setBluetoothState(BluetoothState.UNKNOWN);
} else if (ACTION_SCAN_MODE_CHANGED.equals(action)) {
int scanMode = intent.getIntExtra(EXTRA_SCAN_MODE, 0);
if (scanMode == SCAN_MODE_CONNECTABLE_DISCOVERABLE)
setBluetoothState(BluetoothState.DISCOVERABLE);
else if (scanMode == SCAN_MODE_CONNECTABLE)
setBluetoothState(BluetoothState.ENABLED);
else setBluetoothState(BluetoothState.UNKNOWN);
}
LOG.info("Bluetooth scan mode changed");
showQrCodeFragmentIfAllowed();
}
}
}

View File

@@ -21,6 +21,7 @@ import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
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.TorConstants;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
@@ -73,6 +74,8 @@ import static androidx.core.view.ViewCompat.LAYOUT_DIRECTION_LTR;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENABLE;
import static org.briarproject.bramble.api.plugin.TcpConstants.PREF_TCP_ENABLE;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ENABLE;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_MOBILE;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_AUTOMATIC;
@@ -105,16 +108,24 @@ public class SettingsFragment extends PreferenceFragmentCompat
implements EventListener, OnPreferenceChangeListener {
public static final String SETTINGS_NAMESPACE = "android-ui";
public static final String BT_NAMESPACE = BluetoothConstants.ID.getString();
public static final String TOR_NAMESPACE = TorConstants.ID.getString();
public static final String LANGUAGE = "pref_key_language";
public static final String PREF_SCREEN_LOCK = "pref_key_lock";
public static final String PREF_SCREEN_LOCK_TIMEOUT =
"pref_key_lock_timeout";
public static final String NOTIFY_SIGN_IN = "pref_key_notify_sign_in";
public static final String TOR_NETWORK = "pref_key_tor_network";
public static final String TOR_MOBILE = "pref_key_tor_mobile_data";
public static final String TOR_ONLY_WHEN_CHARGING =
private static final String BT_NAMESPACE =
BluetoothConstants.ID.getString();
private static final String BT_ENABLE = "pref_key_bluetooth";
private static final String WIFI_NAMESPACE = LanTcpConstants.ID.getString();
private static final String WIFI_ENABLE = "pref_key_wifi";
private static final String TOR_NAMESPACE = TorConstants.ID.getString();
private static final String TOR_ENABLE = "pref_key_tor_enable";
private static final String TOR_NETWORK = "pref_key_tor_network";
private static final String TOR_MOBILE = "pref_key_tor_mobile_data";
private static final String TOR_ONLY_WHEN_CHARGING =
"pref_key_tor_only_when_charging";
private static final Logger LOG =
@@ -122,7 +133,9 @@ public class SettingsFragment extends PreferenceFragmentCompat
private SettingsActivity listener;
private ListPreference language;
private ListPreference enableBluetooth;
private SwitchPreference enableBluetooth;
private SwitchPreference enableWifi;
private SwitchPreference enableTor;
private ListPreference torNetwork;
private SwitchPreference torMobile;
private SwitchPreference torOnlyWhenCharging;
@@ -137,7 +150,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
private Preference notifySound;
// Fields that are accessed from background threads must be volatile
private volatile Settings settings, btSettings, torSettings;
private volatile Settings settings, btSettings, wifiSettings, torSettings;
private volatile boolean settingsLoaded = false;
@Inject
@@ -163,28 +176,23 @@ public class SettingsFragment extends PreferenceFragmentCompat
public void onCreatePreferences(Bundle bundle, String s) {
addPreferencesFromResource(R.xml.settings);
language = (ListPreference) findPreference(LANGUAGE);
language = findPreference(LANGUAGE);
setLanguageEntries();
ListPreference theme =
(ListPreference) findPreference("pref_key_theme");
enableBluetooth = (ListPreference) findPreference("pref_key_bluetooth");
torNetwork = (ListPreference) findPreference(TOR_NETWORK);
torMobile = (SwitchPreference) findPreference(TOR_MOBILE);
torOnlyWhenCharging =
(SwitchPreference) findPreference(TOR_ONLY_WHEN_CHARGING);
screenLock = (SwitchPreference) findPreference(PREF_SCREEN_LOCK);
screenLockTimeout =
(ListPreference) findPreference(PREF_SCREEN_LOCK_TIMEOUT);
notifyPrivateMessages = (SwitchPreference) findPreference(
"pref_key_notify_private_messages");
notifyGroupMessages = (SwitchPreference) findPreference(
"pref_key_notify_group_messages");
notifyForumPosts = (SwitchPreference) findPreference(
"pref_key_notify_forum_posts");
notifyBlogPosts = (SwitchPreference) findPreference(
"pref_key_notify_blog_posts");
notifyVibration = (SwitchPreference) findPreference(
"pref_key_notify_vibration");
ListPreference theme = findPreference("pref_key_theme");
enableBluetooth = findPreference(BT_ENABLE);
enableWifi = findPreference(WIFI_ENABLE);
enableTor = findPreference(TOR_ENABLE);
torNetwork = findPreference(TOR_NETWORK);
torMobile = findPreference(TOR_MOBILE);
torOnlyWhenCharging = findPreference(TOR_ONLY_WHEN_CHARGING);
screenLock = findPreference(PREF_SCREEN_LOCK);
screenLockTimeout = findPreference(PREF_SCREEN_LOCK_TIMEOUT);
notifyPrivateMessages =
findPreference("pref_key_notify_private_messages");
notifyGroupMessages = findPreference("pref_key_notify_group_messages");
notifyForumPosts = findPreference("pref_key_notify_forum_posts");
notifyBlogPosts = findPreference("pref_key_notify_blog_posts");
notifyVibration = findPreference("pref_key_notify_vibration");
notifySound = findPreference("pref_key_notify_sound");
language.setOnPreferenceChangeListener(this);
@@ -194,8 +202,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
UiUtils.setTheme(getActivity(), (String) newValue);
// bring up parent activity, so it can change its theme as well
// upstream bug: https://issuetracker.google.com/issues/38352704
Intent intent =
new Intent(getActivity(), ENTRY_ACTIVITY);
Intent intent = new Intent(getActivity(), ENTRY_ACTIVITY);
intent.setFlags(
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
@@ -207,6 +214,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
return true;
});
enableBluetooth.setOnPreferenceChangeListener(this);
enableWifi.setOnPreferenceChangeListener(this);
enableTor.setOnPreferenceChangeListener(this);
torNetwork.setOnPreferenceChangeListener(this);
torMobile.setOnPreferenceChangeListener(this);
torOnlyWhenCharging.setOnPreferenceChangeListener(this);
@@ -335,7 +344,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
boolean blocked =
circumventionProvider.isTorProbablyBlocked(country);
boolean useBridges = circumventionProvider.doBridgesWork(country);
String setting = getString(R.string.tor_network_setting_without_bridges);
String setting =
getString(R.string.tor_network_setting_without_bridges);
if (blocked && useBridges) {
setting = getString(R.string.tor_network_setting_with_bridges);
} else if (blocked) {
@@ -352,6 +362,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
long start = now();
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
btSettings = settingsManager.getSettings(BT_NAMESPACE);
wifiSettings = settingsManager.getSettings(WIFI_NAMESPACE);
torSettings = settingsManager.getSettings(TOR_NAMESPACE);
settingsLoaded = true;
logDuration(LOG, "Loading settings", start);
@@ -369,7 +380,15 @@ public class SettingsFragment extends PreferenceFragmentCompat
boolean btEnabledSetting =
btSettings.getBoolean(PREF_BT_ENABLE, false);
enableBluetooth.setValue(Boolean.toString(btEnabledSetting));
enableBluetooth.setChecked(btEnabledSetting);
boolean wifiEnabledSetting =
wifiSettings.getBoolean(PREF_TCP_ENABLE, false);
enableWifi.setChecked(wifiEnabledSetting);
boolean torEnabledSetting =
torSettings.getBoolean(PREF_TOR_ENABLE, true);
enableTor.setChecked(torEnabledSetting);
int torNetworkSetting = torSettings.getInt(PREF_TOR_NETWORK,
PREF_TOR_NETWORK_AUTOMATIC);
@@ -443,6 +462,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
// - pref_key_lock (screenLock -> displayScreenLockSetting())
// - pref_key_lock_timeout (screenLockTimeout)
enableBluetooth.setEnabled(enabled);
enableWifi.setEnabled(enabled);
enableTor.setEnabled(enabled);
torNetwork.setEnabled(enabled);
torMobile.setEnabled(enabled);
torOnlyWhenCharging.setEnabled(enabled);
@@ -545,8 +566,14 @@ public class SettingsFragment extends PreferenceFragmentCompat
languageChanged((String) newValue);
return false;
} else if (preference == enableBluetooth) {
boolean btSetting = Boolean.valueOf((String) newValue);
storeBluetoothSettings(btSetting);
boolean btSetting = (Boolean) newValue;
storeBluetoothSetting(btSetting);
} else if (preference == enableWifi) {
boolean wifiSetting = (Boolean) newValue;
storeWifiSetting(wifiSetting);
} else if (preference == enableTor) {
boolean torEnabledSetting = (Boolean) newValue;
storeTorEnabledSetting(torEnabledSetting);
} else if (preference == torNetwork) {
int torNetworkSetting = Integer.valueOf((String) newValue);
storeTorNetworkSetting(torNetworkSetting);
@@ -610,6 +637,12 @@ public class SettingsFragment extends PreferenceFragmentCompat
builder.show();
}
private void storeTorEnabledSetting(boolean torEnabledSetting) {
Settings s = new Settings();
s.putBoolean(PREF_TOR_ENABLE, torEnabledSetting);
mergeSettings(s, TOR_NAMESPACE);
}
private void storeTorNetworkSetting(int torNetworkSetting) {
Settings s = new Settings();
s.putInt(PREF_TOR_NETWORK, torNetworkSetting);
@@ -628,12 +661,18 @@ public class SettingsFragment extends PreferenceFragmentCompat
mergeSettings(s, TOR_NAMESPACE);
}
private void storeBluetoothSettings(boolean btSetting) {
private void storeBluetoothSetting(boolean btSetting) {
Settings s = new Settings();
s.putBoolean(PREF_BT_ENABLE, btSetting);
mergeSettings(s, BT_NAMESPACE);
}
private void storeWifiSetting(boolean wifiSetting) {
Settings s = new Settings();
s.putBoolean(PREF_TCP_ENABLE, wifiSetting);
mergeSettings(s, WIFI_NAMESPACE);
}
private void storeSettings(Settings s) {
mergeSettings(s, SETTINGS_NAMESPACE);
}
@@ -696,6 +735,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
LOG.info("Bluetooth settings updated");
btSettings = s.getSettings();
displaySettings();
} else if (namespace.equals(WIFI_NAMESPACE)) {
LOG.info("Wifi settings updated");
wifiSettings = s.getSettings();
displaySettings();
} else if (namespace.equals(TOR_NAMESPACE)) {
LOG.info("Tor settings updated");
torSettings = s.getSettings();

View File

@@ -1,14 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="boolean_array">
<item>true</item>
<item>false</item>
</string-array>
<string-array name="bt_setting_names">
<item>@string/bluetooth_setting_enabled</item>
<item>@string/bluetooth_setting_disabled</item>
</string-array>
<string-array name="tor_network_setting_names">
<item>@string/tor_network_setting_automatic</item>
<item>@string/tor_network_setting_without_bridges</item>
@@ -66,6 +57,7 @@
<item>zh-CN</item>
<item>zh-TW</item>
</string-array>
<string-array name="pref_theme_entries">
<item>@string/pref_theme_light</item>
<item>@string/pref_theme_dark</item>

View File

@@ -441,12 +441,12 @@
<string name="pref_theme_auto">Automatic (Daytime)</string>
<string name="pref_theme_system">System Default</string>
<!-- Settings Network -->
<string name="network_settings_title">Networks</string>
<string name="bluetooth_setting">Connect via Bluetooth</string>
<string name="bluetooth_setting_enabled">Whenever contacts are nearby</string>
<string name="bluetooth_setting_disabled">Only when adding contacts</string>
<string name="tor_network_setting">Connect via Internet (Tor)</string>
<!-- Settings Connections -->
<string name="network_settings_title">Connections</string>
<string name="bluetooth_setting">Connect to contacts via Bluetooth</string>
<string name="wifi_setting">Connect to contacts on the same Wi-Fi network</string>
<string name="tor_enable_title">Connect to contacts via Internet (Tor)</string>
<string name="tor_network_setting">Connection method for Internet (Tor)</string>
<string name="tor_network_setting_automatic">Automatic based on location</string>
<string name="tor_network_setting_without_bridges">Use Tor without bridges</string>
<string name="tor_network_setting_with_bridges">Use Tor with bridges</string>

View File

@@ -29,18 +29,33 @@
android:layout="@layout/preferences_category"
android:title="@string/network_settings_title">
<ListPreference
<SwitchPreference
android:defaultValue="false"
android:entries="@array/bt_setting_names"
android:entryValues="@array/boolean_array"
android:key="pref_key_bluetooth"
android:persistent="false"
android:summary="%s"
android:title="@string/bluetooth_setting"
android:widgetLayout="@layout/preference_switch_compat"
app:iconSpaceReserved="false"/>
<SwitchPreference
android:defaultValue="false"
android:key="pref_key_wifi"
android:persistent="false"
android:title="@string/wifi_setting"
android:widgetLayout="@layout/preference_switch_compat"
app:iconSpaceReserved="false"/>
<SwitchPreference
android:defaultValue="true"
android:key="pref_key_tor_enable"
android:persistent="false"
android:title="@string/tor_enable_title"
android:widgetLayout="@layout/preference_switch_compat"
app:iconSpaceReserved="false"/>
<ListPreference
android:defaultValue="0"
android:dependency="pref_key_tor_enable"
android:entries="@array/tor_network_setting_names"
android:entryValues="@array/tor_network_setting_values"
android:key="pref_key_tor_network"
@@ -51,6 +66,7 @@
<SwitchPreference
android:defaultValue="true"
android:dependency="pref_key_tor_enable"
android:key="pref_key_tor_mobile_data"
android:persistent="false"
android:title="@string/tor_mobile_data_title"
@@ -59,6 +75,7 @@
<SwitchPreference
android:defaultValue="false"
android:dependency="pref_key_tor_enable"
android:key="pref_key_tor_only_when_charging"
android:persistent="false"
android:title="@string/tor_only_when_charging_title"