diff --git a/Pub/PubVersion.json b/Pub/PubVersion.json
index c288d9c9d..001665065 100644
--- a/Pub/PubVersion.json
+++ b/Pub/PubVersion.json
@@ -1,6 +1,6 @@
 {
-  "Version": "3.3.470",
-  "BumpTime": "2024-02-16T20:19:54.5087389Z",
+  "Version": "3.3.471",
+  "BumpTime": "2024-02-28T07:21:16.2620690Z",
   "Prerelease": false,
   "DeprecatedVersion": "3.0.416"
 }
diff --git a/Samples/VpnHood.Samples.SimpleClient.Win/VpnHood.Samples.SimpleClient.Win.csproj b/Samples/VpnHood.Samples.SimpleClient.Win/VpnHood.Samples.SimpleClient.Win.csproj
index d2cb81e1f..c3e68d04b 100644
--- a/Samples/VpnHood.Samples.SimpleClient.Win/VpnHood.Samples.SimpleClient.Win.csproj
+++ b/Samples/VpnHood.Samples.SimpleClient.Win/VpnHood.Samples.SimpleClient.Win.csproj
@@ -24,8 +24,8 @@
 	</PropertyGroup>
 
 	<ItemGroup>
-		<PackageReference Include="VpnHood.Client" Version="3.3.456" />
-		<PackageReference Include="VpnHood.Client.Device.WinDivert" Version="3.3.456" />
+		<PackageReference Include="VpnHood.Client" Version="3.3.470" />
+		<PackageReference Include="VpnHood.Client.Device.WinDivert" Version="3.3.470" />
 	</ItemGroup>
 
 </Project>
diff --git a/Tests/VpnHood.Test/VpnHood.Test.csproj b/Tests/VpnHood.Test/VpnHood.Test.csproj
index 3d3b49e86..99016c848 100644
--- a/Tests/VpnHood.Test/VpnHood.Test.csproj
+++ b/Tests/VpnHood.Test/VpnHood.Test.csproj
@@ -25,10 +25,10 @@
 	<ItemGroup>
 		<PackageReference Include="EmbedIO" Version="3.5.2" />
 		<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
-		<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
-		<PackageReference Include="MSTest.TestAdapter" Version="3.2.0" />
-		<PackageReference Include="MSTest.TestFramework" Version="3.2.0" />
-		<PackageReference Include="coverlet.collector" Version="6.0.0">
+		<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
+		<PackageReference Include="MSTest.TestAdapter" Version="3.2.2" />
+		<PackageReference Include="MSTest.TestFramework" Version="3.2.2" />
+		<PackageReference Include="coverlet.collector" Version="6.0.1">
 			<PrivateAssets>all</PrivateAssets>
 			<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
 		</PackageReference>
diff --git a/Tests/VpnHood.UdpTrafficTest/VpnHood.UdpTrafficTest.csproj b/Tests/VpnHood.UdpTrafficTest/VpnHood.UdpTrafficTest.csproj
index c49f857c9..556353d7e 100644
--- a/Tests/VpnHood.UdpTrafficTest/VpnHood.UdpTrafficTest.csproj
+++ b/Tests/VpnHood.UdpTrafficTest/VpnHood.UdpTrafficTest.csproj
@@ -23,7 +23,7 @@
 	</PropertyGroup>
 
 	<ItemGroup>
-		<PackageReference Include="VpnHood.Common" Version="3.3.456" />
+		<PackageReference Include="VpnHood.Common" Version="3.3.470" />
 	</ItemGroup>
 
 </Project>
diff --git a/VpnHood.Client.App.Android.Common/Activities/AndroidAppMainActivity.cs b/VpnHood.Client.App.Android.Common/Activities/AndroidAppMainActivity.cs
index d754a861e..665885aa1 100644
--- a/VpnHood.Client.App.Android.Common/Activities/AndroidAppMainActivity.cs
+++ b/VpnHood.Client.App.Android.Common/Activities/AndroidAppMainActivity.cs
@@ -1,135 +1,48 @@
-using Android;
-using Android.Content;
+using Android.Content;
 using Android.Content.PM;
 using Android.Runtime;
-using VpnHood.Client.App.Abstractions;
-using VpnHood.Client.Device.Droid;
-using VpnHood.Client.Device.Droid.Utils;
+using Android.Views;
 
 namespace VpnHood.Client.App.Droid.Common.Activities;
 
