Skip to content

Commit

Permalink
ios working
Browse files Browse the repository at this point in the history
  • Loading branch information
zachdean committed Oct 24, 2024
1 parent 147187d commit d5b81aa
Show file tree
Hide file tree
Showing 20 changed files with 871 additions and 1,249 deletions.
8 changes: 3 additions & 5 deletions Bugsnag.Maui/Bugsnag.Maui.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>

<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' " >net8.0;net8.0-android</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' " >net8.0;net8.0-ios</TargetFrameworks>
<TargetFrameworks Condition=" '$(OS)' != 'Windows_NT' " >net8.0;net8.0-ios;net8.0-android</TargetFrameworks>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down Expand Up @@ -43,12 +43,10 @@
<!-- point to local projects in debug -->
<!--<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android' AND $(Configuration) == 'Debug'">-->
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<ProjectReference Include="..\Bugsnag.Android\Bugsnag.Android.csproj">
<HintPath>..\Bugsnag.Android\bin\$(Configuration)\$(TargetFramework)34\Bugsnag.Android.dll</HintPath>
</ProjectReference>
<ProjectReference Include="..\Bugsnag.Android\Bugsnag.Android.csproj" />
</ItemGroup>

<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios' AND $(Configuration) == 'Debug' AND '$(OS)' != 'Windows_NT'">
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios' AND '$(OS)' != 'Windows_NT'">
<ProjectReference Include="..\Bugsnag.iOS\Bugsnag.iOS.csproj">
<HintPath>..\Bugsnag.iOS\bin\$(Configuration)\$(TargetFramework)\Bugsnag.iOS.dll</HintPath>
</ProjectReference>
Expand Down
17 changes: 17 additions & 0 deletions Bugsnag.Maui/BugsnagBuilder.android.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using AndroidConfiguration = Com.Bugsnag.Android.Configuration;

namespace Bugsnag.Maui;

public partial class BugsnagBuilder
{
internal partial BugsnagMaui Build()
{
ArgumentException.ThrowIfNullOrEmpty(this.apiKey);

var config = new AndroidConfiguration(this.apiKey);
config.AutoDetectErrors = this.autoDetectErrors;
config.LaunchDurationMillis = this.launchDurationMillis ?? config.LaunchDurationMillis;
config.ReleaseStage = this.releaseStage.ToString().ToLowerInvariant();
return new BugsnagMaui(config);
}
}
37 changes: 37 additions & 0 deletions Bugsnag.Maui/BugsnagBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
namespace Bugsnag.Maui;

public partial class BugsnagBuilder
{
private string? apiKey;
private ReleaseStage releaseStage;
private bool autoDetectErrors = true;
private int? launchDurationMillis;

public BugsnagBuilder WithApiKey(string apiKey)
{
ArgumentException.ThrowIfNullOrEmpty(apiKey);
this.apiKey = this.apiKey;
return this;
}

public BugsnagBuilder WithReleaseStage(ReleaseStage releaseStage)
{
this.releaseStage = releaseStage;
return this;
}


public BugsnagBuilder WithAutoDetectErrors(bool autoDetectErrors)
{
this.autoDetectErrors = autoDetectErrors;
return this;
}

public BugsnagBuilder WithLaunchDurationMillis(int launchDurationMillis)
{
this.launchDurationMillis = launchDurationMillis;
return this;
}

internal partial BugsnagMaui Build();
}
18 changes: 18 additions & 0 deletions Bugsnag.Maui/BugsnagBuilder.ios.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Bugsnag.iOS;

namespace Bugsnag.Maui;

public partial class BugsnagBuilder
{
internal partial BugsnagMaui Build()
{
ArgumentException.ThrowIfNullOrEmpty(this.apiKey);

var config = new BugsnagConfiguration(this.apiKey);
config.AutoDetectErrors = this.autoDetectErrors;
config.LaunchDurationMillis = (uint?)this.launchDurationMillis ?? config.LaunchDurationMillis;
config.ReleaseStage = this.releaseStage.ToString().ToLowerInvariant();

return new BugsnagMaui(config);
}
}
11 changes: 11 additions & 0 deletions Bugsnag.Maui/BugsnagBuilder.standard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Bugsnag.Maui;

