TunnelManager/QuickTileService: Remember last used tunnel

This is actually a bit simpler than having a manually-selected "primary"
tunnel, and is hopefully easier for the user.

Signed-off-by: Samuel Holland <samuel@sholland.org>
This commit is contained in:
Samuel Holland
2018-01-07 21:50:43 -06:00
parent 38b2aafce8
commit 1fd9547f6a
2 changed files with 110 additions and 101 deletions
@@ -2,12 +2,8 @@ package com.wireguard.android;
import android.annotation.TargetApi;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.databinding.Observable;
import android.databinding.Observable.OnPropertyChangedCallback;
import android.databinding.ObservableList;
import android.databinding.ObservableList.OnListChangedCallback;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.service.quicksettings.Tile;
@@ -15,13 +11,10 @@ import android.service.quicksettings.TileService;
import android.util.Log;
import android.widget.Toast;
import com.wireguard.android.Application.ApplicationComponent;
import com.wireguard.android.activity.MainActivity;
import com.wireguard.android.activity.SettingsActivity;
import com.wireguard.android.model.Tunnel;
import com.wireguard.android.model.Tunnel.State;
import com.wireguard.android.model.TunnelManager;
import com.wireguard.android.util.ObservableKeyedList;
import java.util.Objects;
@@ -32,61 +25,40 @@ import java.util.Objects;
*/
@TargetApi(Build.VERSION_CODES.N)
public class QuickTileService extends TileService implements OnSharedPreferenceChangeListener {
public class QuickTileService extends TileService {
private static final String TAG = QuickTileService.class.getSimpleName();
private final OnTunnelListChangedCallback listCallback = new OnTunnelListChangedCallback();
private final OnTunnelStateChangedCallback tunnelCallback = new OnTunnelStateChangedCallback();
private SharedPreferences preferences;
private final OnStateChangedCallback onStateChangedCallback = new OnStateChangedCallback();
private final OnTunnelChangedCallback onTunnelChangedCallback = new OnTunnelChangedCallback();
private Tunnel tunnel;
private TunnelManager tunnelManager;
@Override
public void onClick() {
if (tunnel != null) {
tunnel.setState(State.TOGGLE).handle(this::onToggleFinished);
} else {
if (tunnelManager.getTunnels().isEmpty()) {
// Prompt the user to create or import a tunnel configuration.
startActivityAndCollapse(new Intent(this, MainActivity.class));
} else {
// Prompt the user to select a tunnel for use with the quick settings tile.
final Intent intent = new Intent(this, SettingsActivity.class);
intent.putExtra(SettingsActivity.KEY_SHOW_QUICK_TILE_SETTINGS, true);
startActivityAndCollapse(intent);
}
}
if (tunnel != null)
tunnel.setState(State.TOGGLE).whenComplete(this::onToggleFinished);
else
startActivityAndCollapse(new Intent(this, MainActivity.class));
}
@Override
public void onCreate() {
super.onCreate();
final ApplicationComponent component = Application.getComponent();
preferences = component.getPreferences();
tunnelManager = component.getTunnelManager();
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) {
if (!TunnelManager.KEY_PRIMARY_TUNNEL.equals(key))
return;
updateTile();
tunnelManager = Application.getComponent().getTunnelManager();
}
@Override
public void onStartListening() {
preferences.registerOnSharedPreferenceChangeListener(this);
tunnelManager.getTunnels().addOnListChangedCallback(listCallback);
tunnelManager.addOnPropertyChangedCallback(onTunnelChangedCallback);
if (tunnel != null)
tunnel.addOnPropertyChangedCallback(tunnelCallback);
tunnel.addOnPropertyChangedCallback(onStateChangedCallback);
updateTile();
}
@Override
public void onStopListening() {
preferences.unregisterOnSharedPreferenceChangeListener(this);
tunnelManager.getTunnels().removeOnListChangedCallback(listCallback);
if (tunnel != null)
tunnel.removeOnPropertyChangedCallback(tunnelCallback);
tunnel.removeOnPropertyChangedCallback(onStateChangedCallback);
tunnelManager.removeOnPropertyChangedCallback(onTunnelChangedCallback);
}
@SuppressWarnings("unused")
@@ -101,16 +73,13 @@ public class QuickTileService extends TileService implements OnSharedPreferenceC
private void updateTile() {
// Update the tunnel.
final String currentName = tunnel != null ? tunnel.getName() : null;
final String newName = preferences.getString(TunnelManager.KEY_PRIMARY_TUNNEL, null);
if (!Objects.equals(currentName, newName)) {
final ObservableKeyedList<String, Tunnel> tunnels = tunnelManager.getTunnels();
final Tunnel newTunnel = newName != null ? tunnels.get(newName) : null;
final Tunnel newTunnel = tunnelManager.getLastUsedTunnel();
if (newTunnel != tunnel) {
if (tunnel != null)
tunnel.removeOnPropertyChangedCallback(tunnelCallback);
tunnel.removeOnPropertyChangedCallback(onStateChangedCallback);
tunnel = newTunnel;
if (tunnel != null)
tunnel.addOnPropertyChangedCallback(tunnelCallback);
tunnel.addOnPropertyChangedCallback(onStateChangedCallback);
}
// Update the tile contents.
final String label;
@@ -126,48 +95,15 @@ public class QuickTileService extends TileService implements OnSharedPreferenceC
tile.setLabel(label);
if (tile.getState() != state) {
// The icon must be changed every time the state changes, or the shade will not change.
final Integer iconResource = (state == Tile.STATE_ACTIVE)
? R.drawable.ic_tile : R.drawable.ic_tile_disabled;
final Integer iconResource = state == Tile.STATE_ACTIVE ? R.drawable.ic_tile
: R.drawable.ic_tile_disabled;
tile.setIcon(Icon.createWithResource(this, iconResource));
tile.setState(state);
}
tile.updateTile();
}
private final class OnTunnelListChangedCallback
extends OnListChangedCallback<ObservableList<Tunnel>> {
@Override
public void onChanged(final ObservableList<Tunnel> sender) {
updateTile();
}
@Override
public void onItemRangeChanged(final ObservableList<Tunnel> sender,
final int positionStart, final int itemCount) {
updateTile();
}
@Override
public void onItemRangeInserted(final ObservableList<Tunnel> sender,
final int positionStart, final int itemCount) {
// Do nothing.
}
@Override
public void onItemRangeMoved(final ObservableList<Tunnel> sender,
final int fromPosition, final int toPosition,
final int itemCount) {
// Do nothing.
}
@Override
public void onItemRangeRemoved(final ObservableList<Tunnel> sender,
final int positionStart, final int itemCount) {
updateTile();
}
}
private final class OnTunnelStateChangedCallback extends OnPropertyChangedCallback {
private final class OnStateChangedCallback extends OnPropertyChangedCallback {
@Override
public void onPropertyChanged(final Observable sender, final int propertyId) {
if (!Objects.equals(sender, tunnel)) {
@@ -179,4 +115,13 @@ public class QuickTileService extends TileService implements OnSharedPreferenceC
updateTile();
}
}
private final class OnTunnelChangedCallback extends OnPropertyChangedCallback {
@Override
public void onPropertyChanged(final Observable sender, final int propertyId) {
if (propertyId != 0 && propertyId != BR.lastUsedTunnel)
return;
updateTile();
}
}
}