QuickTileService: Implement and update from VpnService
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
d5d3566e6c
commit
416d3adda7
@ -24,7 +24,11 @@
|
||||
android:label="@string/edit_activity_title" />
|
||||
<activity
|
||||
android:name=".SettingsActivity"
|
||||
android:label="@string/settings" />
|
||||
android:label="@string/settings">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<receiver android:name=".BootCompletedReceiver">
|
||||
<intent-filter>
|
||||
@ -32,6 +36,17 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name=".QuickTileService"
|
||||
android:icon="@drawable/ic_tile"
|
||||
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.quicksettings.action.QS_TILE" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.service.quicksettings.ACTIVE_TILE"
|
||||
android:value="true" />
|
||||
</service>
|
||||
<service
|
||||
android:name=".VpnService"
|
||||
android:exported="false" />
|
||||
|
@ -0,0 +1,81 @@
|
||||
package com.wireguard.android;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.service.quicksettings.Tile;
|
||||
import android.service.quicksettings.TileService;
|
||||
|
||||
import com.wireguard.config.Config;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
public class QuickTileService extends TileService {
|
||||
private Config config;
|
||||
private SharedPreferences preferences;
|
||||
private VpnService service;
|
||||
|
||||
@Override
|
||||
public void onClick() {
|
||||
if (service != null && config != null) {
|
||||
if (config.isEnabled())
|
||||
service.disable(config.getName());
|
||||
else
|
||||
service.enable(config.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
service = VpnService.getInstance();
|
||||
if (service == null)
|
||||
bindService(new Intent(this, VpnService.class), new ServiceConnectionCallbacks(),
|
||||
Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartListening() {
|
||||
// Since this is an active tile, this only gets called when we want to update the tile.
|
||||
final Tile tile = getQsTile();
|
||||
final String configName = preferences.getString(VpnService.KEY_PRIMARY_CONFIG, null);
|
||||
config = configName != null && service != null ? service.get(configName) : null;
|
||||
if (config != null) {
|
||||
tile.setLabel(config.getName());
|
||||
final int state = config.isEnabled() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
|
||||
if (tile.getState() != state) {
|
||||
// The icon must be changed every time the state changes, or the color won't change.
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
tile.setIcon(Icon.createWithResource(this, R.drawable.ic_tile_disabled));
|
||||
tile.setLabel(getString(R.string.loading));
|
||||
tile.setState(Tile.STATE_UNAVAILABLE);
|
||||
}
|
||||
tile.updateTile();
|
||||
}
|
||||
|
||||
private class ServiceConnectionCallbacks implements ServiceConnection {
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName component, final IBinder binder) {
|
||||
// We don't actually need a binding, only notification that the service is started.
|
||||
unbindService(this);
|
||||
service = VpnService.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName component) {
|
||||
// This can never happen; the service runs in the same thread as this service.
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,15 @@
|
||||
package com.wireguard.android;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.service.quicksettings.TileService;
|
||||
import android.util.Log;
|
||||
|
||||
import com.wireguard.config.Config;
|
||||
@ -137,11 +140,13 @@ public class VpnService extends Service
|
||||
final String key) {
|
||||
if (!KEY_PRIMARY_CONFIG.equals(key))
|
||||
return;
|
||||
boolean changed = false;
|
||||
final String newName = preferences.getString(key, null);
|
||||
if (primaryName != null && !primaryName.equals(newName)) {
|
||||
final Config oldConfig = configurations.get(primaryName);
|
||||
if (oldConfig != null)
|
||||
oldConfig.setIsPrimary(false);
|
||||
changed = true;
|
||||
}
|
||||
if (newName != null && !newName.equals(primaryName)) {
|
||||
final Config newConfig = configurations.get(newName);
|
||||
@ -149,8 +154,11 @@ public class VpnService extends Service
|
||||
newConfig.setIsPrimary(true);
|
||||
else
|
||||
preferences.edit().remove(KEY_PRIMARY_CONFIG).apply();
|
||||
changed = true;
|
||||
}
|
||||
primaryName = newName;
|
||||
if (changed)
|
||||
updateTile();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -198,6 +206,13 @@ public class VpnService extends Service
|
||||
new ConfigUpdater(oldConfig, config, wasEnabled).execute();
|
||||
}
|
||||
|
||||
private void updateTile() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
|
||||
return;
|
||||
Log.v(TAG, "Requesting quick tile update");
|
||||
TileService.requestListeningState(this, new ComponentName(this, QuickTileService.class));
|
||||
}
|
||||
|
||||
private class ConfigDisabler extends AsyncTask<Void, Void, Boolean> {
|
||||
private final Config config;
|
||||
|
||||
@ -219,6 +234,8 @@ public class VpnService extends Service
|
||||
config.setIsEnabled(false);
|
||||
enabledConfigs.remove(config.getName());
|
||||
preferences.edit().putStringSet(KEY_ENABLED_CONFIGS, enabledConfigs).apply();
|
||||
if (config.getName().equals(primaryName))
|
||||
updateTile();
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,6 +260,8 @@ public class VpnService extends Service
|
||||
config.setIsEnabled(true);
|
||||
enabledConfigs.add(config.getName());
|
||||
preferences.edit().putStringSet(KEY_ENABLED_CONFIGS, enabledConfigs).apply();
|
||||
if (config.getName().equals(primaryName))
|
||||
updateTile();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
<string name="hint_optional">(optional)</string>
|
||||
<string name="hint_random">(random)</string>
|
||||
<string name="listen_port">Listen port</string>
|
||||
<string name="loading">Loading</string>
|
||||
<string name="mtu">MTU</string>
|
||||
<string name="placeholder_text">No configuration selected</string>
|
||||
<string name="primary_config">Primary configuration</string>
|
||||
|
Loading…
Reference in New Issue
Block a user