-public abstract class AndroidAppMainActivity : ActivityEvent
+public abstract class AndroidAppMainActivity : Activity
 {
-    private TaskCompletionSource<Permission>? _requestPostNotificationsCompletionTask;
-    protected const int RequestPostNotificationId = 11;
-    protected AndroidDevice VpnDevice => AndroidDevice.Current ?? throw new InvalidOperationException($"{nameof(AndroidDevice)} has not been initialized.");
-    protected string[] AccessKeySchemes { get; set; } = Array.Empty<string>();
-    protected string[] AccessKeyMimes { get; set; } = Array.Empty<string>();
-    protected abstract IAppUpdaterService? CreateAppUpdaterService();
+    private AndroidAppMainActivityHandler _mainActivityHandler = default!;
+    protected abstract AndroidAppMainActivityHandler CreateMainActivityHandler();
 
     protected override void OnCreate(Bundle? savedInstanceState)
     {
         base.OnCreate(savedInstanceState);
-        VpnDevice.Prepare(this);
-
-        // process intent
-        ProcessIntent(Intent);
-    }
-
-    protected async Task RequestFeatures()
-    {
-        // request for adding tile
-        if (!VpnHoodApp.Instance.Settings.IsQuickLaunchRequested &&
-            OperatingSystem.IsAndroidVersionAtLeast(33))
-        {
-            VpnHoodApp.Instance.Settings.IsQuickLaunchRequested = true;
-            VpnHoodApp.Instance.Settings.Save();
-            await QuickLaunchTileService.RequestAddTile(this);
-        }
-
-        // request for notification
-        if (OperatingSystem.IsAndroidVersionAtLeast(33) && CheckSelfPermission(Manifest.Permission.PostNotifications) != Permission.Granted)
-        {
-            _requestPostNotificationsCompletionTask = new TaskCompletionSource<Permission>();
-            RequestPermissions([Manifest.Permission.PostNotifications], RequestPostNotificationId);
-            await _requestPostNotificationsCompletionTask.Task;
-        }
-
-        // Check for update
-        var appUpdaterService = CreateAppUpdaterService();
-        VpnHoodApp.Instance.AppUpdaterService = appUpdaterService;
-        if (VpnHoodApp.Instance.VersionCheckRequired && appUpdaterService != null && await appUpdaterService.Update())
-            VpnHoodApp.Instance.VersionCheckPostpone(); // postpone check if check succeeded
+        _mainActivityHandler = CreateMainActivityHandler();
+        _mainActivityHandler.OnCreate(savedInstanceState);
     }
 
     protected override void OnNewIntent(Intent? intent)
     {
-        if (!ProcessIntent(intent))
+        if (!_mainActivityHandler.OnNewIntent(intent))
             base.OnNewIntent(intent);
     }
 
-    private bool ProcessIntent(Intent? intent)
+    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
     {
-        if (intent?.Data == null || ContentResolver == null)
-            return false;
-
-        // try to add the access key
-        try
-        {
-            var uri = intent.Data;
-            if (AccessKeySchemes.Contains(uri.Scheme, StringComparer.OrdinalIgnoreCase))
-            {
-                ImportAccessKey(uri.ToString()!);
-                return true;
-            }
-
-            // check mime
-            var mimeType = ContentResolver.GetType(uri);
-            if (!AccessKeyMimes.Contains(mimeType, StringComparer.OrdinalIgnoreCase))
-            {
-                Toast.MakeText(this, VpnHoodApp.Instance.Resources.Strings.MsgUnsupportedContent, ToastLength.Long)?.Show();
-                return false;
-            }
-
-            // open stream
-            using var inputStream = ContentResolver.OpenInputStream(uri);
-            if (inputStream == null)
-                throw new Exception("Can not open the intent file stream.");
-
-            // read string into buffer maximum 5k
-            var buffer = new byte[5 * 1024];
-            var length = inputStream.Read(buffer);
-            using var memoryStream = new MemoryStream(buffer, 0, length);
-            var streamReader = new StreamReader(memoryStream);
-            var accessKey = streamReader.ReadToEnd();
-
-            ImportAccessKey(accessKey);
-        }
-        catch
-        {
-            Toast.MakeText(this, VpnHoodApp.Instance.Resources.Strings.MsgCantReadAccessKey, ToastLength.Long)?.Show();
-        }
-
-        return true;
+        _mainActivityHandler.OnRequestPermissionsResult(requestCode, permissions, grantResults);
+        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
     }
 
-    protected void ImportAccessKey(string accessKey)
+    protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent? data)
     {
-        var profiles = VpnHoodApp.Instance.ClientProfileService.List();
-        var profile = VpnHoodApp.Instance.ClientProfileService.ImportAccessKey(accessKey).ToInfo();
-        _ = VpnHoodApp.Instance.Disconnect(true);
-        VpnHoodApp.Instance.UserSettings.DefaultClientProfileId = profile.ClientProfileId;
-
-        var isNew = profiles.Any(x => x.ClientProfileId == profile.ClientProfileId);
-        var message = isNew
-            ? string.Format(VpnHoodApp.Instance.Resources.Strings.MsgAccessKeyAdded, profile.ClientProfileName)
-            : string.Format(VpnHoodApp.Instance.Resources.Strings.MsgAccessKeyUpdated, profile.ClientProfileName);
-
-        Toast.MakeText(this, message, ToastLength.Long)?.Show();
+        _mainActivityHandler.OnActivityResult(requestCode, resultCode, data);
+        base.OnActivityResult(requestCode, resultCode, data);
     }
 
-    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
+    public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent? e)
     {
-        var postNotificationsIndex = Array.IndexOf(permissions, Manifest.Permission.PostNotifications);
-        if (postNotificationsIndex != -1 && _requestPostNotificationsCompletionTask != null)
-            _requestPostNotificationsCompletionTask.TrySetResult(grantResults[postNotificationsIndex]);
-
-        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
+        return _mainActivityHandler.OnKeyDown(keyCode, e) || base.OnKeyDown(keyCode, e);
     }
 
     protected override void OnDestroy()
     {
-        VpnHoodApp.Instance.AppUpdaterService = null;
+        _mainActivityHandler.OnDestroy();
         base.OnDestroy();
     }
 }
