diff --git a/.github/workflows/nuget_push.yml b/.github/workflows/nuget_push.yml
index a8669aa..b19c4af 100644
--- a/.github/workflows/nuget_push.yml
+++ b/.github/workflows/nuget_push.yml
@@ -4,34 +4,60 @@ on:
workflow_dispatch:
jobs:
- build:
+ build-maui:
runs-on: windows-latest
- name: Update NuGet package
+ name: Update Aptabase.Maui NuGet package
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup .NET Core @ Latest
uses: actions/setup-dotnet@v4
-
+
- name: Setup JDK 11
uses: actions/setup-java@v2
with:
- java-version: '11'
- distribution: 'adopt'
-
+ java-version: '11'
+ distribution: 'adopt'
+
- name: Extract Version from csproj
id: get_version
run: |
- $version = Select-String -Path "./src/Aptabase.Maui.csproj" -Pattern '(.*)' | ForEach-Object { $_.Matches.Groups[1].Value }
+ $version = Select-String -Path "./src/Aptabase.Maui/Aptabase.Maui.csproj" -Pattern '(.*)' | ForEach-Object { $_.Matches.Groups[1].Value }
echo "PackageVersion=$version" | Out-File -Append -FilePath $env:GITHUB_ENV
shell: powershell
- - name: Build and Publish
+ - name: Build and Publish Aptabase.Maui
run: |
- cd ./src/
+ cd ./src/Aptabase.Maui
dotnet restore Aptabase.Maui.csproj
dotnet pack Aptabase.Maui.csproj -c Release -o artifacts -p:PackageVersion=${{ env.PackageVersion }}
- - name: Push
- run: dotnet nuget push ./src/artifacts/Aptabase.Maui.${{ env.PackageVersion }}.nupkg -k ${{ secrets.NUGET_APIKEY }} -s https://api.nuget.org/v3/index.json
\ No newline at end of file
+ - name: Push Aptabase.Maui Package
+ run: dotnet nuget push ./src/Aptabase.Maui/artifacts/Aptabase.Maui.${{ env.PackageVersion }}.nupkg -k ${{ secrets.NUGET_APIKEY }} -s https://api.nuget.org/v3/index.json
+
+ build-core:
+ runs-on: ubuntu-latest
+ name: Build and Publish Aptabase.Core NuGet package
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Setup .NET Core @ Latest
+ uses: actions/setup-dotnet@v4
+
+ - name: Extract Version from csproj
+ id: get_version_core
+ run: |
+ $version = Select-String -Path "./src/Aptabase.Core/Aptabase.Core.csproj" -Pattern '(.*)' | ForEach-Object { $_.Matches.Groups[1].Value }
+ echo "PackageVersion=$version" | Out-File -Append -FilePath $env:GITHUB_ENV
+ shell: bash
+
+ - name: Build and Publish Aptabase.Core
+ run: |
+ cd ./src/Aptabase.Core
+ dotnet restore Aptabase.Core.csproj
+ dotnet pack Aptabase.Core.csproj -c Release -o artifacts -p:PackageVersion=${{ env.PackageVersion }}
+
+ - name: Push Aptabase.Core Package
+ run: dotnet nuget push ./src/Aptabase.Core/artifacts/Aptabase.Core.${{ env.PackageVersion }}.nupkg -k ${{ secrets.NUGET_APIKEY }} -s https://api.nuget.org/v3/index.json
diff --git a/Aptabase.MAUI.sln b/Aptabase.NET.sln
similarity index 58%
rename from Aptabase.MAUI.sln
rename to Aptabase.NET.sln
index 4711026..e30cbee 100644
--- a/Aptabase.MAUI.sln
+++ b/Aptabase.NET.sln
@@ -1,40 +1,54 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.5.33530.505
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aptabase.Maui", "src\Aptabase.Maui.csproj", "{CDBA84BA-F326-4162-B509-31892E9CAF2E}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloWorld", "test\HelloWorld\HelloWorld.csproj", "{E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8BFFEF39-1EA0-4D6D-9988-322A74A6558D}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{19E5FDF2-25B6-48AA-BB1B-8BBA9E8323E1}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {CDBA84BA-F326-4162-B509-31892E9CAF2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {CDBA84BA-F326-4162-B509-31892E9CAF2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {CDBA84BA-F326-4162-B509-31892E9CAF2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CDBA84BA-F326-4162-B509-31892E9CAF2E}.Release|Any CPU.Build.0 = Release|Any CPU
- {E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {CDBA84BA-F326-4162-B509-31892E9CAF2E} = {8BFFEF39-1EA0-4D6D-9988-322A74A6558D}
- {E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E} = {19E5FDF2-25B6-48AA-BB1B-8BBA9E8323E1}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {C696E39C-8A3B-4FE3-BBB1-95FE24E67DCD}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33530.505
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aptabase.Maui", "src\Aptabase.Maui\Aptabase.Maui.csproj", "{CDBA84BA-F326-4162-B509-31892E9CAF2E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aptabase.Core", "src\Aptabase.Core\Aptabase.Core.csproj", "{D6DE2CBA-F461-4E04-9A96-6C0EE7E32B9E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloMaui", "test\HelloMaui\HelloMaui.csproj", "{E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8BFFEF39-1EA0-4D6D-9988-322A74A6558D}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{19E5FDF2-25B6-48AA-BB1B-8BBA9E8323E1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloWorld", "test\HelloWorld\HelloWorld.csproj", "{E6EB4FC9-CF24-4735-B8DB-EC78674A94F1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CDBA84BA-F326-4162-B509-31892E9CAF2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CDBA84BA-F326-4162-B509-31892E9CAF2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CDBA84BA-F326-4162-B509-31892E9CAF2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CDBA84BA-F326-4162-B509-31892E9CAF2E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D6DE2CBA-F461-4E04-9A96-6C0EE7E32B9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D6DE2CBA-F461-4E04-9A96-6C0EE7E32B9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D6DE2CBA-F461-4E04-9A96-6C0EE7E32B9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D6DE2CBA-F461-4E04-9A96-6C0EE7E32B9E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E6EB4FC9-CF24-4735-B8DB-EC78674A94F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E6EB4FC9-CF24-4735-B8DB-EC78674A94F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E6EB4FC9-CF24-4735-B8DB-EC78674A94F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E6EB4FC9-CF24-4735-B8DB-EC78674A94F1}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {CDBA84BA-F326-4162-B509-31892E9CAF2E} = {8BFFEF39-1EA0-4D6D-9988-322A74A6558D}
+ {E9D22AE5-0B04-4ED6-B1BC-4242BE3D321E} = {19E5FDF2-25B6-48AA-BB1B-8BBA9E8323E1}
+ {D6DE2CBA-F461-4E04-9A96-6C0EE7E32B9E} = {8BFFEF39-1EA0-4D6D-9988-322A74A6558D}
+ {E6EB4FC9-CF24-4735-B8DB-EC78674A94F1} = {19E5FDF2-25B6-48AA-BB1B-8BBA9E8323E1}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {C696E39C-8A3B-4FE3-BBB1-95FE24E67DCD}
+ EndGlobalSection
+EndGlobal
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f4c51a3..21612f3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.2.0
+
+* Add `Aptabase.Core` for generic .NET support (Does not support crash reporter)
+* Use [XDG.Directories](https://www.nuget.org/packages/Xdg.Directories) Cache Directory across all .NET SDKs (This was a requirement for Aptabase.Core)
+
## 0.1.0
* Add `EnablePersistence` to persist events on disk before sending them to the server
diff --git a/README.md b/README.md
index 182666b..bf14c78 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
![Aptabase](https://raw.githubusercontent.com/aptabase/aptabase-com/main/public/og.png)
-# MAUI SDK for Aptabase
+# .NET SDK for Aptabase
[![NuGet](https://img.shields.io/nuget/v/Aptabase.Maui)](https://www.nuget.org/packages/Aptabase.Maui)
[![GitHub](https://img.shields.io/github/license/aptabase/aptabase-maui)](https://github.com/aptabase/aptabase-maui/blob/main/LICENSE)
@@ -12,10 +12,51 @@ Instrument your apps with Aptabase, an Open Source, Privacy-First and, Simple An
Start by adding the Aptabase NuGet package to your .csproj:
```xml
-
+
```
-## Usage
+Or, if you're using MAUI
+
+```xml
+
+```
+
+## Usage (.NET)
+
+First, you need to get your `App Key` from Aptabase, you can find it in the `Instructions` menu on the left side menu.
+
+Change your `Program.cs` to add Aptabase:
+
+```csharp
+// Create a ServiceCollection
+var services = new ServiceCollection();
+
+services.AddLogging(); // If you haven't registered a logger yet
+
+// Add Aptabase to the service collection
+services.UseAptabase("", new AptabaseOptions
+{
+#if DEBUG
+ IsDebugMode = true,
+#else
+ IsDebugMode = false,
+#endif
+ EnableCrashReporting = false, // ❌ Not supported with Aptabase.Core, only Aptabase.Maui
+ EnablePersistence = true,
+});
+
+// ... Register other services you need ...
+
+// Build the service provider
+var serviceProvider = services.BuildServiceProvider();
+
+// Get an instance of the Aptabase service (if you need it directly)
+var aptabaseClient = serviceProvider.GetRequiredService();
+...
+}
+```
+
+## Usage (Maui)
First, you need to get your `App Key` from Aptabase, you can find it in the `Instructions` menu on the left side menu.
diff --git a/src/Aptabase.Core/Aptabase.Core.csproj b/src/Aptabase.Core/Aptabase.Core.csproj
new file mode 100644
index 0000000..8322cb6
--- /dev/null
+++ b/src/Aptabase.Core/Aptabase.Core.csproj
@@ -0,0 +1,34 @@
+
+
+
+ Aptabase.Core
+ 0.2.0
+ $(Version)
+ $(Version)
+ net8.0
+ Dotnet SDK for Aptabase: Open Source, Privacy-First and Simple Analytics for Mobile, Desktop and Web Apps
+ Aptabase Team
+ Aptabase
+ https://aptabase.com
+ README.md
+ logo.png
+ https://github.com/aptabase/aptabase-dotnet
+ git
+ analytics, privacy, dotnet, sdk, telemetry
+ MIT
+ true
+ snupkg
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AptabaseClient.cs b/src/Aptabase.Core/AptabaseClient.cs
similarity index 98%
rename from src/AptabaseClient.cs
rename to src/Aptabase.Core/AptabaseClient.cs
index dfbfdac..91aacf6 100644
--- a/src/AptabaseClient.cs
+++ b/src/Aptabase.Core/AptabaseClient.cs
@@ -1,7 +1,7 @@
using Microsoft.Extensions.Logging;
using System.Threading.Channels;
-namespace Aptabase.Maui;
+namespace Aptabase.Core;
public class AptabaseClient : IAptabaseClient
{
diff --git a/src/AptabaseClientBase.cs b/src/Aptabase.Core/AptabaseClientBase.cs
similarity index 96%
rename from src/AptabaseClientBase.cs
rename to src/Aptabase.Core/AptabaseClientBase.cs
index 18495f3..af59a4b 100644
--- a/src/AptabaseClientBase.cs
+++ b/src/Aptabase.Core/AptabaseClientBase.cs
@@ -3,7 +3,7 @@
using System.Net.Http.Json;
using System.Reflection;
-namespace Aptabase.Maui;
+namespace Aptabase.Core;
internal class AptabaseClientBase : IAsyncDisposable
{
@@ -20,7 +20,7 @@ internal class AptabaseClientBase : IAsyncDisposable
{
{ "US", "https://us.aptabase.com" },
{ "EU", "https://eu.aptabase.com" },
- { "DEV", DeviceInfo.Platform == DevicePlatform.Android ? "https://10.0.2.2:3000" : "https://localhost:3000" },
+ { "DEV", OperatingSystem.IsAndroid() ? "https://10.0.2.2:3000" : "https://localhost:3000" },
{ "SH", "" },
};
diff --git a/src/Aptabase.Core/AptabaseExtensions.cs b/src/Aptabase.Core/AptabaseExtensions.cs
new file mode 100644
index 0000000..0d6dec2
--- /dev/null
+++ b/src/Aptabase.Core/AptabaseExtensions.cs
@@ -0,0 +1,38 @@
+
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+
+namespace Aptabase.Core;
+
+
+public static class AptabaseExtensions
+{
+ public static IServiceCollection UseAptabase(this IServiceCollection services, string appKey, AptabaseOptions? options = null)
+ {
+ services.AddSingleton(serviceProvider =>
+ {
+ IAptabaseClient client;
+ var loggerFactory = serviceProvider.GetRequiredService();
+
+ if (options?.EnablePersistence != true)
+ {
+ client = new AptabaseClient(appKey, options, loggerFactory.CreateLogger());
+ }
+ else
+ {
+ client = new AptabasePersistentClient(appKey, options, loggerFactory.CreateLogger());
+ }
+
+ if (options?.EnableCrashReporting == true)
+ {
+ throw new NotImplementedException("Crash reporting is only for Aptabase.Maui");
+ }
+
+ return client;
+ });
+
+ return services;
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/AptabaseOptions.cs b/src/Aptabase.Core/AptabaseOptions.cs
similarity index 97%
rename from src/AptabaseOptions.cs
rename to src/Aptabase.Core/AptabaseOptions.cs
index 1ca0a0b..e6d63f3 100644
--- a/src/AptabaseOptions.cs
+++ b/src/Aptabase.Core/AptabaseOptions.cs
@@ -1,4 +1,4 @@
-namespace Aptabase.Maui;
+namespace Aptabase.Core;
///
/// Initialization options for the Aptabase Client
diff --git a/src/AptabasePersistentClient.cs b/src/Aptabase.Core/AptabasePersistentClient.cs
similarity index 97%
rename from src/AptabasePersistentClient.cs
rename to src/Aptabase.Core/AptabasePersistentClient.cs
index 57a2c6a..8aa1557 100644
--- a/src/AptabasePersistentClient.cs
+++ b/src/Aptabase.Core/AptabasePersistentClient.cs
@@ -3,8 +3,9 @@
using System.Text;
using System.Text.Json;
using System.Threading.Channels;
+using Xdg.Directories;
-namespace Aptabase.Maui;
+namespace Aptabase.Core;
public class AptabasePersistentClient : IAptabaseClient
{
@@ -26,7 +27,7 @@ public AptabasePersistentClient(string appKey, AptabaseOptions? options, ILogger
SingleReader = true,
ReliableEnumeration = true,
PartitionCapacity = _maxPersistedEvents,
- Location = Path.Combine(FileSystem.CacheDirectory, "EventData"),
+ Location = Path.Combine(BaseDirectory.CacheHome, "Aptabase", "EventData"),
});
_logger = logger;
_cts = new CancellationTokenSource();
diff --git a/src/Aptabase.Core/DeviceDetect.cs b/src/Aptabase.Core/DeviceDetect.cs
new file mode 100644
index 0000000..0bdd8fe
--- /dev/null
+++ b/src/Aptabase.Core/DeviceDetect.cs
@@ -0,0 +1,92 @@
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+#pragma warning disable CA1416 // I like to live dangerously.
+using Microsoft.Win32;
+
+namespace Aptabase.Core;
+
+internal static class DeviceDetect
+{
+ internal static string GetDeviceModel()
+ {
+ return RuntimeInformation.OSDescription.ToLower() switch
+ {
+ var os when OperatingSystem.IsWindows() => GetWindowsDeviceModel(),
+ var os when OperatingSystem.IsMacOS() => GetMacDeviceModel(),
+ var os when OperatingSystem.IsLinux() => GetLinuxDeviceModel(),
+ var os when OperatingSystem.IsFreeBSD() => GetFreeBSDDeviceModel(),
+ _ => "" // Unsupported Device Detection Platform
+ };
+ }
+
+ private static string GetWindowsDeviceModel()
+ {
+ const string registryKeyPath = @"HARDWARE\DESCRIPTION\System\BIOS";
+ const string registryValueName = "SystemProductName";
+ try
+ {
+ using var key = Registry.LocalMachine.OpenSubKey(registryKeyPath);
+ if (key == null) return "";
+
+ var model = key.GetValue(registryValueName) as string;
+
+ return !string.IsNullOrEmpty(model) ? model : "";
+ }
+ catch
+ {
+ return "";
+ }
+ }
+ private static string GetMacDeviceModel()
+ {
+ var processStartInfo = new ProcessStartInfo
+ {
+ FileName = "sysctl",
+ Arguments = "-n hw.model",
+ RedirectStandardOutput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ };
+
+ using var process = Process.Start(processStartInfo);
+ if (process == null) return "";
+
+ var output = process.StandardOutput.ReadToEnd();
+ var modelIdentifier = output.Trim();
+
+ return string.IsNullOrEmpty(modelIdentifier) ? "" : modelIdentifier;
+ }
+
+ private static string GetLinuxDeviceModel()
+ {
+ try
+ {
+ var model = File.ReadAllText("/sys/class/dmi/id/product_name");
+ return model.Trim();
+ }
+ catch (IOException)
+ {
+ return "";
+ }
+ }
+
+ private static string GetFreeBSDDeviceModel()
+ {
+ var processStartInfo = new ProcessStartInfo
+ {
+ FileName = "kenv",
+ Arguments = "smbios.system.product",
+ RedirectStandardOutput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ };
+
+ using var process = Process.Start(processStartInfo);
+ if (process == null) return "";
+
+ var output = process.StandardOutput.ReadToEnd();
+ var deviceModel = output.Trim();
+
+ return string.IsNullOrEmpty(deviceModel) ? "" : deviceModel;
+ }
+}
\ No newline at end of file
diff --git a/src/Aptabase.Core/DistroDetect.cs b/src/Aptabase.Core/DistroDetect.cs
new file mode 100644
index 0000000..78a19dc
--- /dev/null
+++ b/src/Aptabase.Core/DistroDetect.cs
@@ -0,0 +1,112 @@
+namespace Aptabase.Core;
+
+internal static class DistroDetect
+{
+ // Linux distributions also have /var/lib/lsb-release but I wanted to keep this simple.
+ public static (string Name, string Version) GetLinuxInfo()
+ {
+ const string osReleaseFile = "/etc/os-release";
+
+ // Try reading /etc/os-release
+ try
+ {
+ var data = File.ReadAllText(osReleaseFile);
+ return ParseOsRelease(data);
+ }
+ catch (IOException)
+ {
+ // Fallback to lsb_release if /etc/os-release is inaccessible (e.g., under firejail)
+ return ParseLsbReleaseOrFallback();
+ }
+ }
+ private static (string Name, string Version) ParseOsRelease(string data)
+ {
+ string name = string.Empty, version = string.Empty;
+
+ var lines = data.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
+
+ foreach (var line in lines)
+ {
+ if (line.StartsWith("NAME="))
+ {
+ name = TrimValue(line);
+ }
+ else if (line.StartsWith("VERSION_ID="))
+ {
+ version = TrimValue(line);
+ }
+ else if (line.StartsWith("VERSION=") && string.IsNullOrEmpty(version))
+ {
+ version = TrimValue(line);
+ }
+ else if (line.StartsWith("VERSION_CODENAME=") && string.IsNullOrEmpty(version))
+ {
+ version = TrimValue(line);
+ }
+ }
+
+ return (name, version);
+ }
+
+ private static (string Name, string Version) ParseLsbReleaseOrFallback()
+ {
+ // Fallback parsing if /etc/os-release is unavailable, using lsb_release command
+ // I know the file exists, but according to a StackOverflow wizard, it shouldn't be used.
+ try
+ {
+ var lsbReleaseOutput = ExecuteCommand("lsb_release", "-a");
+ string name = string.Empty, version = string.Empty;
+
+ foreach (var line in lsbReleaseOutput.Split('\n'))
+ {
+ if (line.StartsWith("Distributor ID:"))
+ {
+ name = line.Split(new[] { ':' }, 2)[1].Trim();
+ }
+ else if (line.StartsWith("Release:"))
+ {
+ version = line.Split(new[] { ':' }, 2)[1].Trim();
+ }
+ }
+
+ return (name, version);
+ }
+ catch (Exception)
+ {
+ return ("", "");
+ }
+ }
+
+ private static string TrimValue(string line)
+ {
+ // Extracts and trims the value from the line, removing the surrounding quotes
+ return line.Split(new[] { '=' }, 2)[1].Trim('\"');
+ }
+
+ private static string ExecuteCommand(string command, string arguments)
+ {
+ var startInfo = new System.Diagnostics.ProcessStartInfo
+ {
+ FileName = command,
+ Arguments = arguments,
+ RedirectStandardOutput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ };
+
+ using var process = System.Diagnostics.Process.Start(startInfo);
+ if (process == null) return "";
+
+ return process.StandardOutput.ReadToEnd();
+ }
+ internal static string GetLinuxDistro()
+ {
+ var distroName = GetLinuxInfo().Name;
+ return string.IsNullOrWhiteSpace(distroName) ? "Linux" : distroName;
+ }
+ internal static string GetLinuxDistroVersion()
+ {
+ var distroVersion = GetLinuxInfo().Version;
+ return string.IsNullOrWhiteSpace(distroVersion) ? Environment.OSVersion.Version.ToString() : distroVersion;
+ }
+}
\ No newline at end of file
diff --git a/src/EventData.cs b/src/Aptabase.Core/EventData.cs
similarity index 94%
rename from src/EventData.cs
rename to src/Aptabase.Core/EventData.cs
index 1fd1bbd..f968c36 100644
--- a/src/EventData.cs
+++ b/src/Aptabase.Core/EventData.cs
@@ -1,4 +1,4 @@
-namespace Aptabase.Maui;
+namespace Aptabase.Core;
internal class EventData
{
diff --git a/src/IAptabaseClient.cs b/src/Aptabase.Core/IAptabaseClient.cs
similarity index 88%
rename from src/IAptabaseClient.cs
rename to src/Aptabase.Core/IAptabaseClient.cs
index 9b12214..bc35bd6 100644
--- a/src/IAptabaseClient.cs
+++ b/src/Aptabase.Core/IAptabaseClient.cs
@@ -1,4 +1,4 @@
-namespace Aptabase.Maui;
+namespace Aptabase.Core;
///
/// Aptabase client used for tracking events
diff --git a/src/Aptabase.Core/LocalHttpsClientHandler.cs b/src/Aptabase.Core/LocalHttpsClientHandler.cs
new file mode 100644
index 0000000..641cd88
--- /dev/null
+++ b/src/Aptabase.Core/LocalHttpsClientHandler.cs
@@ -0,0 +1,13 @@
+namespace Aptabase.Core;
+
+public class LocalHttpsClientHandler : HttpClientHandler
+{
+ public LocalHttpsClientHandler()
+ {
+ // Disable SSL verification
+ ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) =>
+ {
+ return true;
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/SystemInfo.cs b/src/Aptabase.Core/SystemInfo.cs
similarity index 58%
rename from src/SystemInfo.cs
rename to src/Aptabase.Core/SystemInfo.cs
index 6e25c69..81e921c 100644
--- a/src/SystemInfo.cs
+++ b/src/Aptabase.Core/SystemInfo.cs
@@ -1,7 +1,8 @@
using System.Diagnostics;
using System.Reflection;
+using System.Runtime.InteropServices;
-namespace Aptabase.Maui;
+namespace Aptabase.Core;
internal class SystemInfo
{
@@ -21,11 +22,11 @@ public SystemInfo()
{
OsName = GetOsName();
OsVersion = GetOsVersion();
- DeviceModel = DeviceInfo.Current.Model;
- SdkVersion = $"Aptabase.Maui@{_pkgVersion}";
+ DeviceModel = DeviceDetect.GetDeviceModel();
+ SdkVersion = $"{Assembly.GetExecutingAssembly().GetName()}@{_pkgVersion}";
Locale = Thread.CurrentThread.CurrentCulture.Name;
- AppVersion = AppInfo.Current.VersionString;
- AppBuildNumber = AppInfo.Current.BuildString;
+ AppVersion = Assembly.GetEntryAssembly()?.GetName().Version?.ToString() ?? string.Empty;
+ AppBuildNumber = Assembly.GetEntryAssembly()?.GetName().Version?.Build.ToString() ?? string.Empty;
}
internal static bool IsInDebugMode(Assembly? assembly)
@@ -46,35 +47,25 @@ internal static bool IsInDebugMode(Assembly? assembly)
}
private static string GetOsName()
- {
- var platform = DeviceInfo.Current.Platform;
- if (platform == DevicePlatform.Android)
- return "Android";
+ {
+ if (OperatingSystem.IsAndroid())
+ return "Android";
- if (platform == DevicePlatform.WinUI)
+ if (OperatingSystem.IsWindows())
return "Windows";
+
+
+ if (OperatingSystem.IsMacOS()) return "macOS";
+ if (OperatingSystem.IsTvOS()) return "tvOS";
+ if (OperatingSystem.IsWatchOS()) return "watchOS";
+ // iPadOS is bundled as iOS as well. It's hard to tell the difference from pure .NET
+ if (OperatingSystem.IsIOS()) return "iOS";
- if (platform == DevicePlatform.macOS || platform == DevicePlatform.MacCatalyst)
- return "macOS";
-
- if (platform == DevicePlatform.tvOS)
- return "tvOS";
-
- if (platform == DevicePlatform.watchOS)
- return "watchOS";
-
- if (platform == DevicePlatform.Tizen)
- return "Tizen";
-
- if (platform == DevicePlatform.iOS)
- {
- if (DeviceInfo.Current.Idiom == DeviceIdiom.Tablet && DeviceInfo.Current.Version.Major >= 13)
- return "iPadOS";
+ if (OperatingSystem.IsLinux()) return DistroDetect.GetLinuxDistro();
+ if (OperatingSystem.IsFreeBSD()) return "FreeBSD";
- return "iOS";
- }
- return "";
+ return string.Empty;
}
private static string GetOsVersion()
@@ -83,7 +74,7 @@ private static string GetOsVersion()
var osVersion = Foundation.NSProcessInfo.ProcessInfo.OperatingSystemVersion;
return $"{osVersion.Major}.{osVersion.Minor}.{osVersion.PatchVersion}";
#else
- return DeviceInfo.Current.VersionString;
+ return OperatingSystem.IsLinux() ? DistroDetect.GetLinuxDistroVersion() : Environment.OSVersion.Version.ToString();
#endif
}
}
diff --git a/src/Aptabase.Maui.csproj b/src/Aptabase.Maui/Aptabase.Maui.csproj
similarity index 88%
rename from src/Aptabase.Maui.csproj
rename to src/Aptabase.Maui/Aptabase.Maui.csproj
index 47ebb2d..890f857 100644
--- a/src/Aptabase.Maui.csproj
+++ b/src/Aptabase.Maui/Aptabase.Maui.csproj
@@ -2,7 +2,7 @@
Aptabase.Maui
- 0.1.0
+ 0.2.0
$(Version)
$(Version)
net8.0;net8.0-android;net8.0-ios;net8.0-maccatalyst
@@ -12,7 +12,7 @@
https://aptabase.com
README.md
logo.png
- https://github.com/aptabase/aptabase-maui
+ https://github.com/aptabase/aptabase-dotnet
git
analytics, privacy, maui, sdk, telemetry
MIT
@@ -42,11 +42,12 @@
false
-
-
+
+
-
+
+
diff --git a/src/AptabaseCrashReporter.cs b/src/Aptabase.Maui/AptabaseMauiCrashReporter.cs
similarity index 90%
rename from src/AptabaseCrashReporter.cs
rename to src/Aptabase.Maui/AptabaseMauiCrashReporter.cs
index d0d2d16..cc822aa 100644
--- a/src/AptabaseCrashReporter.cs
+++ b/src/Aptabase.Maui/AptabaseMauiCrashReporter.cs
@@ -1,18 +1,19 @@
-using Microsoft.Extensions.Logging;
+using Aptabase.Core;
+using Microsoft.Extensions.Logging;
namespace Aptabase.Maui;
-public class AptabaseCrashReporter
+public class AptabaseMauiCrashReporter
{
private readonly IAptabaseClient _client;
- private readonly ILogger? _logger;
+ private readonly ILogger? _logger;
#if ANDROID
// the UnhandledExceptionRaiser fires first, but others may fire redundantly soon after
private bool _nativeThrown;
#endif
- public AptabaseCrashReporter(IAptabaseClient client, ILogger? logger)
+ public AptabaseMauiCrashReporter(IAptabaseClient client, ILogger? logger)
{
_client = client;
_logger = logger;
diff --git a/src/AptabaseExtensions.cs b/src/Aptabase.Maui/MauiExtensions.cs
similarity index 86%
rename from src/AptabaseExtensions.cs
rename to src/Aptabase.Maui/MauiExtensions.cs
index 80d122f..e4037e3 100644
--- a/src/AptabaseExtensions.cs
+++ b/src/Aptabase.Maui/MauiExtensions.cs
@@ -1,4 +1,5 @@
-using Aptabase.Maui;
+using Aptabase.Core;
+using Aptabase.Maui;
using Microsoft.Extensions.Logging;
namespace Microsoft.Maui.Hosting;
@@ -6,7 +7,7 @@ namespace Microsoft.Maui.Hosting;
///
/// Aptabase extensions for .
///
-public static class AptabaseExtensions
+public static class MauiExtensions
{
///
/// Uses Aptabase integration.
@@ -34,7 +35,7 @@ public static MauiAppBuilder UseAptabase(this MauiAppBuilder builder, string app
if (options?.EnableCrashReporting == true)
{
- _ = new AptabaseCrashReporter(client, loggerFactory.CreateLogger());
+ _ = new AptabaseMauiCrashReporter(client, loggerFactory.CreateLogger());
}
return client;
diff --git a/src/LocalHttpsClientHandler.cs b/src/LocalHttpsClientHandler.cs
deleted file mode 100644
index d5e5088..0000000
--- a/src/LocalHttpsClientHandler.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-#if ANDROID
-using Xamarin.Android.Net;
-#endif
-#if IOS
-using Foundation;
-#endif
-
-namespace Aptabase.Maui;
-
-public class LocalHttpsClientHandler : DelegatingHandler
-{
- public LocalHttpsClientHandler()
- {
-#if ANDROID
- InnerHandler = new AndroidMessageHandler
- {
- ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
- {
- if (cert?.Issuer != null && cert.Issuer.Contains("CN=mkcert"))
- {
- return true;
- }
- return errors == System.Net.Security.SslPolicyErrors.None;
- }
- };
-#elif IOS
- InnerHandler = new NSUrlSessionHandler
- {
- TrustOverrideForUrl = (sender, url, trust) => url.StartsWith("https://localhost"),
- };
-#else
- InnerHandler = new HttpClientHandler();
-#endif
- }
-}
\ No newline at end of file
diff --git a/test/HelloWorld/App.xaml b/test/HelloMaui/App.xaml
similarity index 86%
rename from test/HelloWorld/App.xaml
rename to test/HelloMaui/App.xaml
index f3e53f8..01c178b 100644
--- a/test/HelloWorld/App.xaml
+++ b/test/HelloMaui/App.xaml
@@ -1,8 +1,8 @@
+ xmlns:local="clr-namespace:HelloMaui"
+ x:Class="HelloMaui.App">
diff --git a/test/HelloWorld/App.xaml.cs b/test/HelloMaui/App.xaml.cs
similarity index 100%
rename from test/HelloWorld/App.xaml.cs
rename to test/HelloMaui/App.xaml.cs
diff --git a/test/HelloWorld/AppShell.xaml b/test/HelloMaui/AppShell.xaml
similarity index 81%
rename from test/HelloWorld/AppShell.xaml
rename to test/HelloMaui/AppShell.xaml
index a328548..8a9bd39 100644
--- a/test/HelloWorld/AppShell.xaml
+++ b/test/HelloMaui/AppShell.xaml
@@ -1,9 +1,9 @@
+
+
+ net8.0-android;net8.0-ios;net8.0-maccatalyst
+ $(TargetFrameworks);net8.0-windows10.0.19041.0
+
+
+ Exe
+ HelloWorld
+ true
+ 8.0.70
+ true
+ enable
+
+
+ HelloWorld
+
+
+ com.companyname.helloworld
+ 91c837fe-e892-450c-8365-a45127a53bc3
+
+
+ 1.0
+ 1
+
+ 11.0
+ 13.1
+ 21.0
+ 10.0.17763.0
+ 10.0.17763.0
+ 6.5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/HelloWorld/MainPage.xaml b/test/HelloMaui/MainPage.xaml
similarity index 96%
rename from test/HelloWorld/MainPage.xaml
rename to test/HelloMaui/MainPage.xaml
index 8cabec1..a9e44fd 100644
--- a/test/HelloWorld/MainPage.xaml
+++ b/test/HelloMaui/MainPage.xaml
@@ -1,7 +1,7 @@
+ x:Class="HelloMaui.MainPage">
-
+
maui-appicon-placeholder
diff --git a/test/HelloWorld/Platforms/Windows/App.xaml b/test/HelloMaui/Platforms/Windows/App.xaml
similarity index 74%
rename from test/HelloWorld/Platforms/Windows/App.xaml
rename to test/HelloMaui/Platforms/Windows/App.xaml
index 9505b19..5b15940 100644
--- a/test/HelloWorld/Platforms/Windows/App.xaml
+++ b/test/HelloMaui/Platforms/Windows/App.xaml
@@ -1,9 +1,9 @@
+ xmlns:local="using:HelloMaui.WinUI">
diff --git a/test/HelloWorld/Platforms/Windows/App.xaml.cs b/test/HelloMaui/Platforms/Windows/App.xaml.cs
similarity index 100%
rename from test/HelloWorld/Platforms/Windows/App.xaml.cs
rename to test/HelloMaui/Platforms/Windows/App.xaml.cs
diff --git a/test/HelloWorld/Platforms/Windows/Package.appxmanifest b/test/HelloMaui/Platforms/Windows/Package.appxmanifest
similarity index 100%
rename from test/HelloWorld/Platforms/Windows/Package.appxmanifest
rename to test/HelloMaui/Platforms/Windows/Package.appxmanifest
diff --git a/test/HelloWorld/Platforms/Windows/app.manifest b/test/HelloMaui/Platforms/Windows/app.manifest
similarity index 100%
rename from test/HelloWorld/Platforms/Windows/app.manifest
rename to test/HelloMaui/Platforms/Windows/app.manifest
diff --git a/test/HelloWorld/Platforms/iOS/AppDelegate.cs b/test/HelloMaui/Platforms/iOS/AppDelegate.cs
similarity index 100%
rename from test/HelloWorld/Platforms/iOS/AppDelegate.cs
rename to test/HelloMaui/Platforms/iOS/AppDelegate.cs
diff --git a/test/HelloWorld/Platforms/iOS/Info.plist b/test/HelloMaui/Platforms/iOS/Info.plist
similarity index 100%
rename from test/HelloWorld/Platforms/iOS/Info.plist
rename to test/HelloMaui/Platforms/iOS/Info.plist
diff --git a/test/HelloWorld/Platforms/iOS/Program.cs b/test/HelloMaui/Platforms/iOS/Program.cs
similarity index 100%
rename from test/HelloWorld/Platforms/iOS/Program.cs
rename to test/HelloMaui/Platforms/iOS/Program.cs
diff --git a/test/HelloWorld/Properties/launchSettings.json b/test/HelloMaui/Properties/launchSettings.json
similarity index 100%
rename from test/HelloWorld/Properties/launchSettings.json
rename to test/HelloMaui/Properties/launchSettings.json
diff --git a/test/HelloWorld/Resources/AppIcon/appicon.svg b/test/HelloMaui/Resources/AppIcon/appicon.svg
similarity index 100%
rename from test/HelloWorld/Resources/AppIcon/appicon.svg
rename to test/HelloMaui/Resources/AppIcon/appicon.svg
diff --git a/test/HelloWorld/Resources/AppIcon/appiconfg.svg b/test/HelloMaui/Resources/AppIcon/appiconfg.svg
similarity index 100%
rename from test/HelloWorld/Resources/AppIcon/appiconfg.svg
rename to test/HelloMaui/Resources/AppIcon/appiconfg.svg
diff --git a/test/HelloWorld/Resources/Fonts/OpenSans-Regular.ttf b/test/HelloMaui/Resources/Fonts/OpenSans-Regular.ttf
similarity index 100%
rename from test/HelloWorld/Resources/Fonts/OpenSans-Regular.ttf
rename to test/HelloMaui/Resources/Fonts/OpenSans-Regular.ttf
diff --git a/test/HelloWorld/Resources/Fonts/OpenSans-Semibold.ttf b/test/HelloMaui/Resources/Fonts/OpenSans-Semibold.ttf
similarity index 100%
rename from test/HelloWorld/Resources/Fonts/OpenSans-Semibold.ttf
rename to test/HelloMaui/Resources/Fonts/OpenSans-Semibold.ttf
diff --git a/test/HelloWorld/Resources/Images/dotnet_bot.svg b/test/HelloMaui/Resources/Images/dotnet_bot.svg
similarity index 100%
rename from test/HelloWorld/Resources/Images/dotnet_bot.svg
rename to test/HelloMaui/Resources/Images/dotnet_bot.svg
diff --git a/test/HelloWorld/Resources/Raw/AboutAssets.txt b/test/HelloMaui/Resources/Raw/AboutAssets.txt
similarity index 100%
rename from test/HelloWorld/Resources/Raw/AboutAssets.txt
rename to test/HelloMaui/Resources/Raw/AboutAssets.txt
diff --git a/test/HelloWorld/Resources/Splash/splash.svg b/test/HelloMaui/Resources/Splash/splash.svg
similarity index 100%
rename from test/HelloWorld/Resources/Splash/splash.svg
rename to test/HelloMaui/Resources/Splash/splash.svg
diff --git a/test/HelloWorld/Resources/Styles/Colors.xaml b/test/HelloMaui/Resources/Styles/Colors.xaml
similarity index 100%
rename from test/HelloWorld/Resources/Styles/Colors.xaml
rename to test/HelloMaui/Resources/Styles/Colors.xaml
diff --git a/test/HelloWorld/Resources/Styles/Styles.xaml b/test/HelloMaui/Resources/Styles/Styles.xaml
similarity index 100%
rename from test/HelloWorld/Resources/Styles/Styles.xaml
rename to test/HelloMaui/Resources/Styles/Styles.xaml
diff --git a/test/HelloWorld/HelloWorld.csproj b/test/HelloWorld/HelloWorld.csproj
index ce6ddb1..2f2b451 100644
--- a/test/HelloWorld/HelloWorld.csproj
+++ b/test/HelloWorld/HelloWorld.csproj
@@ -1,61 +1,14 @@
-
- net8.0-android;net8.0-ios;net8.0-maccatalyst
- $(TargetFrameworks);net8.0-windows10.0.19041.0
-
-
- Exe
- HelloWorld
- true
- 8.0.70
- true
- enable
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
-
- HelloWorld
-
-
- com.companyname.helloworld
- 91c837fe-e892-450c-8365-a45127a53bc3
-
-
- 1.0
- 1
-
- 11.0
- 13.1
- 21.0
- 10.0.17763.0
- 10.0.17763.0
- 6.5
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/HelloWorld/Program.cs b/test/HelloWorld/Program.cs
new file mode 100644
index 0000000..b1a14ce
--- /dev/null
+++ b/test/HelloWorld/Program.cs
@@ -0,0 +1,34 @@
+
+using Aptabase.Core;
+using Microsoft.Extensions.DependencyInjection;
+
+// Microsoft dependency injection semantics
+var services = new ServiceCollection();
+
+services.AddLogging();
+
+services.UseAptabase("", new AptabaseOptions
+{
+#if DEBUG
+ IsDebugMode = true,
+#else
+ IsDebugMode = false,
+#endif
+ EnableCrashReporting = false,
+ EnablePersistence = true,
+});
+
+// Build the service provider
+var serviceProvider = services.BuildServiceProvider();
+
+// Get an instance of the Aptabase service
+var aptabaseClient = serviceProvider.GetRequiredService();
+
+// Track a sample event
+await aptabaseClient.TrackEvent("HelloWorldEvent", new Dictionary
+{
+ { "Message", "Hello from Aptabase!" }
+});
+
+Console.WriteLine("Hello, World!");
+Console.ReadKey();
\ No newline at end of file