@@ -1,5 +1,6 @@ | |||
package com.wireguard.android.activity; | |||
import androidx.annotation.Nullable; | |||
import androidx.appcompat.app.AppCompatActivity; | |||
import androidx.lifecycle.ViewModelProvider; | |||
import android.content.Intent; | |||
@@ -8,8 +9,13 @@ import android.view.View; | |||
import android.view.View.OnClickListener; | |||
import android.widget.Button; | |||
import android.widget.TextView; | |||
import android.widget.Toast; | |||
import com.wireguard.android.Application; | |||
import com.wireguard.android.R; | |||
import com.wireguard.android.backend.GoBackend; | |||
import com.wireguard.android.backend.Tunnel; | |||
import com.wireguard.android.model.ObservableTunnel; | |||
import com.wireguard.android.viewmodel.MainViewModel; | |||
public class MainActivity extends AppCompatActivity { | |||
@@ -17,6 +23,10 @@ public class MainActivity extends AppCompatActivity { | |||
private TextView bubbleStatus; | |||
private TextView deviceStatus; | |||
private Button connectButton; | |||
public ObservableTunnel pendingTunnel; | |||
private Boolean pendingTunnelUp; | |||
private static final int REQUEST_CODE_VPN_PERMISSION = 23491; | |||
@Override | |||
protected void onCreate(Bundle savedInstanceState) { | |||
@@ -30,6 +40,7 @@ public class MainActivity extends AppCompatActivity { | |||
finish(); | |||
} | |||
initUI(); | |||
pendingTunnel = mainViewModel.getTunnel(this); | |||
} | |||
private void initUI() { | |||
@@ -44,14 +55,50 @@ public class MainActivity extends AppCompatActivity { | |||
} | |||
private void initListeners() { | |||
connectButton.setOnClickListener(new OnClickListener() { | |||
@Override public void onClick(final View v) { | |||
connect(); | |||
} | |||
}); | |||
connectButton.setOnClickListener(new OnClickListener() { | |||
@Override public void onClick(final View v) { | |||
connect(); | |||
} | |||
}); | |||
} | |||
private void connect() { | |||
setTunnelState(true); | |||
} | |||
private void setTunnelState(final Boolean checked) { | |||
final ObservableTunnel tunnel = pendingTunnel; | |||
Application.getBackendAsync().thenAccept(backend -> { | |||
if (backend instanceof GoBackend) { | |||
final Intent intent = GoBackend.VpnService.prepare(this); | |||
if (intent != null) { | |||
pendingTunnelUp = checked; | |||
startActivityForResult(intent, REQUEST_CODE_VPN_PERMISSION); | |||
return; | |||
} | |||
} | |||
setTunnelStateWithPermissionsResult(tunnel, checked); | |||
}); | |||
} | |||
private void setTunnelStateWithPermissionsResult(final ObservableTunnel tunnel, final boolean checked) { | |||
tunnel.setStateAsync(Tunnel.State.of(checked)).whenComplete((observableTunnel, throwable) ->{ | |||
if(throwable==null){ | |||
Toast.makeText(this,"Connected",Toast.LENGTH_SHORT).show(); | |||
} | |||
else { | |||
Toast.makeText(this,"Failed",Toast.LENGTH_SHORT).show(); | |||
} | |||
}); | |||
} | |||
@Override protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) { | |||
super.onActivityResult(requestCode, resultCode, data); | |||
if (requestCode == REQUEST_CODE_VPN_PERMISSION) { | |||
if (pendingTunnel != null && pendingTunnelUp != null) setTunnelStateWithPermissionsResult(pendingTunnel, pendingTunnelUp); | |||
pendingTunnel = null; | |||
pendingTunnelUp = null; | |||
} | |||
} | |||
} |
@@ -1,6 +1,7 @@ | |||
package com.wireguard.android.repository; | |||
import android.content.Context; | |||
import android.content.Intent; | |||
import android.os.Build; | |||
import android.provider.Settings; | |||
import android.provider.Settings.Secure; | |||
@@ -10,10 +11,17 @@ import com.wireguard.android.api.ApiConstants; | |||
import com.wireguard.android.api.network.ClientApi; | |||
import com.wireguard.android.api.network.ClientService; | |||
import com.wireguard.android.api.network.NetworkBoundStatusResource; | |||
import com.wireguard.android.backend.GoBackend; | |||
import com.wireguard.android.backend.Tunnel.State; | |||
import com.wireguard.android.configStore.FileConfigStore; | |||
import com.wireguard.android.model.Device; | |||
import com.wireguard.android.model.ObservableTunnel; | |||
import com.wireguard.android.model.TunnelManager; | |||
import com.wireguard.android.model.User; | |||
import com.wireguard.android.resource.StatusResource; | |||
import com.wireguard.android.util.TunnelStore; | |||
import com.wireguard.android.util.UserStore; | |||
import com.wireguard.config.BadConfigException; | |||
import com.wireguard.config.Config; | |||
import java.io.ByteArrayInputStream; | |||
@@ -241,15 +249,17 @@ public class DataRepository { | |||
try { | |||
final byte[] configText = data.getBytes(); | |||
final Config config = Config.parse(new ByteArrayInputStream(configText)); | |||
createTunnel(config, tunnelName); | |||
createTunnel(config, tunnelName, data); | |||
} catch (Exception e) { | |||
postMutableLiveData(StatusResource.error(e.getMessage())); | |||
} | |||
} | |||
private void createTunnel(Config config, String tunnelName) { | |||
private void createTunnel(Config config, String tunnelName, String configString) { | |||
Application.getTunnelManager().create(tunnelName, config).whenComplete((observableTunnel, throwable) -> { | |||
if (observableTunnel != null) { | |||
TunnelStore.getInstance(context).setTunnelName(tunnelName); | |||
TunnelStore.getInstance(context).setConfig(configString); | |||
setMutableLiveData(StatusResource.success()); | |||
} else { | |||
setMutableLiveData(StatusResource.error(throwable.getMessage())); | |||
@@ -298,4 +308,24 @@ public class DataRepository { | |||
public void clearDisposable() { | |||
compositeDisposable.clear(); | |||
} | |||
public ObservableTunnel getTunnel(Context context){ | |||
Config config = null; | |||
try { | |||
config = parseConfig(TunnelStore.getInstance(context).getConfig()); | |||
} catch (final IOException | BadConfigException e) { | |||
e.printStackTrace(); | |||
} | |||
final String name = TunnelStore.getInstance(context).getTunnelName(); | |||
final TunnelManager tunnelManager = new TunnelManager(new FileConfigStore(context)); | |||
final ObservableTunnel tunnel = new ObservableTunnel(tunnelManager, name, config, State.DOWN); | |||
return tunnel; | |||
} | |||
private Config parseConfig(String data) throws IOException, BadConfigException { | |||
final byte[] configText = data.getBytes(); | |||
final Config config = Config.parse(new ByteArrayInputStream(configText)); | |||
return config; | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
package com.wireguard.android.util; | |||
import android.content.Context; | |||
import android.content.SharedPreferences; | |||
public class TunnelStore { | |||
private static TunnelStore instance; | |||
private SharedPreferences sharedPreferences; | |||
private static final String TUNNEL_SHARED_PREF = "com.wireguard.android.util.bubbleTunnelSharedPref"; | |||
private static final String TUNNEL_DATA_KEY = "com.wireguard.android.util.bubbleResponse"; | |||
private static final String CONFIG_DATA_KEY = "com.wireguard.android.util.bubbleConfigResponse"; | |||
public static final String TUNNEL_DEFAULT_VALUE = ""; | |||
public static final String CONFIG_DEFAULT_VALUE = ""; | |||
public static TunnelStore getInstance(Context context) { | |||
if (instance == null) { | |||
synchronized (UserStore.class) { | |||
if (instance == null) { | |||
instance = new TunnelStore(context); | |||
} | |||
} | |||
} | |||
return instance; | |||
} | |||
private TunnelStore(Context context) { | |||
sharedPreferences = context.getSharedPreferences(TUNNEL_SHARED_PREF, Context.MODE_PRIVATE); | |||
} | |||
public void setTunnelName(String tunnelName){ | |||
sharedPreferences.edit().putString(TUNNEL_DATA_KEY,tunnelName).apply(); | |||
} | |||
public String getTunnelName(){ | |||
return sharedPreferences.getString(TUNNEL_DATA_KEY, TUNNEL_DEFAULT_VALUE); | |||
} | |||
public void setConfig(String config){ | |||
sharedPreferences.edit().putString(CONFIG_DATA_KEY,config).apply(); | |||
} | |||
public String getConfig(){ | |||
return sharedPreferences.getString(CONFIG_DATA_KEY,CONFIG_DEFAULT_VALUE); | |||
} | |||
} |
@@ -1,6 +1,8 @@ | |||
package com.wireguard.android.viewmodel; | |||
import android.content.Context; | |||
import com.wireguard.android.model.ObservableTunnel; | |||
import com.wireguard.android.repository.DataRepository; | |||
import androidx.lifecycle.ViewModel; | |||
@@ -8,4 +10,8 @@ public class MainViewModel extends ViewModel { | |||
public boolean isUserLoggedIn(Context context){ | |||
return DataRepository.getRepositoryInstance().isUserLoggedIn(context); | |||
} | |||
public ObservableTunnel getTunnel(Context context) { | |||
return DataRepository.getRepositoryInstance().getTunnel(context); | |||
} | |||
} |