From 0cdf44a06b42506b57d56c7b15c8536ecd09f7ee Mon Sep 17 00:00:00 2001 From: Mushegh98 Date: Mon, 1 Jun 2020 19:38:35 +0400 Subject: [PATCH 1/3] Adds initViews and initListeners in MainActivity. --- .../android/activity/MainActivity.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/ui/src/main/java/com/wireguard/android/activity/MainActivity.java b/ui/src/main/java/com/wireguard/android/activity/MainActivity.java index 2a92821..f109bc7 100644 --- a/ui/src/main/java/com/wireguard/android/activity/MainActivity.java +++ b/ui/src/main/java/com/wireguard/android/activity/MainActivity.java @@ -4,11 +4,19 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.lifecycle.ViewModelProvider; import android.content.Intent; import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.TextView; + import com.wireguard.android.R; import com.wireguard.android.viewmodel.MainViewModel; public class MainActivity extends AppCompatActivity { private MainViewModel mainViewModel; + private TextView bubbleStatus; + private TextView deviceStatus; + private Button connectButton; @Override protected void onCreate(Bundle savedInstanceState) { @@ -21,5 +29,29 @@ public class MainActivity extends AppCompatActivity { startActivity(intent); finish(); } + initUI(); + } + + private void initUI() { + initViews(); + initListeners(); + } + + private void initViews() { + bubbleStatus = findViewById(R.id.bubbleStatus); + deviceStatus = findViewById(R.id.deviceStatus); + connectButton = findViewById(R.id.connectButton); + } + + private void initListeners() { + connectButton.setOnClickListener(new OnClickListener() { + @Override public void onClick(final View v) { + connect(); + } + }); + } + + private void connect() { + } } From a5dae8b19f003f65a19f09c674be00b4c02ad6fd Mon Sep 17 00:00:00 2001 From: Mushegh98 Date: Tue, 2 Jun 2020 19:12:50 +0400 Subject: [PATCH 2/3] Adds VPN Connection functionality. --- .../android/activity/MainActivity.java | 57 +++++++++++++++++-- .../android/repository/DataRepository.java | 34 ++++++++++- .../wireguard/android/util/TunnelStore.java | 47 +++++++++++++++ .../android/viewmodel/MainViewModel.java | 6 ++ 4 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 ui/src/main/java/com/wireguard/android/util/TunnelStore.java diff --git a/ui/src/main/java/com/wireguard/android/activity/MainActivity.java b/ui/src/main/java/com/wireguard/android/activity/MainActivity.java index f109bc7..7862bfe 100644 --- a/ui/src/main/java/com/wireguard/android/activity/MainActivity.java +++ b/ui/src/main/java/com/wireguard/android/activity/MainActivity.java @@ -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; + } } } diff --git a/ui/src/main/java/com/wireguard/android/repository/DataRepository.java b/ui/src/main/java/com/wireguard/android/repository/DataRepository.java index 8ab2f40..fbc8215 100644 --- a/ui/src/main/java/com/wireguard/android/repository/DataRepository.java +++ b/ui/src/main/java/com/wireguard/android/repository/DataRepository.java @@ -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; + } } diff --git a/ui/src/main/java/com/wireguard/android/util/TunnelStore.java b/ui/src/main/java/com/wireguard/android/util/TunnelStore.java new file mode 100644 index 0000000..0458af8 --- /dev/null +++ b/ui/src/main/java/com/wireguard/android/util/TunnelStore.java @@ -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); + } +} diff --git a/ui/src/main/java/com/wireguard/android/viewmodel/MainViewModel.java b/ui/src/main/java/com/wireguard/android/viewmodel/MainViewModel.java index 96591f3..738de9b 100644 --- a/ui/src/main/java/com/wireguard/android/viewmodel/MainViewModel.java +++ b/ui/src/main/java/com/wireguard/android/viewmodel/MainViewModel.java @@ -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); + } } From 84b9ee9bcdaaf2fe85f39669cc7edeb376d4f8d5 Mon Sep 17 00:00:00 2001 From: Mushegh98 Date: Wed, 3 Jun 2020 18:19:47 +0400 Subject: [PATCH 3/3] Refactored code. --- .../android/activity/MainActivity.java | 24 +++++----- .../android/repository/DataRepository.java | 47 ++++++++----------- .../wireguard/android/util/TunnelStore.java | 7 +-- .../com/wireguard/android/util/UserStore.java | 9 ++-- 4 files changed, 37 insertions(+), 50 deletions(-) diff --git a/ui/src/main/java/com/wireguard/android/activity/MainActivity.java b/ui/src/main/java/com/wireguard/android/activity/MainActivity.java index 7862bfe..983eafb 100644 --- a/ui/src/main/java/com/wireguard/android/activity/MainActivity.java +++ b/ui/src/main/java/com/wireguard/android/activity/MainActivity.java @@ -67,18 +67,20 @@ public class MainActivity extends AppCompatActivity { } 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; - } + if(pendingTunnel!=null) { + 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); + }); } - setTunnelStateWithPermissionsResult(tunnel, checked); - }); } diff --git a/ui/src/main/java/com/wireguard/android/repository/DataRepository.java b/ui/src/main/java/com/wireguard/android/repository/DataRepository.java index fbc8215..6f7a2a7 100644 --- a/ui/src/main/java/com/wireguard/android/repository/DataRepository.java +++ b/ui/src/main/java/com/wireguard/android/repository/DataRepository.java @@ -1,7 +1,6 @@ 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; @@ -11,7 +10,6 @@ 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; @@ -143,8 +141,7 @@ public class DataRepository { final String[] myDeviceName = deviceName.split(SEPARATOR); if (deviceNameItem.length > 1) { if (deviceNameItem[ANDROID_ID].equals(myDeviceName[ANDROID_ID])) { - UserStore.getInstance(context).setDeviceName(device.getName()); - UserStore.getInstance(context).setDeviceID(device.getUuid()); + UserStore.getInstance(context).setDevice(device.getName(), device.getUuid()); hasDevice = true; getConfig(context); break; @@ -169,8 +166,7 @@ public class DataRepository { .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(device -> { - UserStore.getInstance(context).setDeviceName(device.getName()); - UserStore.getInstance(context).setDeviceID(device.getUuid()); + UserStore.getInstance(context).setDevice(device.getName(), device.getUuid()); getConfig(context); }, throwable -> { setMutableLiveData(StatusResource.error(throwable.getMessage())); @@ -208,8 +204,7 @@ public class DataRepository { .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(device -> { - UserStore.getInstance(context).setDeviceName(device.getName()); - UserStore.getInstance(context).setDeviceID(device.getUuid()); + UserStore.getInstance(context).setDevice(device.getName(), device.getUuid()); getConfig(context); }, throwable -> { setMutableLiveData(StatusResource.error(throwable.getMessage())); @@ -240,32 +235,27 @@ public class DataRepository { final InputStream inputStream = response.body().byteStream(); final Scanner scanner = new Scanner(inputStream).useDelimiter(DELIMITER); final String data = scanner.hasNext() ? scanner.next() : ""; - parseConfig(data); + createTunnel(data, tunnelName); } }); } - private void parseConfig(String data) { + private void createTunnel(String rawConfig, String tunnelName) { try { - final byte[] configText = data.getBytes(); - final Config config = Config.parse(new ByteArrayInputStream(configText)); - createTunnel(config, tunnelName, data); + final byte[] configBytes = rawConfig.getBytes(); + final Config config = Config.parse(new ByteArrayInputStream(configBytes)); + Application.getTunnelManager().create(tunnelName, config).whenComplete((observableTunnel, throwable) -> { + if (observableTunnel != null) { + TunnelStore.getInstance(context).setTunnel(tunnelName, rawConfig); + setMutableLiveData(StatusResource.success()); + } else { + setMutableLiveData(StatusResource.error(throwable.getMessage())); + } + }); } catch (Exception e) { postMutableLiveData(StatusResource.error(e.getMessage())); } } - - 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())); - } - }); - } }.getMutableLiveData(); } @@ -310,14 +300,15 @@ public class DataRepository { } - public ObservableTunnel getTunnel(Context context){ + public ObservableTunnel getTunnel(Context context) { + //TODO implement config is null case Config config = null; try { config = parseConfig(TunnelStore.getInstance(context).getConfig()); } catch (final IOException | BadConfigException e) { - e.printStackTrace(); + return null; } - final String name = TunnelStore.getInstance(context).getTunnelName(); + 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; diff --git a/ui/src/main/java/com/wireguard/android/util/TunnelStore.java b/ui/src/main/java/com/wireguard/android/util/TunnelStore.java index 0458af8..d57914d 100644 --- a/ui/src/main/java/com/wireguard/android/util/TunnelStore.java +++ b/ui/src/main/java/com/wireguard/android/util/TunnelStore.java @@ -29,18 +29,15 @@ public class TunnelStore { sharedPreferences = context.getSharedPreferences(TUNNEL_SHARED_PREF, Context.MODE_PRIVATE); } - public void setTunnelName(String tunnelName){ + public void setTunnel(String tunnelName , String config){ sharedPreferences.edit().putString(TUNNEL_DATA_KEY,tunnelName).apply(); + sharedPreferences.edit().putString(CONFIG_DATA_KEY,config).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); } diff --git a/ui/src/main/java/com/wireguard/android/util/UserStore.java b/ui/src/main/java/com/wireguard/android/util/UserStore.java index 8537f31..58eac38 100644 --- a/ui/src/main/java/com/wireguard/android/util/UserStore.java +++ b/ui/src/main/java/com/wireguard/android/util/UserStore.java @@ -39,18 +39,15 @@ public class UserStore { return sharedPreferences.getString(USER_DATA_KEY, USER_TOKEN_DEFAULT_VALUE); } - public void setDeviceName(String device){ - sharedPreferences.edit().putString(DEVICE_DATA_KEY, device).apply(); + public void setDevice(String deviceName, String deviceID){ + sharedPreferences.edit().putString(DEVICE_DATA_KEY, deviceName).apply(); + sharedPreferences.edit().putString(DEVICE_ID_KEY,deviceID).apply(); } public String getDeviceName(){ return sharedPreferences.getString(DEVICE_DATA_KEY, DEVICE_DEFAULT_VALUE); } - public void setDeviceID(String id){ - sharedPreferences.edit().putString(DEVICE_ID_KEY,id).apply(); - } - public String getDeviceID(){ return sharedPreferences.getString(DEVICE_ID_KEY,DEVICE_ID_DEFAULT_VALUE); }