diff --git a/VpnHood.Client.App.Android.Common/Activities/AndroidAppMainActivityHandler.cs b/VpnHood.Client.App.Android.Common/Activities/AndroidAppMainActivityHandler.cs
new file mode 100644
index 000000000..1ab422f43
--- /dev/null
+++ b/VpnHood.Client.App.Android.Common/Activities/AndroidAppMainActivityHandler.cs
@@ -0,0 +1,152 @@
+using Android;
+using Android.Content;
+using Android.Content.PM;
+using Android.Runtime;
+using Android.Views;
+using VpnHood.Client.App.Abstractions;
+using VpnHood.Client.Device.Droid;
+using VpnHood.Client.Device.Droid.Utils;
+
+namespace VpnHood.Client.App.Droid.Common.Activities;
+
+public class AndroidAppMainActivityHandler(
+    Activity activity, 
+    AndroidMainActivityOptions options) 
+    : IActivityEvent
+{
+    private TaskCompletionSource<Permission>? _requestPostNotificationsCompletionTask;
+    private readonly string[] _accessKeySchemes = options.AccessKeySchemes;
+    private readonly string[] _accessKeyMimes = options.AccessKeySchemes;
+    private readonly IAppUpdaterService? _appUpdaterService = options.AppUpdaterService;
+    private const int RequestPostNotificationId = 11;
+    protected AndroidDevice VpnDevice => AndroidDevice.Current ?? throw new InvalidOperationException($"{nameof(AndroidDevice)} has not been initialized.");
+    protected Activity Activity { get; } = activity;
+    public event EventHandler<ActivityResultEventArgs>? OnActivityResultEvent;
+    public event EventHandler? OnDestroyEvent;
+
+    public virtual void OnCreate(Bundle? savedInstanceState)
+    {
+        VpnDevice.Prepare(Activity, this);
+
+        // process intent
+        ProcessIntent(Activity.Intent);
+    }
+
+    protected async Task RequestFeatures()
+    {
+        // request for adding tile
+        if (!VpnHoodApp.Instance.Settings.IsQuickLaunchRequested &&
+            OperatingSystem.IsAndroidVersionAtLeast(33))
+        {
+            VpnHoodApp.Instance.Settings.IsQuickLaunchRequested = true;
+            VpnHoodApp.Instance.Settings.Save();
+            await QuickLaunchTileService.RequestAddTile(Activity);
+        }
+
+        // request for notification
+        if (OperatingSystem.IsAndroidVersionAtLeast(33) && Activity.CheckSelfPermission(Manifest.Permission.PostNotifications) != Permission.Granted)
+        {
+            _requestPostNotificationsCompletionTask = new TaskCompletionSource<Permission>();
+            Activity.RequestPermissions([Manifest.Permission.PostNotifications], RequestPostNotificationId);
+            await _requestPostNotificationsCompletionTask.Task;
+        }
+
+        // Check for update
+        VpnHoodApp.Instance.AppUpdaterService = _appUpdaterService;
+        if (VpnHoodApp.Instance.VersionCheckRequired && _appUpdaterService != null && await _appUpdaterService.Update())
+            VpnHoodApp.Instance.VersionCheckPostpone(); // postpone check if check succeeded
+    }
+
+    public bool OnNewIntent(Intent? intent)
+    {
+        return ProcessIntent(intent);
+    }
+
+    private bool ProcessIntent(Intent? intent)
+    {
+        if (intent?.Data == null || Activity.ContentResolver == null)
+            return false;
+
+        // try to add the access key
+        try
+        {
+            var uri = intent.Data;
+            if (_accessKeySchemes.Contains(uri.Scheme, StringComparer.OrdinalIgnoreCase))
+            {
+                ImportAccessKey(uri.ToString()!);
+                return true;
+            }
+
+            // check mime
+            var mimeType = Activity.ContentResolver.GetType(uri);
+            if (!_accessKeyMimes.Contains(mimeType, StringComparer.OrdinalIgnoreCase))
+            {
+                Toast.MakeText(Activity, VpnHoodApp.Instance.Resources.Strings.MsgUnsupportedContent, ToastLength.Long)?.Show();
+                return false;
+            }
+
+            // open stream
+            using var inputStream = Activity.ContentResolver.OpenInputStream(uri);
+            if (inputStream == null)
+                throw new Exception("Can not open the intent file stream.");
+
+            // read string into buffer maximum 5k
+            var buffer = new byte[5 * 1024];
+            var length = inputStream.Read(buffer);
+            using var memoryStream = new MemoryStream(buffer, 0, length);
+            var streamReader = new StreamReader(memoryStream);
+            var accessKey = streamReader.ReadToEnd();
+
+            ImportAccessKey(accessKey);
+        }
+        catch
+        {
+            Toast.MakeText(Activity, VpnHoodApp.Instance.Resources.Strings.MsgCantReadAccessKey, ToastLength.Long)?.Show();
+        }
+
+        return true;
+    }
+
+    protected void ImportAccessKey(string accessKey)
+    {
+        var profiles = VpnHoodApp.Instance.ClientProfileService.List();
+        var profile = VpnHoodApp.Instance.ClientProfileService.ImportAccessKey(accessKey).ToInfo();
+        _ = VpnHoodApp.Instance.Disconnect(true);
+        VpnHoodApp.Instance.UserSettings.DefaultClientProfileId = profile.ClientProfileId;
+
+        var isNew = profiles.Any(x => x.ClientProfileId == profile.ClientProfileId);
+        var message = isNew
+            ? string.Format(VpnHoodApp.Instance.Resources.Strings.MsgAccessKeyAdded, profile.ClientProfileName)
+            : string.Format(VpnHoodApp.Instance.Resources.Strings.MsgAccessKeyUpdated, profile.ClientProfileName);
+
+        Toast.MakeText(Activity, message, ToastLength.Long)?.Show();
+    }
+
+    public void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
+    {
+        var postNotificationsIndex = Array.IndexOf(permissions, Manifest.Permission.PostNotifications);
+        if (postNotificationsIndex != -1 && _requestPostNotificationsCompletionTask != null)
+            _requestPostNotificationsCompletionTask.TrySetResult(grantResults[postNotificationsIndex]);
+    }
+
+    public virtual bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent? e)
+    {
+        return false;
+    }
+
+    public virtual void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent? data)
+    {
+        OnActivityResultEvent?.Invoke(this, new ActivityResultEventArgs
+        {
+            RequestCode = requestCode,
+            ResultCode = resultCode,
+            Data = data
+        });
+    }
+
+    public virtual void OnDestroy()
+    {
+        OnDestroyEvent?.Invoke(this, EventArgs.Empty);
+        VpnHoodApp.Instance.AppUpdaterService = null;
+    }
+}
\ No newline at end of file
diff --git a/VpnHood.Client.App.Android.Common/Activities/AndroidAppWebViewMainActivity.cs b/VpnHood.Client.App.Android.Common/Activities/AndroidAppWebViewMainActivityHandler.cs
similarity index 80%
rename from VpnHood.Client.App.Android.Common/Activities/AndroidAppWebViewMainActivity.cs
rename to VpnHood.Client.App.Android.Common/Activities/AndroidAppWebViewMainActivityHandler.cs
index 1591cfd0d..f36cbcc06 100644
--- a/VpnHood.Client.App.Android.Common/Activities/AndroidAppWebViewMainActivity.cs
+++ b/VpnHood.Client.App.Android.Common/Activities/AndroidAppWebViewMainActivityHandler.cs
@@ -5,14 +5,13 @@
 
 namespace VpnHood.Client.App.Droid.Common.Activities;
 