public partial class BugsnagBuilder
{
internal partial BugsnagMaui Build()
{
ArgumentException.ThrowIfNullOrEmpty(this.apiKey);

return new BugsnagMaui();
}
}
45 changes: 38 additions & 7 deletions Bugsnag.Maui/BugsnagMaui.android.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json;
using Com.Bugsnag.Android;
using Org.Json;
using AndroidBreadcrumbType = Com.Bugsnag.Android.BreadcrumbType;
using AndroidBugsnag = Com.Bugsnag.Android.Bugsnag;
Expand All @@ -8,24 +9,54 @@

namespace Bugsnag.Maui;

public partial class BugsnagMaui
public partial class BugsnagMaui : Object, IOnErrorCallback
{
private readonly AndroidConfiguration config;
private readonly BugsnagWrapper client = new();

public void Start(ReleaseStage releaseStage)
public BugsnagMaui(AndroidConfiguration config)
{
this.config = config;
this.config.AddOnError(this);
this.ConfigureErrorHandling();
}

public void Start()
{
if (AndroidBugsnag.IsStarted)
{
return;
}

var context = Platform.CurrentActivity!;
var config = new AndroidConfiguration(this.apiKey);
config.AutoDetectErrors = false;
config.LaunchDurationMillis = 0;
config.ReleaseStage = releaseStage.ToString().ToLowerInvariant();
client.Start(context, config);
}


public bool OnError(Event bugsnagEvent)
{
if (!bugsnagEvent.Unhandled
|| !(bugsnagEvent.Errors?.Count > 0)
|| !(bugsnagEvent.Errors[0].Stacktrace?.Count > 1))
{
return true;
}

// Maui Errors are handled in the Maui layer, so we do not want to send the
// native crash reports to Bugsnag. only go back 5 frames since the
// xamaerin_unhandled_exception_handler is the best indicator that the error
// was handled in the Maui layer.
var stackTrace = bugsnagEvent.Errors[0].Stacktrace;
for (int frame = 0; frame < 5; frame++)
{
if (stackTrace[frame].Method?.Contains("xamarin_unhandled_exception_handler") == true)
{
return false;
}
}

return true;
}

public void MarkLaunchCompleted()
{
Expand Down Expand Up @@ -73,7 +104,7 @@ private partial void PlatformNotify(Dictionary<string, object> report, bool unha
// Create a new JSONObject
var jsonObject = new JSONObject(reportJson);

jsonObject.Put("type", "android");
jsonObject.Put("type", "csharp");

var bugsnagEvent = client.CreateEvent(jsonObject, unhandled, false);

Expand Down
19 changes: 8 additions & 11 deletions Bugsnag.Maui/BugsnagMaui.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,20 @@

public partial class BugsnagMaui : IBugsnag
{
private string apiKey;
public void Notify(Exception exception)
{
var report = new Payload.Exception(exception);
PlatformNotify(report, false);
}

private partial void PlatformNotify(Dictionary<string, object> report, bool unhandled);

public BugsnagMaui(string apiKey)
private void ConfigureErrorHandling()
{
MauiExceptions.UnhandledException += (sender, args) =>
{
var report = new Payload.Exception((Exception)args.ExceptionObject);
PlatformNotify(report, true);
};
this.apiKey = apiKey;
}

public void Notify(Exception exception)
{
var report = new Payload.Exception(exception);
PlatformNotify(report, false);
}

private partial void PlatformNotify(Dictionary<string, object> report, bool unhandled);
}
89 changes: 74 additions & 15 deletions Bugsnag.Maui/BugsnagMaui.ios.cs
Original file line number Diff line number Diff line change
@@ -1,59 +1,118 @@
using System.Text.Json;
using Bugsnag.iOS;
using Foundation;

namespace Bugsnag.Maui;

public partial class BugsnagMaui
{
public void Start(ReleaseStage releaseStage)
private BugsnagBindingClient? bugsnagBindingClient;
private readonly BugsnagConfiguration config;

public BugsnagMaui(BugsnagConfiguration config)
{
this.config = config;
this.config.AddOnSendErrorBlock(ShouldSendError);
this.ConfigureErrorHandling();
}

public void Start()
{
if (bugsnagBindingClient != null)
{
return;
}

this.bugsnagBindingClient = new BugsnagBindingClient();
this.bugsnagBindingClient.Start(config);
}

private bool ShouldSendError(BugsnagEvent bugsnagEvent)
{
var config = new BugsnagConfiguration();
config.ApiKey = this.apiKey;
config.ReleaseStage = releaseStage.ToString().ToLowerInvariant();
config.AutoDetectErrors = true;
BugsnagBindingClient.StartBugsnagWithConfiguration(config, "0.0.0");
if (!bugsnagEvent.Unhandled
|| !(bugsnagEvent.Errors?.Length > 0)
|| !(bugsnagEvent.Errors[0].Stacktrace?.Length > 1))
{
return true;
}

// Maui Errors are handled in the Maui layer, so we do not want to send the
// native crash reports to Bugsnag. only go back 5 frames since the
// xamaerin_unhandled_exception_handler is the best indicator that the error
// was handled in the Maui layer.
var stackTrace = bugsnagEvent.Errors[0].Stacktrace;
for (int frame = 0; frame < 5; frame++)
{
if (stackTrace[frame].Method?.Contains("xamarin_unhandled_exception_handler") == true)
{
return false;
}
}

return true;
}

public void MarkLaunchCompleted()
{
BugsnagBindingClient.MarkLaunchCompleted();
this.bugsnagBindingClient?.MarkLaunchCompleted();
}

public void AddFeatureFlag(string name, string variant)
{
BugsnagBindingClient.AddFeatureFlag(name, variant);
this.bugsnagBindingClient?.AddFeatureFlag(name, variant);
}

public void ClearFeatureFlag(string name)
{
BugsnagBindingClient.ClearFeatureFlag(name);
this.bugsnagBindingClient?.ClearFeatureFlag(name);
}

public void ClearFeatureFlags()
{
BugsnagBindingClient.ClearFeatureFlags();
this.bugsnagBindingClient?.ClearFeatureFlags();
}

public void SetUser(string userId)
{
BugsnagBindingClient.SetUser(userId, null, null);
this.bugsnagBindingClient?.SetUser(userId, null, null);
}

public void LeaveBreadcrumb(string message)
{
BugsnagBindingClient.AddBreadcrumb(message, "State", null);
this.bugsnagBindingClient?.LeaveBreadcrumb(message);
}

public void LeaveBreadcrumb(string message, Dictionary<string, object> metadata)
{
BugsnagBindingClient.AddBreadcrumb(message, "State", JsonSerializer.Serialize(metadata));

this.bugsnagBindingClient?.LeaveBreadcrumb(message, ConvertJsonToNsDictionary(JsonSerializer.Serialize(metadata)), BSGBreadcrumbType.State);
}

private partial void PlatformNotify(Dictionary<string, object> report, bool unhandled)
{
if (this.bugsnagBindingClient == null)
{
return;
}



var @event = this.bugsnagBindingClient.CreateEvent(ConvertJsonToNsDictionary(JsonSerializer.Serialize(report)), unhandled, false);
this.bugsnagBindingClient.DeliverEvent(@event);
}

public static NSDictionary ConvertJsonToNsDictionary(string jsonString)
{
NSError error;
NSData jsonData = NSData.FromString(jsonString, NSStringEncoding.UTF8);
NSDictionary dictionary = (NSDictionary)NSJsonSerialization.Deserialize(jsonData, NSJsonReadingOptions.MutableContainers, out error);

if (error != null)
{
// Handle error
Console.WriteLine($"Error converting JSON to NSDictionary: {error.LocalizedDescription}");
return null;
}

return dictionary;
}

}
2 changes: 1 addition & 1 deletion Bugsnag.Maui/BugsnagMaui.standard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

public partial class BugsnagMaui
{
public void Start(ReleaseStage releaseStage) { }
public void Start() { }

public void MarkLaunchCompleted() { }

Expand Down
2 changes: 1 addition & 1 deletion Bugsnag.Maui/IBugsnag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace Bugsnag.Maui;

public interface IBugsnag
{
void Start(ReleaseStage releaseStage);
void Start();

void MarkLaunchCompleted();

Expand Down
Loading

0 comments on commit d5b81aa

Please sign in to comment.