-public abstract class AndroidAppWebViewMainActivity : AndroidAppMainActivity
+public class AndroidAppWebViewMainActivityHandler(Activity activity, AndroidMainActivityWebViewOptions options)
+    : AndroidAppMainActivityHandler(activity, options)
 {
     private bool _isWeViewVisible;
     public WebView? WebView { get; private set; }
-    protected virtual bool ListenToAllIps => false;
-    protected virtual int? DefaultSpaPort => null;
 
-    protected override void OnCreate(Bundle? savedInstanceState)
+    public override void OnCreate(Bundle? savedInstanceState)
     {
         base.OnCreate(savedInstanceState);
 
@@ -24,14 +23,13 @@ protected override void OnCreate(Bundle? savedInstanceState)
         {
             ArgumentNullException.ThrowIfNull(VpnHoodApp.Instance.Resources.SpaZipData);
             using var memoryStream = new MemoryStream(VpnHoodApp.Instance.Resources.SpaZipData);
-            VpnHoodAppWebServer.Init(memoryStream, DefaultSpaPort, listenToAllIps: ListenToAllIps);
+            VpnHoodAppWebServer.Init(memoryStream, options.DefaultSpaPort, listenToAllIps: options.ListenToAllIps);
         }
 
         InitWebUi();
     }
 
-
-    protected override void OnDestroy()
+    public override void OnDestroy()
     {
         if (VpnHoodAppWebServer.IsInit)
             VpnHoodAppWebServer.Instance.Dispose();
@@ -41,7 +39,7 @@ protected override void OnDestroy()
 
     private void InitSplashScreen()
     {
-        var imageView = new ImageView(this);
+        var imageView = new ImageView(Activity);
         var appInfo = Application.Context.ApplicationInfo ?? throw new Exception("Could not retrieve app info");
         var backgroundColor = VpnHoodApp.Instance.Resources.Colors.WindowBackgroundColor?.ToAndroidColor();
 
@@ -51,19 +49,19 @@ private void InitSplashScreen()
         imageView.LayoutParameters = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent);
         imageView.SetScaleType(ImageView.ScaleType.CenterInside);
         if (backgroundColor != null) imageView.SetBackgroundColor(backgroundColor.Value);
-        SetContentView(imageView);
+        Activity.SetContentView(imageView);
 
         // set window background color
         if (backgroundColor != null)
         {
-            Window?.SetStatusBarColor(backgroundColor.Value);
-            Window?.SetNavigationBarColor(backgroundColor.Value);
+            Activity.Window?.SetStatusBarColor(backgroundColor.Value);
+            Activity.Window?.SetNavigationBarColor(backgroundColor.Value);
         }
     }
 
     private void InitWebUi()
     {
-        WebView = new WebView(this);
+        WebView = new WebView(Activity);
         WebView.Settings.JavaScriptEnabled = true;
         WebView.Settings.DomStorageEnabled = true;
         WebView.Settings.JavaScriptCanOpenWindowsAutomatically = true;
@@ -87,11 +85,11 @@ private void WebViewClient_PageLoaded(object? sender, EventArgs e)
     {
         if (_isWeViewVisible) return; // prevent double set SetContentView
         if (WebView == null) throw new Exception("WebView has not been loaded yet!");
-        SetContentView(WebView);
+        Activity.SetContentView(WebView);
         _isWeViewVisible = true;
 
         if (VpnHoodApp.Instance.Resources.Colors.NavigationBarColor != null)
-            Window?.SetNavigationBarColor(VpnHoodApp.Instance.Resources.Colors.NavigationBarColor.Value.ToAndroidColor());
+            Activity.Window?.SetNavigationBarColor(VpnHoodApp.Instance.Resources.Colors.NavigationBarColor.Value.ToAndroidColor());
 
         // request features after loading the webview, so SPA can update the localize the resources
         _ = RequestFeatures();
diff --git a/VpnHood.Client.App.Android.Common/Activities/AndroidMainActivityOptions.cs b/VpnHood.Client.App.Android.Common/Activities/AndroidMainActivityOptions.cs
new file mode 100644
index 000000000..1eb849f8a
--- /dev/null
+++ b/VpnHood.Client.App.Android.Common/Activities/AndroidMainActivityOptions.cs
@@ -0,0 +1,12 @@
+using VpnHood.Client.App.Abstractions;
+
+namespace VpnHood.Client.App.Droid.Common.Activities
+{
+    public class AndroidMainActivityOptions
+    {
+        public string[] AccessKeySchemes { get; init; } = Array.Empty<string>();
+        public string[] AccessKeyMimes { get; init; } = Array.Empty<string>();
+        public IAppUpdaterService? AppUpdaterService { get; init; }
+
+    }
+}
\ No newline at end of file
diff --git a/VpnHood.Client.App.Android.Common/Activities/AndroidMainActivityWebViewOptions.cs b/VpnHood.Client.App.Android.Common/Activities/AndroidMainActivityWebViewOptions.cs
new file mode 100644
index 000000000..b47363531
--- /dev/null
+++ b/VpnHood.Client.App.Android.Common/Activities/AndroidMainActivityWebViewOptions.cs
@@ -0,0 +1,7 @@
+namespace VpnHood.Client.App.Droid.Common.Activities;
+
+public class AndroidMainActivityWebViewOptions : AndroidMainActivityOptions
+{
+    public bool ListenToAllIps { get; init; }
+    public int? DefaultSpaPort { get; init; }
+}
\ No newline at end of file
diff --git a/VpnHood.Client.App.Android.Common/VpnHood.Client.App.Android.Common.csproj b/VpnHood.Client.App.Android.Common/VpnHood.Client.App.Android.Common.csproj
index 0be597798..41839278d 100644
--- a/VpnHood.Client.App.Android.Common/VpnHood.Client.App.Android.Common.csproj
+++ b/VpnHood.Client.App.Android.Common/VpnHood.Client.App.Android.Common.csproj
@@ -21,7 +21,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 		<BaseOutputPath></BaseOutputPath>
 		<BaseIntermediateOutputPath />
diff --git a/VpnHood.Client.App.Android.Connect/MainActivity.cs b/VpnHood.Client.App.Android.Connect/MainActivity.cs
index fe255972b..c26b99f94 100644
--- a/VpnHood.Client.App.Android.Connect/MainActivity.cs
+++ b/VpnHood.Client.App.Android.Connect/MainActivity.cs
@@ -1,9 +1,7 @@
-using System.Diagnostics.CodeAnalysis;
 using Android.Content;
 using Android.Content.PM;
 using Android.Service.QuickSettings;
 using Android.Views;
-using VpnHood.Client.App.Abstractions;
 using VpnHood.Client.App.Droid.Common.Activities;
 using VpnHood.Client.App.Droid.Connect.Properties;
 using VpnHood.Client.App.Droid.GooglePlay;
@@ -11,7 +9,8 @@
 
 namespace VpnHood.Client.App.Droid.Connect;
 
-[Activity(Label = "@string/app_name",
+[Activity(
+    Label = "@string/app_name",
     Theme = "@android:style/Theme.DeviceDefault.NoActionBar",
     MainLauncher = true,
     Exported = true,
@@ -25,15 +24,14 @@ namespace VpnHood.Client.App.Droid.Connect;
 
 [IntentFilter([Intent.ActionMain], Categories = [Intent.CategoryLauncher, Intent.CategoryLeanbackLauncher])]
 [IntentFilter([TileService.ActionQsTilePreferences])]
-[SuppressMessage("ReSharper", "UnusedMember.Global")]
-public class MainActivity : AndroidAppWebViewMainActivity
+public class MainActivity : AndroidAppMainActivity
 {
-    protected override bool ListenToAllIps => AssemblyInfo.ListenToAllIps;
-    protected override int? DefaultSpaPort => AssemblyInfo.DefaultSpaPort;
-
-    protected override IAppUpdaterService CreateAppUpdaterService()
+    protected override AndroidAppMainActivityHandler CreateMainActivityHandler()
     {
-        return new GooglePlayAppUpdaterService(this);
+        return new AndroidAppWebViewMainActivityHandler(this, new AndroidMainActivityWebViewOptions
+        {
+            AppUpdaterService = new GooglePlayAppUpdaterService(this)
+        });
     }
 
     protected override void OnCreate(Bundle? savedInstanceState)
@@ -52,5 +50,4 @@ protected override void OnDestroy()
         VpnHoodApp.Instance.AccountService = null;
         base.OnDestroy();
     }
-
 }
\ No newline at end of file
diff --git a/VpnHood.Client.App.Android.Connect/VpnHood.Client.App.Android.Connect.csproj b/VpnHood.Client.App.Android.Connect/VpnHood.Client.App.Android.Connect.csproj
index 70c7e14c9..0dcfad30f 100644
--- a/VpnHood.Client.App.Android.Connect/VpnHood.Client.App.Android.Connect.csproj
+++ b/VpnHood.Client.App.Android.Connect/VpnHood.Client.App.Android.Connect.csproj
@@ -47,7 +47,7 @@
 	</ItemGroup>
 
 	<ItemGroup>
-		<PackageReference Include="VpnHood.Store.Api" Version="1.0.32-alpha" />
+		<PackageReference Include="VpnHood.Store.Api" Version="1.0.32" />
 	</ItemGroup>
 
 </Project>
\ No newline at end of file
diff --git a/VpnHood.Client.App.Android.GooglePlay.Core/VpnHood.Client.App.Android.GooglePlay.Core.csproj b/VpnHood.Client.App.Android.GooglePlay.Core/VpnHood.Client.App.Android.GooglePlay.Core.csproj
index b3487e94a..4d18c6be3 100644
--- a/VpnHood.Client.App.Android.GooglePlay.Core/VpnHood.Client.App.Android.GooglePlay.Core.csproj
+++ b/VpnHood.Client.App.Android.GooglePlay.Core/VpnHood.Client.App.Android.GooglePlay.Core.csproj
@@ -21,7 +21,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 		<BaseOutputPath></BaseOutputPath>
 		<BaseIntermediateOutputPath />
diff --git a/VpnHood.Client.App.Android.GooglePlay/VpnHood.Client.App.Android.GooglePlay.csproj b/VpnHood.Client.App.Android.GooglePlay/VpnHood.Client.App.Android.GooglePlay.csproj
index 7e0cd2a93..b9eebeeda 100644
--- a/VpnHood.Client.App.Android.GooglePlay/VpnHood.Client.App.Android.GooglePlay.csproj
+++ b/VpnHood.Client.App.Android.GooglePlay/VpnHood.Client.App.Android.GooglePlay.csproj
@@ -21,7 +21,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 		<BaseOutputPath></BaseOutputPath>
 		<BaseIntermediateOutputPath />
diff --git a/VpnHood.Client.App.Android/MainActivity.cs b/VpnHood.Client.App.Android/MainActivity.cs
index 19cbd0132..39e5b897b 100644
--- a/VpnHood.Client.App.Android/MainActivity.cs
+++ b/VpnHood.Client.App.Android/MainActivity.cs
@@ -1,14 +1,13 @@
-using System.Diagnostics.CodeAnalysis;
-using Android.Content;
+using Android.Content;
 using Android.Content.PM;
 using Android.Service.QuickSettings;
 using Android.Views;
-using VpnHood.Client.App.Abstractions;
 using VpnHood.Client.App.Droid.Common.Activities;
 
 namespace VpnHood.Client.App.Droid;
 
-[Activity(Label = "@string/app_name",
+[Activity(
+    Label = "@string/app_name",
     Theme = "@android:style/Theme.DeviceDefault.NoActionBar",
     MainLauncher = true,
     Exported = true,
@@ -24,31 +23,26 @@ namespace VpnHood.Client.App.Droid;
 [IntentFilter([Intent.ActionMain], Categories = [Intent.CategoryLauncher, Intent.CategoryLeanbackLauncher])]
 [IntentFilter([Intent.ActionView], Categories = [Intent.CategoryDefault], DataScheme = "content", DataMimeTypes = [AccessKeyMime1, AccessKeyMime2, AccessKeyMime3])]
 [IntentFilter([Intent.ActionView], Categories = [Intent.CategoryDefault, Intent.CategoryBrowsable], DataSchemes = [AccessKeyScheme1, AccessKeyScheme2])]
-[SuppressMessage("ReSharper", "UnusedMember.Global")]
-public class MainActivity : AndroidAppWebViewMainActivity
+public class MainActivity : AndroidAppMainActivity
 {
     // https://android.googlesource.com/platform/libcore/+/android-5.0.2_r1/luni/src/main/java/libcore/net/MimeUtils.java
     public const string AccessKeyScheme1 = "vh";
     public const string AccessKeyScheme2 = "vhkey";
-    public const string AccessKeyMime1 = "application/vhkey"; 
+    public const string AccessKeyMime1 = "application/vhkey";
     public const string AccessKeyMime2 = "application/pgp-keys"; //.key
     public const string AccessKeyMime3 = "application/vnd.cinderella"; //.cdy
 
-    public MainActivity()
+    protected override AndroidAppMainActivityHandler CreateMainActivityHandler()
     {
-        AccessKeySchemes = [AccessKeyScheme1, AccessKeyScheme2];
-        AccessKeyMimes = [AccessKeyMime1, AccessKeyMime2, AccessKeyMime3];
-    }
-
-
-    // ReSharper disable once ReturnTypeCanBeNotNullable
-    protected override IAppUpdaterService? CreateAppUpdaterService()
-    {
-#if  GOOGLE_PLAY
-        // ReSharper disable once RedundantNameQualifier
-        return new VpnHood.Client.App.Droid.GooglePlay.GooglePlayAppUpdaterService(this);
+        return new AndroidAppWebViewMainActivityHandler(this, new AndroidMainActivityWebViewOptions
+        {
+            AccessKeySchemes = [AccessKeyScheme1, AccessKeyScheme2],
+            AccessKeyMimes = [AccessKeyMime1, AccessKeyMime2, AccessKeyMime3],
+#if GOOGLE_PLAY
+            AppUpdaterService = new GooglePlay.GooglePlayAppUpdaterService(this)
 #else
-        return null;
+            AppUpdaterService = null
 #endif
+        });
     }
 }
diff --git a/VpnHood.Client.App.Maui/MauiProgram.cs b/VpnHood.Client.App.Maui/MauiProgram.cs
index e4ddac3b3..36e3ae388 100644
--- a/VpnHood.Client.App.Maui/MauiProgram.cs
+++ b/VpnHood.Client.App.Maui/MauiProgram.cs
@@ -1,6 +1,8 @@
 using Microsoft.Extensions.Logging;
 using VpnHood.Client.App.Resources;
-using VpnHood.Client.App.WebServer;
+using VpnHood.Client.Device;
+using VpnHood.Client.Device.WinDivert;
+
 namespace VpnHood.Client.App.Maui;
 
 public static class MauiProgram
@@ -20,18 +22,16 @@ public static MauiApp CreateMauiApp()
         builder.Logging.AddDebug();
 #endif
 
-        var appProvider = CreateAppProvider();
-        using var spaResource = new MemoryStream(UiResource.SPA);
-        VpnHoodApp.Init(appProvider, new AppOptions());
-        VpnHoodAppWebServer.Init(spaResource, url2: appProvider.AdditionalUiUrl);
+        var resources = VpnHoodAppResource.Resources;
+        VpnHoodApp.Init(CreateDevice(), new AppOptions() { Resources = resources });
 
         return builder.Build();
     }
 
-    private static IAppProvider CreateAppProvider()
+    private static IDevice CreateDevice()
     {
 #if WINDOWS
-        return new WinAppProvider();
+        return new WinDivertDevice();
 #elif ANDROID
         return new AppProvider();
 #else
diff --git a/VpnHood.Client.App.Maui/Platforms/Windows/WinAppProvider.cs b/VpnHood.Client.App.Maui/Platforms/Windows/WinAppProvider.cs
deleted file mode 100644
index 5f6380119..000000000
--- a/VpnHood.Client.App.Maui/Platforms/Windows/WinAppProvider.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using VpnHood.Client.Device;
-using VpnHood.Client.Device.WinDivert;
-
-// ReSharper disable once CheckNamespace
-namespace VpnHood.Client.App.Maui;
-
-public class WinAppProvider : IAppProvider
-{
-    public IDevice Device { get; } = new WinDivertDevice();
-    public bool IsLogToConsoleSupported => false;
-    public Uri? AdditionalUiUrl => WinApp.Instance.RegisterLocalDomain();
-
-    public Uri UpdateInfoUrl => new ("https://github.com/vpnhood/VpnHood/releases/latest/download/VpnHoodClient-win-x64.json");
-}
\ No newline at end of file
diff --git a/VpnHood.Client.App.Maui/VpnHood.Client.App.Maui.csproj b/VpnHood.Client.App.Maui/VpnHood.Client.App.Maui.csproj
index 9f6deeb3c..444bebf17 100644
--- a/VpnHood.Client.App.Maui/VpnHood.Client.App.Maui.csproj
+++ b/VpnHood.Client.App.Maui/VpnHood.Client.App.Maui.csproj
@@ -1,8 +1,8 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
 	<PropertyGroup>
-		<TargetFrameworks>net7.0-android</TargetFrameworks>
-		<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
+		<TargetFrameworks>net8.0-android</TargetFrameworks>
+		<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
 		<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
 		<!-- <TargetFrameworks>$(TargetFrameworks);net7.0-tizen</TargetFrameworks> -->
 		<OutputType>Exe</OutputType>
@@ -71,8 +71,8 @@
 	</ItemGroup>
 
 	<ItemGroup>
-		<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
-		<PackageReference Include="System.Resources.Extensions" Version="7.0.0" />
+		<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
+		<PackageReference Include="System.Resources.Extensions" Version="8.0.0" />
 	</ItemGroup>
 
 	<ItemGroup>
@@ -131,4 +131,14 @@
 	  </None>
 	</ItemGroup>
 
+
+	<ItemGroup>
+	  <PackageReference Update="Microsoft.Maui.Controls" Version="8.0.7" />
+	</ItemGroup>
+
+
+	<ItemGroup>
+	  <PackageReference Update="Microsoft.Maui.Controls.Compatibility" Version="8.0.7" />
+	</ItemGroup>
+
 </Project>
diff --git a/VpnHood.Client.App.Resources/VpnHood.Client.App.Resources.csproj b/VpnHood.Client.App.Resources/VpnHood.Client.App.Resources.csproj
index efafaacbe..f154fd706 100644
--- a/VpnHood.Client.App.Resources/VpnHood.Client.App.Resources.csproj
+++ b/VpnHood.Client.App.Resources/VpnHood.Client.App.Resources.csproj
@@ -19,7 +19,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
diff --git a/VpnHood.Client.App.Store/VpnHood.Client.App.Store.csproj b/VpnHood.Client.App.Store/VpnHood.Client.App.Store.csproj
index 20ba0bf8e..30e319aa9 100644
--- a/VpnHood.Client.App.Store/VpnHood.Client.App.Store.csproj
+++ b/VpnHood.Client.App.Store/VpnHood.Client.App.Store.csproj
@@ -19,7 +19,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
@@ -35,7 +35,7 @@
 	</ItemGroup>
 
 	<ItemGroup>
-		<PackageReference Include="VpnHood.Store.Api" Version="1.0.32-alpha" />
+		<PackageReference Include="VpnHood.Store.Api" Version="1.0.32" />
 	</ItemGroup>
 
 </Project>
diff --git a/VpnHood.Client.App.Swagger/VpnHood.Client.App.Swagger.csproj b/VpnHood.Client.App.Swagger/VpnHood.Client.App.Swagger.csproj
index e47ef1778..625ed7bb8 100644
--- a/VpnHood.Client.App.Swagger/VpnHood.Client.App.Swagger.csproj
+++ b/VpnHood.Client.App.Swagger/VpnHood.Client.App.Swagger.csproj
@@ -25,7 +25,7 @@
 	</PropertyGroup>
 
 	<ItemGroup>
-		<PackageReference Include="NSwag.AspNetCore" Version="14.0.2" />
+		<PackageReference Include="NSwag.AspNetCore" Version="14.0.3" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/VpnHood.Client.App.WebServer/VpnHood.Client.App.WebServer.csproj b/VpnHood.Client.App.WebServer/VpnHood.Client.App.WebServer.csproj
index d99bc80f5..c308deac9 100644
--- a/VpnHood.Client.App.WebServer/VpnHood.Client.App.WebServer.csproj
+++ b/VpnHood.Client.App.WebServer/VpnHood.Client.App.WebServer.csproj
@@ -19,7 +19,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
diff --git a/VpnHood.Client.App.Win.Common/VpnHood.Client.App.Win.Common.csproj b/VpnHood.Client.App.Win.Common/VpnHood.Client.App.Win.Common.csproj
index cc765c3ac..a690e097c 100644
--- a/VpnHood.Client.App.Win.Common/VpnHood.Client.App.Win.Common.csproj
+++ b/VpnHood.Client.App.Win.Common/VpnHood.Client.App.Win.Common.csproj
@@ -19,7 +19,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.2.437</Version>
+		<Version>3.3.470</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
@@ -32,7 +32,7 @@
 
 	<ItemGroup>
 		<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
-		<PackageReference Include="System.Drawing.Common" Version="8.0.1" />
+		<PackageReference Include="System.Drawing.Common" Version="8.0.2" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/VpnHood.Client.App.Win.Common/_publish.ps1 b/VpnHood.Client.App.Win.Common/_publish.ps1
new file mode 100644
index 000000000..9991b7b83
--- /dev/null
+++ b/VpnHood.Client.App.Win.Common/_publish.ps1
@@ -0,0 +1 @@
+& "$PSScriptRoot/../Pub/Core/PublishNuget.ps1" $PSScriptRoot
\ No newline at end of file
diff --git a/VpnHood.Client.App.Win/VpnHood.Client.App.Win.csproj b/VpnHood.Client.App.Win/VpnHood.Client.App.Win.csproj
index ad4c1484c..ea094ecd1 100644
--- a/VpnHood.Client.App.Win/VpnHood.Client.App.Win.csproj
+++ b/VpnHood.Client.App.Win/VpnHood.Client.App.Win.csproj
@@ -48,7 +48,7 @@
 	</ItemGroup>
 
 	<ItemGroup>
-		<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2210.55" />
+		<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2365.46" />
 	</ItemGroup>
 
 
diff --git a/VpnHood.Client.App/VpnHood.Client.App.csproj b/VpnHood.Client.App/VpnHood.Client.App.csproj
index 23548c403..4f1aadc45 100644
--- a/VpnHood.Client.App/VpnHood.Client.App.csproj
+++ b/VpnHood.Client.App/VpnHood.Client.App.csproj
@@ -19,7 +19,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
diff --git a/VpnHood.Client.Device.Android/AndroidDevice.cs b/VpnHood.Client.Device.Android/AndroidDevice.cs
index 47cf54e0b..94afac204 100644
--- a/VpnHood.Client.Device.Android/AndroidDevice.cs
+++ b/VpnHood.Client.Device.Android/AndroidDevice.cs
@@ -34,10 +34,15 @@ public AndroidDevice()
     }
 
     public void Prepare<T>(T activity) where T : Activity, IActivityEvent
+    {
+        Prepare(activity, activity);
+    }
+
+    public void Prepare(Activity activity, IActivityEvent activityEvent)
     {
         _activity = activity;
-        ((IActivityEvent)_activity).OnDestroyEvent += Activity_OnDestroy;
-        ((IActivityEvent)_activity).OnActivityResultEvent += Activity_OnActivityResult;
+        activityEvent.OnDestroyEvent += Activity_OnDestroy;
+        activityEvent.OnActivityResultEvent += Activity_OnActivityResult;
     }
 
     public void InitNotification(Notification notification, int notificationId)
@@ -50,7 +55,7 @@ private static Notification GetDefaultNotification()
     {
         const string channelId = "1000";
         var context = Application.Context;
-        var notificationManager = context.GetSystemService(Context.NotificationService) as NotificationManager 
+        var notificationManager = context.GetSystemService(Context.NotificationService) as NotificationManager
             ?? throw new Exception("Could not resolve NotificationManager.");
 
         Notification.Builder notificationBuilder;
diff --git a/VpnHood.Client.Device.Android/VpnHood.Client.Device.Android.csproj b/VpnHood.Client.Device.Android/VpnHood.Client.Device.Android.csproj
index 767c3eec7..0d36f28db 100644
--- a/VpnHood.Client.Device.Android/VpnHood.Client.Device.Android.csproj
+++ b/VpnHood.Client.Device.Android/VpnHood.Client.Device.Android.csproj
@@ -21,7 +21,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
diff --git a/VpnHood.Client.Device.WinDivert/VpnHood.Client.Device.WinDivert.csproj b/VpnHood.Client.Device.WinDivert/VpnHood.Client.Device.WinDivert.csproj
index e15cb36ce..cf499fd37 100644
--- a/VpnHood.Client.Device.WinDivert/VpnHood.Client.Device.WinDivert.csproj
+++ b/VpnHood.Client.Device.WinDivert/VpnHood.Client.Device.WinDivert.csproj
@@ -19,7 +19,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
@@ -31,7 +31,7 @@
 	</ItemGroup>
 
 	<ItemGroup>
-		<PackageReference Include="SharpPcap" Version="6.2.5" />
+		<PackageReference Include="SharpPcap" Version="6.3.0" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/VpnHood.Client.Device/VpnHood.Client.Device.csproj b/VpnHood.Client.Device/VpnHood.Client.Device.csproj
index dc7315d71..d4d00c253 100644
--- a/VpnHood.Client.Device/VpnHood.Client.Device.csproj
+++ b/VpnHood.Client.Device/VpnHood.Client.Device.csproj
@@ -19,7 +19,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
@@ -32,7 +32,7 @@
 
 	<ItemGroup>
 		<PackageReference Include="PacketDotNet" Version="1.4.7" />
-		<PackageReference Include="System.Text.Json" Version="8.0.1" />
+		<PackageReference Include="System.Text.Json" Version="8.0.2" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/VpnHood.Client/VpnHood.Client.csproj b/VpnHood.Client/VpnHood.Client.csproj
index abd9c0d37..96477371f 100644
--- a/VpnHood.Client/VpnHood.Client.csproj
+++ b/VpnHood.Client/VpnHood.Client.csproj
@@ -19,13 +19,13 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
 	<ItemGroup>
 		<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
-		<PackageReference Include="System.Text.Json" Version="8.0.1" />
+		<PackageReference Include="System.Text.Json" Version="8.0.2" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/VpnHood.Common/VpnHood.Common.csproj b/VpnHood.Common/VpnHood.Common.csproj
index 8b1c5c1e3..a3084e8bf 100644
--- a/VpnHood.Common/VpnHood.Common.csproj
+++ b/VpnHood.Common/VpnHood.Common.csproj
@@ -19,13 +19,13 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
 	<ItemGroup>
 		<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
-		<PackageReference Include="System.Text.Json" Version="8.0.1" />
+		<PackageReference Include="System.Text.Json" Version="8.0.2" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/VpnHood.Server.Access/VpnHood.Server.Access.csproj b/VpnHood.Server.Access/VpnHood.Server.Access.csproj
index 4666d77af..bfad20b39 100644
--- a/VpnHood.Server.Access/VpnHood.Server.Access.csproj
+++ b/VpnHood.Server.Access/VpnHood.Server.Access.csproj
@@ -20,7 +20,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
@@ -31,7 +31,7 @@
 	</ItemGroup>
 
 	<ItemGroup>
-		<PackageReference Include="System.Text.Json" Version="8.0.1" />
+		<PackageReference Include="System.Text.Json" Version="8.0.2" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/VpnHood.Server.App.Net/VpnHood.Server.App.Net.csproj b/VpnHood.Server.App.Net/VpnHood.Server.App.Net.csproj
index d5281018a..368ce87c0 100644
--- a/VpnHood.Server.App.Net/VpnHood.Server.App.Net.csproj
+++ b/VpnHood.Server.App.Net/VpnHood.Server.App.Net.csproj
@@ -47,7 +47,7 @@
 		</Content>
 	</ItemGroup>
 	<ItemGroup>
-		<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="4.1.0" />
+		<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="4.1.1" />
 		<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
 		<PackageReference Include="NLog" Version="5.2.8" />
 		<PackageReference Include="NLog.Extensions.Logging" Version="5.3.8" />
diff --git a/VpnHood.Server/VpnHood.Server.csproj b/VpnHood.Server/VpnHood.Server.csproj
index 352d4b107..1457ecfc9 100644
--- a/VpnHood.Server/VpnHood.Server.csproj
+++ b/VpnHood.Server/VpnHood.Server.csproj
@@ -19,14 +19,14 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
 	<ItemGroup>
 		<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
 		<PackageReference Include="PacketDotNet" Version="1.4.7" />
-		<PackageReference Include="System.Text.Json" Version="8.0.1" />
+		<PackageReference Include="System.Text.Json" Version="8.0.2" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/VpnHood.Tunneling/VpnHood.Tunneling.csproj b/VpnHood.Tunneling/VpnHood.Tunneling.csproj
index e4cc44ede..763df18cc 100644
--- a/VpnHood.Tunneling/VpnHood.Tunneling.csproj
+++ b/VpnHood.Tunneling/VpnHood.Tunneling.csproj
@@ -19,7 +19,7 @@
 		<PackageIcon>VpnHood.png</PackageIcon>
 		<PackageProjectUrl>https://github.com/vpnhood/vpnhood</PackageProjectUrl>
 		<RepositoryUrl>https://github.com/vpnhood/vpnhood</RepositoryUrl>
-		<Version>3.3.470</Version>
+		<Version>3.3.471</Version>
 		<FileVersion>$([System.DateTime]::Now.ToString("yyyy.M.d.HHmm"))</FileVersion>
 	</PropertyGroup>
 
@@ -28,7 +28,7 @@
 		<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
 		<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
 		<PackageReference Include="PacketDotNet" Version="1.4.7" />
-		<PackageReference Include="System.Text.Json" Version="8.0.1" />
+		<PackageReference Include="System.Text.Json" Version="8.0.2" />
 	</ItemGroup>
 
 	<ItemGroup>
diff --git a/VpnHood.sln b/VpnHood.sln
index f201cd3e7..1938bd14e 100644
--- a/VpnHood.sln
+++ b/VpnHood.sln
@@ -88,7 +88,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Windows", "Windows", "{BD1C
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "App.Server", "App.Server", "{2439858F-F7EE-4FE7-A146-14C98111D0B4}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VpnHood.Client.App.Android.GooglePlay.Core", "VpnHood.Client.App.Android.GooglePlay.Core\VpnHood.Client.App.Android.GooglePlay.Core.csproj", "{2701D6B3-7E6A-43B6-B285-4BB434DA48CC}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VpnHood.Client.App.Android.GooglePlay.Core", "VpnHood.Client.App.Android.GooglePlay.Core\VpnHood.Client.App.Android.GooglePlay.Core.csproj", "{2701D6B3-7E6A-43B6-B285-4BB434DA48CC}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VpnHood.Client.App.Maui", "VpnHood.Client.App.Maui\VpnHood.Client.App.Maui.csproj", "{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -634,6 +636,36 @@ Global
 		{2701D6B3-7E6A-43B6-B285-4BB434DA48CC}.Release|x64.Build.0 = Release|Any CPU
 		{2701D6B3-7E6A-43B6-B285-4BB434DA48CC}.Release|x86.ActiveCfg = Release|Any CPU
 		{2701D6B3-7E6A-43B6-B285-4BB434DA48CC}.Release|x86.Build.0 = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|ARM.Build.0 = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|ARM.Deploy.0 = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|ARM64.Build.0 = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|ARM64.Deploy.0 = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|x64.Build.0 = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|x64.Deploy.0 = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|x86.Build.0 = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Debug|x86.Deploy.0 = Debug|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|Any CPU.Build.0 = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|Any CPU.Deploy.0 = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|ARM.ActiveCfg = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|ARM.Build.0 = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|ARM.Deploy.0 = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|ARM64.ActiveCfg = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|ARM64.Build.0 = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|ARM64.Deploy.0 = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|x64.ActiveCfg = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|x64.Build.0 = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|x64.Deploy.0 = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|x86.ActiveCfg = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|x86.Build.0 = Release|Any CPU
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151}.Release|x86.Deploy.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -659,6 +691,7 @@ Global
 		{DC9319F3-8348-498C-9A5B-77399106DB10} = {B3EAE8F1-8ECF-4FC9-9941-28F65A2E7F3E}
 		{BD1C4F74-C48B-4302-90C3-0B7243C0DD20} = {B3EAE8F1-8ECF-4FC9-9941-28F65A2E7F3E}
 		{2701D6B3-7E6A-43B6-B285-4BB434DA48CC} = {DC9319F3-8348-498C-9A5B-77399106DB10}
+		{84C2CD7C-8088-4273-B9A9-D5A4DEFE4151} = {BD1C4F74-C48B-4302-90C3-0B7243C0DD20}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {19BAEB35-FD38-4E41-9963-46313AF87C41}